[373577] Fix hostnames with underscores
Hostnames with underscores caused a deployment failure. Update to use a double underscore as a delimiter and provide a design validator to check that hostnames do not contain it. Closes #78 Change-Id: Ib148aed5cffe7fd8bc08441eaef8a45af6601bdd
This commit is contained in:
parent
b138b3c179
commit
3b41868802
@ -227,6 +227,7 @@ reference to the particular physical node. The ``BaremetalNode`` definition will
|
||||
reference a ``HostProfile`` and can then extend or override any of the
|
||||
configuration values.
|
||||
|
||||
NOTE: Drydock does not support hostnames containing '__' (double underscoe)
|
||||
|
||||
Hardware Profile
|
||||
----------------
|
||||
|
@ -660,7 +660,9 @@ class ConfigureUserCredentials(BaseMaasAction):
|
||||
if key_list:
|
||||
for k in key_list:
|
||||
try:
|
||||
if len(current_keys.query({'key': k.replace("\n", "")})) == 0:
|
||||
if len(current_keys.query({
|
||||
'key': k.replace("\n", "")
|
||||
})) == 0:
|
||||
new_key = maas_keys.SshKey(self.maas_client, key=k)
|
||||
new_key = current_keys.add(new_key)
|
||||
msg = "Added SSH key %s to MaaS user profile. Will be installed on all deployed nodes." % (
|
||||
@ -1814,7 +1816,8 @@ class ApplyNodeStorage(BaseMaasAction):
|
||||
raise errors.NotEnoughStorage()
|
||||
|
||||
if match.group(1) == '>':
|
||||
computed_size = int(context.available_size) - ApplyNodeStorage.PART_TABLE_RESERVATION
|
||||
computed_size = int(context.available_size
|
||||
) - ApplyNodeStorage.PART_TABLE_RESERVATION
|
||||
|
||||
return computed_size
|
||||
|
||||
@ -1919,7 +1922,7 @@ class DeployNode(BaseMaasAction):
|
||||
|
||||
tag_list = maas_tag.Tags(self.maas_client)
|
||||
tag_list.refresh()
|
||||
node_id_tags = tag_list.startswith("%s_baid-" % (n.name))
|
||||
node_id_tags = tag_list.startswith("%s__baid__" % (n.name))
|
||||
for t in node_id_tags:
|
||||
t.delete()
|
||||
|
||||
@ -1929,7 +1932,7 @@ class DeployNode(BaseMaasAction):
|
||||
self.logger.debug(msg)
|
||||
node_baid_tag = maas_tag.Tag(
|
||||
self.maas_client,
|
||||
name="%s_baid-%s" % (n.name, ba_key.hex()))
|
||||
name="%s__baid__%s" % (n.name, ba_key.hex()))
|
||||
node_baid_tag = tag_list.add(node_baid_tag)
|
||||
node_baid_tag.apply_to_node(machine.resource_id)
|
||||
self.task.add_status_msg(
|
||||
|
@ -24,6 +24,7 @@ from bson import BSON
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Machine(model_base.ResourceBase):
|
||||
|
||||
resource_url = 'machines/{resource_id}/'
|
||||
|
@ -0,0 +1,32 @@
|
||||
# Copyright 2018 AT&T Intellectual Property. All other rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
from drydock_provisioner.orchestrator.validations.validators import Validators
|
||||
|
||||
|
||||
class HostnameValidity(Validators):
|
||||
def __init__(self):
|
||||
super().__init__('Hostname Validity', 'DD3003')
|
||||
|
||||
def run_validation(self, site_design, orchestrator=None):
|
||||
"""Validate that node hostnames do not contain '__' """
|
||||
node_list = site_design.baremetal_nodes or []
|
||||
|
||||
invalid_nodes = [n for n in node_list if '__' in n.name]
|
||||
|
||||
for n in invalid_nodes:
|
||||
msg = "Hostname %s invalid." % n.name
|
||||
self.report_error(
|
||||
msg, [n.doc_ref],
|
||||
"Hostnames cannot contain '__' (double underscore)")
|
||||
return
|
@ -27,6 +27,7 @@ from drydock_provisioner.orchestrator.validations.rational_network_bond import R
|
||||
from drydock_provisioner.orchestrator.validations.storage_partititioning import StoragePartitioning
|
||||
from drydock_provisioner.orchestrator.validations.storage_sizing import StorageSizing
|
||||
from drydock_provisioner.orchestrator.validations.unique_network_check import UniqueNetworkCheck
|
||||
from drydock_provisioner.orchestrator.validations.hostname_validity import HostnameValidity
|
||||
|
||||
|
||||
class Validator():
|
||||
@ -86,4 +87,5 @@ rule_set = [
|
||||
StoragePartitioning(),
|
||||
StorageSizing(),
|
||||
UniqueNetworkCheck(),
|
||||
HostnameValidity(),
|
||||
]
|
||||
|
@ -282,8 +282,8 @@ class DrydockState(object):
|
||||
"""
|
||||
try:
|
||||
conn = self.db_engine.connect()
|
||||
query = self.tasks_tbl.insert().values(**(
|
||||
task.to_db(include_id=True)))
|
||||
query = self.tasks_tbl.insert().values(
|
||||
**(task.to_db(include_id=True)))
|
||||
conn.execute(query)
|
||||
conn.close()
|
||||
return True
|
||||
|
64
tests/unit/test_validation_rule_hostname_validity.py
Normal file
64
tests/unit/test_validation_rule_hostname_validity.py
Normal file
@ -0,0 +1,64 @@
|
||||
# Copyright 2017 AT&T Intellectual Property. All other rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
"""Test Validation Rule Hostname Validity"""
|
||||
|
||||
import logging
|
||||
|
||||
from drydock_provisioner.orchestrator.orchestrator import Orchestrator
|
||||
from drydock_provisioner.orchestrator.validations.hostname_validity import HostnameValidity
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class TestHostnameValidity(object):
|
||||
def test_hostname(self, mocker, deckhand_ingester, drydock_state,
|
||||
input_files):
|
||||
input_file = input_files.join("validation.yaml")
|
||||
design_ref = "file://%s" % str(input_file)
|
||||
|
||||
orch = Orchestrator(
|
||||
state_manager=drydock_state, ingester=deckhand_ingester)
|
||||
|
||||
status, site_design = Orchestrator.get_effective_site(orch, design_ref)
|
||||
|
||||
validator = HostnameValidity()
|
||||
message_list = validator.execute(site_design, orchestrator=orch)
|
||||
msg = message_list[0].to_dict()
|
||||
|
||||
assert 'Hostname' in msg.get('message')
|
||||
assert msg.get('error') is False
|
||||
assert len(message_list) == 1
|
||||
|
||||
def test_invalid_hostname(self, mocker, deckhand_ingester, drydock_state,
|
||||
input_files):
|
||||
|
||||
input_file = input_files.join("invalid_validation.yaml")
|
||||
design_ref = "file://%s" % str(input_file)
|
||||
|
||||
orch = Orchestrator(
|
||||
state_manager=drydock_state, ingester=deckhand_ingester)
|
||||
|
||||
status, site_design = Orchestrator.get_effective_site(orch, design_ref)
|
||||
|
||||
validator = HostnameValidity()
|
||||
message_list = validator.execute(site_design, orchestrator=orch)
|
||||
|
||||
for msg in message_list:
|
||||
msg = msg.to_dict()
|
||||
LOG.debug(msg)
|
||||
assert msg.get('error')
|
||||
assert len(msg.get('documents')) > 0
|
||||
assert "bad__name" in msg.get('message')
|
||||
|
||||
assert len(message_list) == 1
|
@ -358,7 +358,9 @@ data:
|
||||
schema: 'drydock/BaremetalNode/v1'
|
||||
metadata:
|
||||
schema: 'metadata/Document/v1'
|
||||
name: compute01
|
||||
#####
|
||||
# Invalid hostname contains '__'
|
||||
name: bad__name
|
||||
storagePolicy: 'cleartext'
|
||||
labels:
|
||||
application: 'drydock'
|
||||
|
Loading…
x
Reference in New Issue
Block a user