Пример #1
0
        public void Validate(ClusterDefinition clusterDefinition)
        {
            Covenant.Requires <ArgumentNullException>(clusterDefinition != null, nameof(clusterDefinition));

            switch (Environment)
            {
            case HostingEnvironments.Aws:

                if (Aws == null)
                {
                    throw new ClusterDefinitionException($"[{nameof(HostingOptions)}.{nameof(Aws)}] must be initialized when cloud provider is [{Environment}].");
                }

                Aws.Validate(clusterDefinition);
                break;

            case HostingEnvironments.Azure:

                if (Azure == null)
                {
                    throw new ClusterDefinitionException($"[{nameof(HostingOptions)}.{nameof(Azure)}] must be initialized when cloud provider is [{Environment}].");
                }

                Azure.Validate(clusterDefinition);
                break;

            case HostingEnvironments.Google:

                if (Google == null)
                {
                    throw new ClusterDefinitionException($"[{nameof(HostingOptions)}.{nameof(Google)}] must be initialized when cloud provider is [{Environment}].");
                }

                Google.Validate(clusterDefinition);
                break;

            case HostingEnvironments.HyperV:

                HyperV = HyperV ?? new HyperVOptions();

                HyperV.Validate(clusterDefinition);
                break;

            case HostingEnvironments.HyperVLocal:

                HyperVDev = HyperVDev ?? new LocalHyperVOptions();

                HyperVDev.Validate(clusterDefinition);
                break;

            case HostingEnvironments.Machine:

                Machine = Machine ?? new MachineOptions();

                Machine.Validate(clusterDefinition);
                break;

            case HostingEnvironments.XenServer:

                XenServer = XenServer ?? new XenServerOptions();

                XenServer.Validate(clusterDefinition);
                break;

            default:

                throw new NotImplementedException();
            }

            if (!string.IsNullOrWhiteSpace(VmNamePrefix))
            {
                if (!ClusterDefinition.IsValidName(VmNamePrefix))
                {
                    throw new ClusterDefinitionException($"[{nameof(HostingOptions)}.{nameof(VmNamePrefix)}={VmNamePrefix}] must include only letters, digits, underscores, or periods.");
                }
            }
        }
Пример #2
0
        /// <summary>
        /// Validates the node definition.
        /// </summary>
        /// <param name="clusterDefinition">The cluster definition.</param>
        /// <exception cref="ArgumentException">Thrown if the definition is not valid.</exception>
        public void Validate(ClusterDefinition clusterDefinition)
        {
            Covenant.Requires <ArgumentNullException>(clusterDefinition != null, nameof(clusterDefinition));

            Vm = Vm ?? new VmNodeOptions();

            var nodeDefinitionPrefix = $"{nameof(ClusterDefinition.NodeDefinitions)}";

            // Ensure that the labels are wired up to the parent node.

            if (Labels == null)
            {
                Labels = new NodeLabels(this);
            }
            else
            {
                Labels.Node = this;
            }

            if (Name == null)
            {
                throw new ClusterDefinitionException($"The [{nodeDefinitionPrefix}.{nameof(Name)}] property is required.");
            }

            if (!ClusterDefinition.IsValidName(Name))
            {
                throw new ClusterDefinitionException($"The [{nodeDefinitionPrefix}.{nameof(Name)}={Name}] property is not valid.  Only letters, numbers, periods, dashes, and underscores are allowed.");
            }

            if (name == "localhost")
            {
                throw new ClusterDefinitionException($"The [{nodeDefinitionPrefix}.{nameof(Name)}={Name}] property is not valid.  [localhost] is reserved.");
            }

            if (Name.StartsWith("neon-", StringComparison.InvariantCultureIgnoreCase) && !clusterDefinition.IsSpecialNeonCluster)
            {
                throw new ClusterDefinitionException($"The [{nodeDefinitionPrefix}.{nameof(Name)}={Name}] property is not valid because node names starting with [neon-] are reserved.");
            }

            if (name.Equals("cluster", StringComparison.InvariantCultureIgnoreCase))
            {
                // $hack(jefflill):
                //
                // The node name [cluster] is reserved because we want to persist the
                // global cluster log file as [cluster.log] and we don't want this to
                // conflict with any of the node log files.
                //
                // See: KubeConst.ClusterSetupLogName

                throw new ClusterDefinitionException($"The [{nodeDefinitionPrefix}.{nameof(Name)}={Name}] property is not valid because the node name [cluster] is reserved.");
            }

            if (string.IsNullOrEmpty(Role))
            {
                Role = NodeRole.Worker;
            }

            if (!Role.Equals(NodeRole.ControlPlane, StringComparison.InvariantCultureIgnoreCase) && !Role.Equals(NodeRole.Worker, StringComparison.InvariantCultureIgnoreCase))
            {
                throw new ClusterDefinitionException($"[{nodeDefinitionPrefix}.{nameof(Name)}={Name}] has invalid [{nameof(Role)}={Role}].  This must be [{NodeRole.ControlPlane}] or [{NodeRole.Worker}].");
            }

            // We don't need to check the node address for cloud providers.

            if (clusterDefinition.Hosting.IsOnPremiseProvider)
            {
                if (string.IsNullOrEmpty(Address))
                {
                    throw new ClusterDefinitionException($"[{nodeDefinitionPrefix}.{nameof(Name)}={Name}] requires [{nameof(Address)}] when hosting in an on-premise facility.");
                }

                if (!NetHelper.TryParseIPv4Address(Address, out var nodeAddress))
                {
                    throw new ClusterDefinitionException($"[{nodeDefinitionPrefix}.{nameof(Name)}={Name}] has invalid IP address [{Address}].");
                }
            }

            switch (clusterDefinition.Hosting.Environment)
            {
            case HostingEnvironment.Aws:

                Aws = Aws ?? new AwsNodeOptions();
                Aws.Validate(clusterDefinition, this.Name);
                break;

            case HostingEnvironment.Azure:

                Azure = Azure ?? new AzureNodeOptions();
                Azure.Validate(clusterDefinition, this.Name);
                break;

            case HostingEnvironment.BareMetal:

                // No machine options to check at this time.
                break;

            case HostingEnvironment.Google:

                // $todo(jefflill: Implement this
                break;

            case HostingEnvironment.HyperV:
            case HostingEnvironment.XenServer:

                Vm = Vm ?? new VmNodeOptions();
                Vm.Validate(clusterDefinition, this.Name);
                break;

            default:

                throw new NotImplementedException($"Hosting environment [{clusterDefinition.Hosting.Environment}] hosting option check is not implemented.");
            }
        }
Пример #3
0
        /// <summary>
        /// Validates the options and also ensures that all <c>null</c> properties are
        /// initialized to their default values.
        /// </summary>
        /// <param name="clusterDefinition">The cluster definition.</param>
        /// <exception cref="ClusterDefinitionException">Thrown if the definition is not valid.</exception>
        public void Validate(ClusterDefinition clusterDefinition)
        {
            Covenant.Requires <ArgumentNullException>(clusterDefinition != null, nameof(clusterDefinition));

            var vmHostingOptionsPrefix = $"{nameof(ClusterDefinition.Hosting)}";

            // Validate the VM name prefix.

            if (!string.IsNullOrWhiteSpace(NamePrefix))
            {
                if (!ClusterDefinition.IsValidName(NamePrefix))
                {
                    throw new ClusterDefinitionException($"[{nameof(HostingOptions)}.{nameof(NamePrefix)}={NamePrefix}] must include only letters, digits, underscores, or periods.");
                }
            }

            if (Cores <= 0)
            {
                throw new ClusterDefinitionException($"[{nameof(HyperVHostingOptions)}.{nameof(Cores)}={Cores}] must be positive.");
            }

            Memory = Memory ?? DefaultMemory;
            OsDisk = OsDisk ?? DefaultOsDisk;
            Hosts  = Hosts ?? new List <HypervisorHost>();

            ClusterDefinition.ValidateSize(Memory, this.GetType(), $"{vmHostingOptionsPrefix}.{nameof(Memory)}");
            ClusterDefinition.ValidateSize(OsDisk, this.GetType(), $"{vmHostingOptionsPrefix}.{nameof(OsDisk)}");
            ClusterDefinition.ValidateSize(OpenEbsDisk, this.GetType(), $"{vmHostingOptionsPrefix}.{nameof(OpenEbsDisk)}");

            // Verify that the hypervisor host machines have unique names and addresses.

            var hostNameSet    = new HashSet <string>(StringComparer.InvariantCultureIgnoreCase);
            var hostAddressSet = new HashSet <string>(StringComparer.InvariantCultureIgnoreCase);

            foreach (var vmHost in clusterDefinition.Hosting.Vm.Hosts)
            {
                if (hostNameSet.Contains(vmHost.Name))
                {
                    throw new ClusterDefinitionException($"One or more hypervisor hosts are assigned the [{vmHost.Name}] name.");
                }

                hostNameSet.Add(vmHost.Name);

                if (hostAddressSet.Contains(vmHost.Address))
                {
                    throw new ClusterDefinitionException($"One or more hypervisor hosts are assigned the [{vmHost.Address}] address.");
                }

                hostAddressSet.Add(vmHost.Address);
            }

            // Ensure that some hypervisor hosts have been specified if we're deploying
            // to remote hypervisors.

            if (clusterDefinition.Hosting.IsHostedHypervisor)
            {
                foreach (var vmHost in Hosts)
                {
                    vmHost.Validate(clusterDefinition);
                }
            }
        }
Пример #4
0
        public void Validate(ClusterDefinition clusterDefinition)
        {
            Covenant.Requires <ArgumentNullException>(clusterDefinition != null);

            // Ensure that the labels are wired up to the parent node.

            if (Labels == null)
            {
                Labels = new NodeLabels(this);
            }
            else
            {
                Labels.Node = this;
            }

            if (Name == null)
            {
                throw new ClusterDefinitionException($"The [{nameof(NodeDefinition)}.{nameof(Name)}] property is required.");
            }

            if (!ClusterDefinition.IsValidName(Name))
            {
                throw new ClusterDefinitionException($"The [{nameof(NodeDefinition)}.{nameof(Name)}={Name}] property is not valid.  Only letters, numbers, periods, dashes, and underscores are allowed.");
            }

            if (name == "localhost")
            {
                throw new ClusterDefinitionException($"The [{nameof(NodeDefinition)}.{nameof(Name)}={Name}] property is not valid.  [localhost] is reserved.");
            }

            if (Name.StartsWith("neon-", StringComparison.InvariantCultureIgnoreCase))
            {
                throw new ClusterDefinitionException($"The [{nameof(NodeDefinition)}.{nameof(Name)}={Name}] property is not valid because node names starting with [node-] are reserved.");
            }

            if (clusterDefinition.Hosting.IsOnPremiseProvider)
            {
                if (string.IsNullOrEmpty(PrivateAddress))
                {
                    throw new ClusterDefinitionException($"Node [{Name}] requires [{nameof(PrivateAddress)}] when hosting in an on-premise facility.");
                }

                if (!IPAddress.TryParse(PrivateAddress, out var nodeAddress))
                {
                    throw new ClusterDefinitionException($"Node [{Name}] has invalid IP address [{PrivateAddress}].");
                }
            }

            if (Azure != null)
            {
                Azure.Validate(clusterDefinition, this.Name);
            }

            if (clusterDefinition.Hosting.IsRemoteHypervisorProvider)
            {
                if (string.IsNullOrEmpty(VmHost))
                {
                    throw new ClusterDefinitionException($"Node [{Name}] does not specify a hypervisor [{nameof(NodeDefinition)}.{nameof(NodeDefinition.VmHost)}].");
                }
                else if (clusterDefinition.Hosting.VmHosts.FirstOrDefault(h => h.Name.Equals(VmHost, StringComparison.InvariantCultureIgnoreCase)) == null)
                {
                    throw new ClusterDefinitionException($"Node [{Name}] references hypervisor [{VmHost}] which is defined in [{nameof(HostingOptions)}={nameof(HostingOptions.VmHosts)}].");
                }
            }

            if (VmMemory != null)
            {
                ClusterDefinition.ValidateSize(VmMemory, this.GetType(), nameof(VmMemory));
            }

            if (VmDisk != null)
            {
                ClusterDefinition.ValidateSize(VmDisk, this.GetType(), nameof(VmDisk));
            }
        }