diff --git a/drydock_provisioner/drivers/node/maasdriver/actions/node.py b/drydock_provisioner/drivers/node/maasdriver/actions/node.py index 7fa3d8e5..da35b7ac 100644 --- a/drydock_provisioner/drivers/node/maasdriver/actions/node.py +++ b/drydock_provisioner/drivers/node/maasdriver/actions/node.py @@ -18,10 +18,13 @@ import logging import re import math +from datetime import datetime + import drydock_provisioner.error as errors import drydock_provisioner.config as config import drydock_provisioner.objects.fields as hd_fields import drydock_provisioner.objects.hostprofile as hostprofile +import drydock_provisioner.objects as objects from drydock_provisioner.orchestrator.actions.orchestrator import BaseAction @@ -815,6 +818,7 @@ class ConfigureHardware(BaseMaasAction): ctx=n.name, ctx_type='node') self.task.success(focus=n.get_id()) + self.collect_build_data(machine) elif machine.status_name == 'Commissioning': msg = "Located node %s in MaaS, node already being commissioned. Skipping..." % ( n.name) @@ -853,6 +857,37 @@ class ConfigureHardware(BaseMaasAction): self.task.save() return + def collect_build_data(self, machine): + """Collect MaaS build data after commissioning.""" + self.logger.debug("Collecting build data for %s" % machine.hostname) + try: + data = machine.get_details() + if data: + for t, d in data.items(): + if t in ('lshw', 'lldp'): + df = 'text/xml' + else: + df = 'text/plain' + bd = objects.BuildData( + node_name=machine.hostname, + task_id=self.task.get_id(), + generator=t, + collected_date=datetime.utcnow(), + data_format=df, + data_element=d.decode()) + self.logger.debug( + "Saving build data from generator %s" % t) + self.state_manager.post_build_data(bd) + self.task.add_status_msg( + msg="Saving build data element.", + error=False, + ctx=machine.hostname, + ctx_type='node') + except Exception as ex: + self.logger.error( + "Error collecting node build data for %s" % machine.hostname, + exc_info=ex) + class ApplyNodeNetworking(BaseMaasAction): """Action to configure networking on a node.""" diff --git a/drydock_provisioner/drivers/node/maasdriver/models/machine.py b/drydock_provisioner/drivers/node/maasdriver/models/machine.py index 7edfbcf4..67c63b48 100644 --- a/drydock_provisioner/drivers/node/maasdriver/models/machine.py +++ b/drydock_provisioner/drivers/node/maasdriver/models/machine.py @@ -270,7 +270,7 @@ class Machine(model_base.ResourceBase): resp = self.api_client.get(url, op='details') if resp.status_code == 200: - detail_config = bson.loads(resp.text) + detail_config = bson.loads(resp.content) return detail_config def set_owner_data(self, key, value): diff --git a/tests/integration/postgres/test_build_data_collection.py b/tests/integration/postgres/test_build_data_collection.py new file mode 100644 index 00000000..6087ffac --- /dev/null +++ b/tests/integration/postgres/test_build_data_collection.py @@ -0,0 +1,46 @@ +# 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 build data collection and persistence.""" +import bson + +from drydock_provisioner import objects +from drydock_provisioner.drivers.node.maasdriver.actions.node import ConfigureHardware + + +class TestBuildDataCollection(object): + def test_build_data_collection(self, setup, blank_state, mocker, + deckhand_orchestrator): + """Test that the build data collection from MaaS works.""" + sample_data = { + 'lshw': 'foo'.encode(), + 'lldp': 'bar'.encode(), + } + bson_data = bson.loads(bson.dumps(sample_data)) + + machine = mocker.MagicMock() + mocker_config = { + 'get_details.return_value': bson_data, + 'hostname': 'foo', + } + machine.configure_mock(**mocker_config) + + task = objects.Task(statemgr=blank_state) + + action = ConfigureHardware(task, deckhand_orchestrator, blank_state) + + action.collect_build_data(machine) + + bd = blank_state.get_build_data(node_name='foo') + + assert len(bd) == 2