Node naming validations
- Update the hostname validator account for the FQDN Change-Id: If59eb5d5d351e2251cf881492b46e109111c91ec
This commit is contained in:
parent
89ce941202
commit
e044575e05
|
@ -203,9 +203,10 @@ class SiteDesign(base.DrydockPersistentObject, base.DrydockObject):
|
||||||
self.networks.append(new_network)
|
self.networks.append(new_network)
|
||||||
|
|
||||||
def get_network(self, network_key):
|
def get_network(self, network_key):
|
||||||
for n in self.networks:
|
if self.networks:
|
||||||
if n.get_id() == network_key:
|
for n in self.networks:
|
||||||
return n
|
if n.get_id() == network_key:
|
||||||
|
return n
|
||||||
|
|
||||||
raise errors.DesignError(
|
raise errors.DesignError(
|
||||||
"Network %s not found in design state" % network_key)
|
"Network %s not found in design state" % network_key)
|
||||||
|
@ -220,9 +221,10 @@ class SiteDesign(base.DrydockPersistentObject, base.DrydockObject):
|
||||||
self.network_links.append(new_network_link)
|
self.network_links.append(new_network_link)
|
||||||
|
|
||||||
def get_network_link(self, link_key):
|
def get_network_link(self, link_key):
|
||||||
for l in self.network_links:
|
if self.network_links:
|
||||||
if l.get_id() == link_key:
|
for l in self.network_links:
|
||||||
return l
|
if l.get_id() == link_key:
|
||||||
|
return l
|
||||||
|
|
||||||
raise errors.DesignError(
|
raise errors.DesignError(
|
||||||
"NetworkLink %s not found in design state" % link_key)
|
"NetworkLink %s not found in design state" % link_key)
|
||||||
|
@ -237,9 +239,10 @@ class SiteDesign(base.DrydockPersistentObject, base.DrydockObject):
|
||||||
self.racks.append(new_rack)
|
self.racks.append(new_rack)
|
||||||
|
|
||||||
def get_rack(self, rack_key):
|
def get_rack(self, rack_key):
|
||||||
for r in self.racks:
|
if self.racks:
|
||||||
if r.get_id() == rack_key:
|
for r in self.racks:
|
||||||
return r
|
if r.get_id() == rack_key:
|
||||||
|
return r
|
||||||
raise errors.DesignError(
|
raise errors.DesignError(
|
||||||
"Rack %s not found in design state" % rack_key)
|
"Rack %s not found in design state" % rack_key)
|
||||||
|
|
||||||
|
@ -258,9 +261,10 @@ class SiteDesign(base.DrydockPersistentObject, base.DrydockObject):
|
||||||
|
|
||||||
:param ba_key: Value should match the ``get_id()`` value of the BootAction returned
|
:param ba_key: Value should match the ``get_id()`` value of the BootAction returned
|
||||||
"""
|
"""
|
||||||
for ba in self.bootactions:
|
if self.bootactions:
|
||||||
if ba.get_id() == ba_key:
|
for ba in self.bootactions:
|
||||||
return ba
|
if ba.get_id() == ba_key:
|
||||||
|
return ba
|
||||||
raise errors.DesignError(
|
raise errors.DesignError(
|
||||||
"BootAction %s not found in design state" % ba_key)
|
"BootAction %s not found in design state" % ba_key)
|
||||||
|
|
||||||
|
@ -274,9 +278,10 @@ class SiteDesign(base.DrydockPersistentObject, base.DrydockObject):
|
||||||
self.host_profiles.append(new_host_profile)
|
self.host_profiles.append(new_host_profile)
|
||||||
|
|
||||||
def get_host_profile(self, profile_key):
|
def get_host_profile(self, profile_key):
|
||||||
for p in self.host_profiles:
|
if self.host_profiles:
|
||||||
if p.get_id() == profile_key:
|
for p in self.host_profiles:
|
||||||
return p
|
if p.get_id() == profile_key:
|
||||||
|
return p
|
||||||
|
|
||||||
raise errors.DesignError(
|
raise errors.DesignError(
|
||||||
"HostProfile %s not found in design state" % profile_key)
|
"HostProfile %s not found in design state" % profile_key)
|
||||||
|
@ -291,9 +296,10 @@ class SiteDesign(base.DrydockPersistentObject, base.DrydockObject):
|
||||||
self.hardware_profiles.append(new_hardware_profile)
|
self.hardware_profiles.append(new_hardware_profile)
|
||||||
|
|
||||||
def get_hardware_profile(self, profile_key):
|
def get_hardware_profile(self, profile_key):
|
||||||
for p in self.hardware_profiles:
|
if self.hardware_profiles:
|
||||||
if p.get_id() == profile_key:
|
for p in self.hardware_profiles:
|
||||||
return p
|
if p.get_id() == profile_key:
|
||||||
|
return p
|
||||||
|
|
||||||
raise errors.DesignError(
|
raise errors.DesignError(
|
||||||
"HardwareProfile %s not found in design state" % profile_key)
|
"HardwareProfile %s not found in design state" % profile_key)
|
||||||
|
@ -308,9 +314,10 @@ class SiteDesign(base.DrydockPersistentObject, base.DrydockObject):
|
||||||
self.baremetal_nodes.append(new_baremetal_node)
|
self.baremetal_nodes.append(new_baremetal_node)
|
||||||
|
|
||||||
def get_baremetal_node(self, node_key):
|
def get_baremetal_node(self, node_key):
|
||||||
for n in self.baremetal_nodes:
|
if self.baremetal_nodes:
|
||||||
if n.get_id() == node_key:
|
for n in self.baremetal_nodes:
|
||||||
return n
|
if n.get_id() == node_key:
|
||||||
|
return n
|
||||||
|
|
||||||
raise errors.DesignError(
|
raise errors.DesignError(
|
||||||
"BaremetalNode %s not found in design state" % node_key)
|
"BaremetalNode %s not found in design state" % node_key)
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
import re
|
||||||
|
|
||||||
from drydock_provisioner.orchestrator.validations.validators import Validators
|
from drydock_provisioner.orchestrator.validations.validators import Validators
|
||||||
|
|
||||||
|
|
||||||
|
@ -19,14 +21,32 @@ class HostnameValidity(Validators):
|
||||||
super().__init__('Hostname Validity', 'DD3003')
|
super().__init__('Hostname Validity', 'DD3003')
|
||||||
|
|
||||||
def run_validation(self, site_design, orchestrator=None):
|
def run_validation(self, site_design, orchestrator=None):
|
||||||
"""Validate that node hostnames do not contain '__' """
|
# Check FQDN length is <= 255 characters per RFC 1035
|
||||||
node_list = site_design.baremetal_nodes or []
|
|
||||||
|
|
||||||
invalid_nodes = [n for n in node_list if '__' in n.name]
|
node_list = site_design.baremetal_nodes or []
|
||||||
|
invalid_nodes = [
|
||||||
|
n for n in node_list if len(n.get_fqdn(site_design)) > 255
|
||||||
|
]
|
||||||
|
|
||||||
for n in invalid_nodes:
|
for n in invalid_nodes:
|
||||||
msg = "Hostname %s invalid." % n.name
|
msg = "FQDN %s is invalid, greater than 255 characters." % n.get_fqdn(
|
||||||
|
site_design)
|
||||||
self.report_error(
|
self.report_error(
|
||||||
msg, [n.doc_ref],
|
msg, [n.doc_ref],
|
||||||
"Hostnames cannot contain '__' (double underscore)")
|
"RFC 1035 requires full DNS names to be < 256 characters.")
|
||||||
return
|
|
||||||
|
# Check each label in the domain name is <= 63 characters per RFC 1035
|
||||||
|
# and only contains A-Z,a-z,0-9,-
|
||||||
|
|
||||||
|
valid_label = re.compile('[a-z0-9-]{1,63}', flags=re.I)
|
||||||
|
|
||||||
|
for n in node_list:
|
||||||
|
domain_labels = n.get_fqdn(site_design).split('.')
|
||||||
|
for l in domain_labels:
|
||||||
|
if not valid_label.fullmatch(l):
|
||||||
|
msg = "FQDN %s is invalid - label '%s' is invalid." % (
|
||||||
|
n.get_fqdn(site_design), l)
|
||||||
|
self.report_error(
|
||||||
|
msg, [n.doc_ref],
|
||||||
|
"RFC 1035 requires each label in a DNS name to be <= 63 characters and contain "
|
||||||
|
"only A-Z, a-z, 0-9, and hyphens.")
|
||||||
|
|
|
@ -54,11 +54,13 @@ class TestHostnameValidity(object):
|
||||||
validator = HostnameValidity()
|
validator = HostnameValidity()
|
||||||
message_list = validator.execute(site_design, orchestrator=orch)
|
message_list = validator.execute(site_design, orchestrator=orch)
|
||||||
|
|
||||||
|
long_label = "sitenameisverylongsoitshouldbeinvalidperrfcifikeepaddingoctetsafewmore"
|
||||||
for msg in message_list:
|
for msg in message_list:
|
||||||
msg = msg.to_dict()
|
msg = msg.to_dict()
|
||||||
LOG.debug(msg)
|
LOG.debug(msg)
|
||||||
assert msg.get('error')
|
assert msg.get('error')
|
||||||
assert len(msg.get('documents')) > 0
|
assert len(msg.get('documents')) > 0
|
||||||
assert "bad__name" in msg.get('message')
|
assert "bad__name" in msg.get('message') or long_label in msg.get(
|
||||||
|
'message')
|
||||||
|
|
||||||
assert len(message_list) == 1
|
assert len(message_list) > 1
|
||||||
|
|
|
@ -182,7 +182,7 @@ data:
|
||||||
gateway: 141.16.1.1
|
gateway: 141.16.1.1
|
||||||
metric: 10
|
metric: 10
|
||||||
dns:
|
dns:
|
||||||
domain: mgmt.sitename.example.com
|
domain: mgmt.sitenameisverylongsoitshouldbeinvalidperrfcifikeepaddingoctetsafewmore.example.com
|
||||||
servers: 172.16.1.9,172.16.1.10
|
servers: 172.16.1.9,172.16.1.10
|
||||||
---
|
---
|
||||||
schema: 'drydock/Network/v1'
|
schema: 'drydock/Network/v1'
|
||||||
|
|
Loading…
Reference in New Issue