blob: 65bbdc61f41507e84b03e079f8bd6d5177267281 [file] [log] [blame]
Brad Bishop6e60e8b2018-02-01 10:27:11 -05001# Copyright (C) 2016 Intel Corporation
2#
3# Released under the MIT license (see COPYING.MIT)
4#
5# Functions to get metadata from the testing host used
6# for analytics of test results.
7
8from collections import OrderedDict
9from collections.abc import MutableMapping
10from xml.dom.minidom import parseString
11from xml.etree.ElementTree import Element, tostring
12
Brad Bishopd7bf8c12018-02-25 22:55:05 -050013from oe.lsb import get_os_release
Brad Bishop6e60e8b2018-02-01 10:27:11 -050014from oeqa.utils.commands import runCmd, get_bb_vars
15
Brad Bishop6e60e8b2018-02-01 10:27:11 -050016
17def metadata_from_bb():
18 """ Returns test's metadata as OrderedDict.
19
20 Data will be gathered using bitbake -e thanks to get_bb_vars.
21 """
22 metadata_config_vars = ('MACHINE', 'BB_NUMBER_THREADS', 'PARALLEL_MAKE')
23
24 info_dict = OrderedDict()
25 hostname = runCmd('hostname')
26 info_dict['hostname'] = hostname.output
27 data_dict = get_bb_vars()
28
29 # Distro information
30 info_dict['distro'] = {'id': data_dict['DISTRO'],
31 'version_id': data_dict['DISTRO_VERSION'],
32 'pretty_name': '%s %s' % (data_dict['DISTRO'], data_dict['DISTRO_VERSION'])}
33
34 # Host distro information
35 os_release = get_os_release()
36 if os_release:
37 info_dict['host_distro'] = OrderedDict()
Brad Bishopd7bf8c12018-02-25 22:55:05 -050038 for key in ('ID', 'VERSION_ID', 'PRETTY_NAME'):
Brad Bishop6e60e8b2018-02-01 10:27:11 -050039 if key in os_release:
Brad Bishopd7bf8c12018-02-25 22:55:05 -050040 info_dict['host_distro'][key.lower()] = os_release[key]
Brad Bishop6e60e8b2018-02-01 10:27:11 -050041
42 info_dict['layers'] = get_layers(data_dict['BBLAYERS'])
43 info_dict['bitbake'] = git_rev_info(os.path.dirname(bb.__file__))
44
45 info_dict['config'] = OrderedDict()
46 for var in sorted(metadata_config_vars):
47 info_dict['config'][var] = data_dict[var]
48 return info_dict
49
50def metadata_from_data_store(d):
51 """ Returns test's metadata as OrderedDict.
52
53 Data will be collected from the provided data store.
54 """
55 # TODO: Getting metadata from the data store would
56 # be useful when running within bitbake.
57 pass
58
59def git_rev_info(path):
60 """Get git revision information as a dict"""
61 from git import Repo, InvalidGitRepositoryError, NoSuchPathError
62
63 info = OrderedDict()
64 try:
65 repo = Repo(path, search_parent_directories=True)
66 except (InvalidGitRepositoryError, NoSuchPathError):
67 return info
68 info['commit'] = repo.head.commit.hexsha
69 info['commit_count'] = repo.head.commit.count()
70 try:
71 info['branch'] = repo.active_branch.name
72 except TypeError:
73 info['branch'] = '(nobranch)'
74 return info
75
76def get_layers(layers):
77 """Returns layer information in dict format"""
78 layer_dict = OrderedDict()
79 for layer in layers.split():
80 layer_name = os.path.basename(layer)
81 layer_dict[layer_name] = git_rev_info(layer)
82 return layer_dict
83
84def write_metadata_file(file_path, metadata):
85 """ Writes metadata to a XML file in directory. """
86
87 xml = dict_to_XML('metadata', metadata)
88 xml_doc = parseString(tostring(xml).decode('UTF-8'))
89 with open(file_path, 'w') as f:
90 f.write(xml_doc.toprettyxml())
91
92def dict_to_XML(tag, dictionary, **kwargs):
93 """ Return XML element converting dicts recursively. """
94
95 elem = Element(tag, **kwargs)
96 for key, val in dictionary.items():
97 if tag == 'layers':
98 child = (dict_to_XML('layer', val, name=key))
99 elif isinstance(val, MutableMapping):
100 child = (dict_to_XML(key, val))
101 else:
102 if tag == 'config':
103 child = Element('variable', name=key)
104 else:
105 child = Element(key)
106 child.text = str(val)
107 elem.append(child)
108 return elem