metadata.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. # 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. from collections import OrderedDict
  8. from collections.abc import MutableMapping
  9. from xml.dom.minidom import parseString
  10. from xml.etree.ElementTree import Element, tostring
  11. from oe.lsb import get_os_release
  12. from oeqa.utils.commands import runCmd, get_bb_vars
  13. def metadata_from_bb():
  14. """ Returns test's metadata as OrderedDict.
  15. Data will be gathered using bitbake -e thanks to get_bb_vars.
  16. """
  17. metadata_config_vars = ('MACHINE', 'BB_NUMBER_THREADS', 'PARALLEL_MAKE')
  18. info_dict = OrderedDict()
  19. hostname = runCmd('hostname')
  20. info_dict['hostname'] = hostname.output
  21. data_dict = get_bb_vars()
  22. # Distro information
  23. info_dict['distro'] = {'id': data_dict['DISTRO'],
  24. 'version_id': data_dict['DISTRO_VERSION'],
  25. 'pretty_name': '%s %s' % (data_dict['DISTRO'], data_dict['DISTRO_VERSION'])}
  26. # Host distro information
  27. os_release = get_os_release()
  28. if os_release:
  29. info_dict['host_distro'] = OrderedDict()
  30. for key in ('ID', 'VERSION_ID', 'PRETTY_NAME'):
  31. if key in os_release:
  32. info_dict['host_distro'][key.lower()] = os_release[key]
  33. info_dict['layers'] = get_layers(data_dict['BBLAYERS'])
  34. info_dict['bitbake'] = git_rev_info(os.path.dirname(bb.__file__))
  35. info_dict['config'] = OrderedDict()
  36. for var in sorted(metadata_config_vars):
  37. info_dict['config'][var] = data_dict[var]
  38. return info_dict
  39. def metadata_from_data_store(d):
  40. """ Returns test's metadata as OrderedDict.
  41. Data will be collected from the provided data store.
  42. """
  43. # TODO: Getting metadata from the data store would
  44. # be useful when running within bitbake.
  45. pass
  46. def git_rev_info(path):
  47. """Get git revision information as a dict"""
  48. info = OrderedDict()
  49. try:
  50. from git import Repo, InvalidGitRepositoryError, NoSuchPathError
  51. except ImportError:
  52. import subprocess
  53. try:
  54. info['branch'] = subprocess.check_output(["git", "rev-parse", "--abbrev-ref", "HEAD"], cwd=path).decode('utf-8').strip()
  55. except subprocess.CalledProcessError:
  56. pass
  57. try:
  58. info['commit'] = subprocess.check_output(["git", "rev-parse", "HEAD"], cwd=path).decode('utf-8').strip()
  59. except subprocess.CalledProcessError:
  60. pass
  61. return info
  62. try:
  63. repo = Repo(path, search_parent_directories=True)
  64. except (InvalidGitRepositoryError, NoSuchPathError):
  65. return info
  66. info['commit'] = repo.head.commit.hexsha
  67. info['commit_count'] = repo.head.commit.count()
  68. try:
  69. info['branch'] = repo.active_branch.name
  70. except TypeError:
  71. info['branch'] = '(nobranch)'
  72. return info
  73. def get_layers(layers):
  74. """Returns layer information in dict format"""
  75. layer_dict = OrderedDict()
  76. for layer in layers.split():
  77. layer_name = os.path.basename(layer)
  78. layer_dict[layer_name] = git_rev_info(layer)
  79. return layer_dict
  80. def write_metadata_file(file_path, metadata):
  81. """ Writes metadata to a XML file in directory. """
  82. xml = dict_to_XML('metadata', metadata)
  83. xml_doc = parseString(tostring(xml).decode('UTF-8'))
  84. with open(file_path, 'w') as f:
  85. f.write(xml_doc.toprettyxml())
  86. def dict_to_XML(tag, dictionary, **kwargs):
  87. """ Return XML element converting dicts recursively. """
  88. elem = Element(tag, **kwargs)
  89. for key, val in dictionary.items():
  90. if tag == 'layers':
  91. child = (dict_to_XML('layer', val, name=key))
  92. elif isinstance(val, MutableMapping):
  93. child = (dict_to_XML(key, val))
  94. else:
  95. if tag == 'config':
  96. child = Element('variable', name=key)
  97. else:
  98. child = Element(key)
  99. child.text = str(val)
  100. elem.append(child)
  101. return elem