Add support of MAAS node-results API

- Support extraction of log data from MAAS

Change-Id: I55fcbad5e06378f148c9d5de476e1eef8d898ed2
This commit is contained in:
Scott Hussey 2018-07-06 15:38:35 -05:00
parent cff7420cff
commit b53a3ff0ea
4 changed files with 164 additions and 4 deletions

View File

@ -303,9 +303,9 @@ class ResourceCollectionBase(object):
"""Iterate over the resources in the collection."""
return iter(self.resources.values())
"""
Resource count
"""
def len(self):
return len(self)
def __len__(self):
"""Resource count."""
return len(self.resources)

View File

@ -20,6 +20,7 @@ import drydock_provisioner.drivers.node.maasdriver.models.base as model_base
import drydock_provisioner.drivers.node.maasdriver.models.interface as maas_interface
import drydock_provisioner.drivers.node.maasdriver.models.blockdev as maas_blockdev
import drydock_provisioner.drivers.node.maasdriver.models.volumegroup as maas_vg
import drydock_provisioner.drivers.node.maasdriver.models.node_results as maas_nr
from bson import BSON
@ -296,6 +297,17 @@ class Machine(model_base.ResourceBase):
detail_config = BSON.decode(resp.content)
return detail_config
def get_task_results(self, result_type='all'):
"""Get the result from tasks run during node deployment.
:param str result_type: the type of results to return. One of
``all``, ``commissioning``, ``testing``, ``deploy``
"""
node_results = maas_nr.NodeResults(system_id_list=[self.resource_id], result_type=result_type)
node_results.refresh()
return node_results
def set_owner_data(self, key, value):
"""Add/update/remove node owner data.

View File

@ -0,0 +1,93 @@
# 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 for MaaS Node Result resources."""
import base64
import binascii
import drydock_provisioner.drivers.node.maasdriver.models.base as model_base
class NodeResult(model_base.ResourceBase):
resource_url = 'commissioning-results/'
fields = ['resource_id', 'name', 'result_type', 'updated', 'data', 'script_result']
json_fields = []
type_map = {
'commissioning': 0,
'deploy': 1,
'testing': 2,
}
type_rev_map = {
0: 'commissioning',
1: 'deploy',
2: 'testing',
}
def __init__(self, api_client, **kwargs):
super().__init__(api_client, **kwargs)
def refresh(self):
"""Don't allow refresh of individual result."""
return
def update(self):
"""Don't allow updates."""
return
def get_decoded_data(self):
"""Decode the result data from base64."""
try:
return base64.b64decode(self.data)
except binascii.Error as e:
return None
def get_type_desc(self):
return NodeResult.type_rev_map.get(self.result_type)
class NodeResults(model_base.ResourceCollectionBase):
collection_url = 'commissioning-results/'
collection_resource = NodeResult
def __init__(self, api_client, system_id_list=None, result_type=None):
super().__init__(api_client)
self.system_id_list = system_id_list
self.result_type = result_type
def refresh(self):
params = dict()
if self.system_id_list:
params['system_id'] = self.system_id_list
if self.result_type and self.result_type != 'all':
params['result_type'] = NodeResult.type_map.get(self.result_type)
url = self.interpolate_url()
if params:
resp = self.api_client.get(url, files=params)
else:
resp = self.api_client.get(url)
if resp.status_code in [200]:
json_list = resp.json()
self.resource = dict()
for o in json_list:
if isinstance(o, dict):
i = self.collection_resource.from_dict(self.api_client, o)
self.resources[i.resource_id] = i
return

View File

@ -0,0 +1,55 @@
# 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.
'''Tests for the maasdriver node_results routine.'''
from drydock_provisioner.drivers.node.maasdriver.models.node_results import NodeResults
class TestMaasNodeResults():
def test_get_noderesults(self, mocker):
'''Test noderesults refresh call to load a list of NodeResults.'''
# A object to return that looks like a requests response
# object wrapping a MAAS API response
class MockedResponse():
status_code = 200
def json(self):
resp_content = [{
"id": 3,
"data": "SGVsbG8gV29ybGQh",
"result_type": 0,
"script_result": 0,
"resource_uri": "/MAAS/api/2.0/commissioning-scripts/",
"updated": "2018-07-06T14:32:20.129",
"node": {
"system_id": "r7mqnw"
},
"created": "2018-07-06T14:37:12.632",
"name": "hello_world"
}]
return resp_content
api_client = mocker.MagicMock()
api_client.get.return_value = MockedResponse()
nr_list = NodeResults(api_client)
nr_list.refresh()
api_client.get.assert_called_with('commissioning-results/')
assert len(nr_list) == 1
nr = nr_list.singleton({'name': 'hello_world'})
assert nr.get_decoded_data() == b'Hello World!'