From daf94bdeace0473cec68884378ce9103febbf636 Mon Sep 17 00:00:00 2001 From: Scott Hussey Date: Mon, 6 Aug 2018 08:50:56 -0500 Subject: [PATCH] Add DNS domains during network config - Node domains must be added to MAAS before assigning them to any domain. These domains can be added as the network they are assigned to is configured. Change-Id: I4a10cc7779b74dd79b8ad4602ae0f9050081d6d4 --- drydock_provisioner/control/tasks.py | 3 +- .../drivers/node/maasdriver/actions/node.py | 32 +++++++++++++------ .../drivers/node/maasdriver/models/domain.py | 31 ++++++++++++++++++ drydock_provisioner/objects/bootaction.py | 1 + tests/unit/test_bootaction_asset_render.py | 17 ++++++++++ 5 files changed, 73 insertions(+), 11 deletions(-) create mode 100644 drydock_provisioner/drivers/node/maasdriver/models/domain.py diff --git a/drydock_provisioner/control/tasks.py b/drydock_provisioner/control/tasks.py index 086e2d68..700109e7 100644 --- a/drydock_provisioner/control/tasks.py +++ b/drydock_provisioner/control/tasks.py @@ -398,7 +398,8 @@ class TaskBuilddataResource(StatefulResource): @policy.ApiEnforcer('physical_provisioner:read_build_data') def on_get(self, req, resp, task_id): try: - bd_list = self.state_manager.get_build_data(task_id=uuid.UUID(task_id)) + bd_list = self.state_manager.get_build_data( + task_id=uuid.UUID(task_id)) if not bd_list: resp.status = falcon.HTTP_404 return diff --git a/drydock_provisioner/drivers/node/maasdriver/actions/node.py b/drydock_provisioner/drivers/node/maasdriver/actions/node.py index 2535af01..a12045d0 100644 --- a/drydock_provisioner/drivers/node/maasdriver/actions/node.py +++ b/drydock_provisioner/drivers/node/maasdriver/actions/node.py @@ -41,6 +41,7 @@ import drydock_provisioner.drivers.node.maasdriver.models.rack_controller as maa import drydock_provisioner.drivers.node.maasdriver.models.partition as maas_partition import drydock_provisioner.drivers.node.maasdriver.models.volumegroup as maas_vg import drydock_provisioner.drivers.node.maasdriver.models.repository as maas_repo +import drydock_provisioner.drivers.node.maasdriver.models.domain as maas_domain class BaseMaasAction(BaseAction): @@ -64,8 +65,8 @@ class BaseMaasAction(BaseAction): data_format='text/plain', data_element=r.get_decoded_data()) self.state_manager.post_build_data(bd) - log_href = "%s/tasks/%s/builddata" % ( - get_internal_api_href("v1.0"), str(self.task.task_id)) + log_href = "%s/tasks/%s/builddata" % (get_internal_api_href("v1.0"), + str(self.task.task_id)) self.task.result.add_link('detail_logs', log_href) self.task.save() @@ -425,6 +426,9 @@ class CreateNetworkTemplate(BaseMaasAction): subnets = maas_subnet.Subnets(self.maas_client) subnets.refresh() + domains = maas_domain.Domains(self.maas_client) + domains.refresh() + for l in design_links: if l.metalabels is not None: # TODO(sh8121att): move metalabels into config @@ -508,6 +512,18 @@ class CreateNetworkTemplate(BaseMaasAction): continue try: + domain = domains.singleton({'name': n.dns_domain}) + + if not domain: + self.logger.info( + 'Network domain not found, adding: %s', + n.dns_domain) + domain = maas_domain.Domain( + self.maas_client, + name=n.dns_domain, + authoritative=False) + domain = domains.add(domain) + subnet = subnets.singleton({'cidr': n.cidr}) if subnet is None: @@ -1042,8 +1058,8 @@ class IdentifyNode(BaseMaasAction): for n in nodes: try: - machine = machine_list.identify_baremetal_node(n, - domain=n.get_domain(site_design)) + machine = machine_list.identify_baremetal_node( + n, domain=n.get_domain(site_design)) if machine is not None: self.task.success(focus=n.get_id()) self.task.add_status_msg( @@ -1176,10 +1192,7 @@ class ConfigureHardware(BaseMaasAction): 'commission', result_type='commissioning') self._add_detail_logs( - n, - machine, - 'testing', - result_type='testing') + n, machine, 'testing', result_type='testing') elif machine.status_name in ['Commissioning', 'Testing']: msg = "Located node %s in MaaS, node already being commissioned. Skipping..." % ( n.name) @@ -2333,8 +2346,7 @@ class DeployNode(BaseMaasAction): self.task.add_status_msg( msg=msg, error=True, ctx=n.name, ctx_type='node') self.task.failure(focus=n.get_id()) - self._add_detail_logs( - n, machine, 'deploy', result_type='deploy') + self._add_detail_logs(n, machine, 'deploy', result_type='deploy') self.task.set_status(hd_fields.TaskStatus.Complete) self.task.save() diff --git a/drydock_provisioner/drivers/node/maasdriver/models/domain.py b/drydock_provisioner/drivers/node/maasdriver/models/domain.py new file mode 100644 index 00000000..9f8360e0 --- /dev/null +++ b/drydock_provisioner/drivers/node/maasdriver/models/domain.py @@ -0,0 +1,31 @@ +# 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. +"""Model representing MaaS DNS domain resource.""" + +import drydock_provisioner.drivers.node.maasdriver.models.base as model_base + + +class Domain(model_base.ResourceBase): + """Model for single domain.""" + + resource_url = 'domains/{resource_id}/' + fields = ['resource_id', 'name', 'authoritative', 'ttl'] + json_fields = ['name', 'authoritative', 'ttl'] + + +class Domains(model_base.ResourceCollectionBase): + """Model for a collection of static routes.""" + + collection_url = 'domains/' + collection_resource = Domain diff --git a/drydock_provisioner/objects/bootaction.py b/drydock_provisioner/objects/bootaction.py index 7ba36594..f21192d4 100644 --- a/drydock_provisioner/objects/bootaction.py +++ b/drydock_provisioner/objects/bootaction.py @@ -240,6 +240,7 @@ class BootActionAsset(base.DrydockObject): node = site_design.get_baremetal_node(nodename) return dict( hostname=nodename, + domain=node.get_domain(site_design), tags=[t for t in node.tags], labels={k: v for (k, v) in node.owner_data.items()}, diff --git a/tests/unit/test_bootaction_asset_render.py b/tests/unit/test_bootaction_asset_render.py index aed18e88..02de7f6c 100644 --- a/tests/unit/test_bootaction_asset_render.py +++ b/tests/unit/test_bootaction_asset_render.py @@ -90,3 +90,20 @@ class TestBootactionRenderAction(object): assert 'bond0' in iface_ctx assert iface_ctx['bond0'].get('sriov') assert iface_ctx['bond0'].get('vf_count') == 2 + + def test_bootaction_node_domain(self, input_files, deckhand_orchestrator, + setup): + """Test that a boot action creates proper node domain.""" + input_file = input_files.join("deckhand_fullsite.yaml") + + design_ref = "file://%s" % str(input_file) + + design_status, design_data = deckhand_orchestrator.get_effective_site( + design_ref) + + node_domain = "mgmt.sitename.example.com" + + ba = design_data.get_bootaction('helloworld') + node_ctx = ba.asset_list[0]._get_node_context('compute01', design_data) + + assert node_ctx['domain'] == node_domain