|
Packit |
8ea169 |
#!/usr/bin/python3
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
## Copyright (C) 2014 ABRT team <abrt-devel-list@redhat.com>
|
|
Packit |
8ea169 |
## Copyright (C) 2014 Red Hat, Inc.
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
## This program is free software; you can redistribute it and/or modify
|
|
Packit |
8ea169 |
## it under the terms of the GNU General Public License as published by
|
|
Packit |
8ea169 |
## the Free Software Foundation; either version 2 of the License, or
|
|
Packit |
8ea169 |
## (at your option) any later version.
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
## This program is distributed in the hope that it will be useful,
|
|
Packit |
8ea169 |
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
8ea169 |
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit |
8ea169 |
## GNU General Public License for more details.
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
## You should have received a copy of the GNU General Public License
|
|
Packit |
8ea169 |
## along with this program; if not, write to the Free Software
|
|
Packit |
8ea169 |
## Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
"""This module provides algorithms for generating Machine IDs.
|
|
Packit |
8ea169 |
"""
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
import os
|
|
Packit |
8ea169 |
import sys
|
|
Packit |
8ea169 |
from argparse import ArgumentParser
|
|
Packit |
8ea169 |
from subprocess import check_output
|
|
Packit |
8ea169 |
import logging
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
import hashlib
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
def generate_machine_id_dmidecode():
|
|
Packit |
8ea169 |
"""Generate a machine_id based off dmidecode fields
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
The function generates the same result as sosreport-uploader
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
Returns a machine ID as string or throws RuntimeException
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
"""
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
if not os.path.isfile("/usr/sbin/dmidecode"):
|
|
Packit |
8ea169 |
raise RuntimeError("Could not find dmidecode. It might not be available for this " \
|
|
Packit |
8ea169 |
"architecture.")
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
# What to look for
|
|
Packit |
8ea169 |
keys = ['system-manufacturer',
|
|
Packit |
8ea169 |
'system-product-name',
|
|
Packit |
8ea169 |
'system-serial-number',
|
|
Packit |
8ea169 |
'system-uuid']
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
# Create a sha256 of ^ for machine_id
|
|
Packit |
8ea169 |
machine_id = hashlib.sha256()
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
# Run dmidecode command
|
|
Packit |
8ea169 |
for k in keys:
|
|
Packit |
8ea169 |
data = check_output(["dmidecode", "-s", k]).strip()
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
# Update the hash as we find the fields we are looking for
|
|
Packit |
8ea169 |
machine_id.update(data)
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
# Create sha256 digest
|
|
Packit |
8ea169 |
return machine_id.hexdigest()
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
def generate_machine_id_systemd():
|
|
Packit |
8ea169 |
"""Generate a machine_id equals to a one generated by systemd
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
This function returns contents of /etc/machine-id
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
Returns a machine ID as string or throws RuntimeException.
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
"""
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
try:
|
|
Packit |
8ea169 |
with open('/etc/machine-id', 'r') as midf:
|
|
Packit |
8ea169 |
return "".join((l.strip() for l in midf))
|
|
Packit |
8ea169 |
except IOError as ex:
|
|
Packit |
8ea169 |
raise RuntimeError("Could not use systemd's machine-id: {0}"
|
|
Packit |
8ea169 |
.format(str(ex)))
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
GENERATORS = { 'sosreport_uploader-dmidecode' : generate_machine_id_dmidecode,
|
|
Packit |
8ea169 |
'systemd' : generate_machine_id_systemd }
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
def generate_machine_id(generators):
|
|
Packit |
8ea169 |
"""Generates all requested machine id with all required generators
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
Keyword arguments:
|
|
Packit |
8ea169 |
generators -- a list of generator names
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
Returns a dictionary where keys are generators and associated values are
|
|
Packit |
8ea169 |
products of those generators.
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
"""
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
ids = {}
|
|
Packit |
8ea169 |
workers = GENERATORS
|
|
Packit |
8ea169 |
for sd in generators:
|
|
Packit |
8ea169 |
try:
|
|
Packit |
8ea169 |
ids[sd] = workers[sd]()
|
|
Packit |
8ea169 |
except RuntimeError as ex:
|
|
Packit |
8ea169 |
logging.error("Machine-ID generator '{0}' failed: {1}"
|
|
Packit |
8ea169 |
.format(sd, str(ex)))
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
return ids
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
def print_result(ids, outfile, prefixed):
|
|
Packit |
8ea169 |
"""Writes a dictionary of machine ids to a file
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
Each dictionary entry is written on a single line. The function does not
|
|
Packit |
8ea169 |
print trailing new-line if the dictionary contains only one item as it is
|
|
Packit |
8ea169 |
common format of one-liners placed in a dump directory.
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
Keyword arguments:
|
|
Packit |
8ea169 |
ids -- a dictionary [generator name: machine ids]
|
|
Packit |
8ea169 |
outfile -- output file
|
|
Packit |
8ea169 |
prefixed -- use 'generator name=' prefix or not
|
|
Packit |
8ea169 |
"""
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
fmt = '{0}={1}' if prefixed else '{1}'
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
if len(ids) > 1:
|
|
Packit |
8ea169 |
fmt += '\n'
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
for sd, mid in ids.items():
|
|
Packit |
8ea169 |
outfile.write(fmt.format(sd,mid))
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
def print_generators(outfile=None):
|
|
Packit |
8ea169 |
"""Prints requested generators
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
Keyword arguments:
|
|
Packit |
8ea169 |
outfile -- output file (default: sys.stdout)
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
"""
|
|
Packit |
8ea169 |
if outfile is None:
|
|
Packit |
8ea169 |
outfile = sys.stdout
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
for sd in GENERATORS.keys():
|
|
Packit |
8ea169 |
outfile.write("{0}\n".format(sd))
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
if __name__ == '__main__':
|
|
Packit |
8ea169 |
CMDARGS = ArgumentParser(description = "Generate a machine_id")
|
|
Packit |
8ea169 |
CMDARGS.add_argument('-o', '--output', type=str,
|
|
Packit |
8ea169 |
help="Output file")
|
|
Packit |
8ea169 |
CMDARGS.add_argument('-g', '--generators', nargs='+', type=str,
|
|
Packit |
8ea169 |
help="Use given generators only")
|
|
Packit |
8ea169 |
CMDARGS.add_argument('-l', '--list-generators', action='store_true',
|
|
Packit |
8ea169 |
default=False, help="Print out a list of usable generators")
|
|
Packit |
8ea169 |
CMDARGS.add_argument('-n', '--noprefix', action='store_true',
|
|
Packit |
8ea169 |
default=False, help="Do not use generator name as prefix for IDs")
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
OPTIONS = CMDARGS.parse_args()
|
|
Packit |
8ea169 |
ARGS = vars(OPTIONS)
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
logging.basicConfig(format='%(message)s')
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
if ARGS['list_generators']:
|
|
Packit |
8ea169 |
print_generators()
|
|
Packit |
8ea169 |
sys.exit(0)
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
requested_generators = None
|
|
Packit |
8ea169 |
if ARGS['generators']:
|
|
Packit |
8ea169 |
requested_generators = ARGS['generators']
|
|
Packit |
8ea169 |
else:
|
|
Packit |
8ea169 |
requested_generators = list(GENERATORS.keys())
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
machineids = generate_machine_id(requested_generators)
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
if ARGS['output']:
|
|
Packit |
8ea169 |
try:
|
|
Packit |
8ea169 |
with open(ARGS['output'], 'w') as fout:
|
|
Packit |
8ea169 |
print_result(machineids, fout, not ARGS['noprefix'])
|
|
Packit |
8ea169 |
except IOError as ex:
|
|
Packit |
8ea169 |
logging.error("Could not open output file: {0}".format(str(ex)))
|
|
Packit |
8ea169 |
sys.exit(1)
|
|
Packit |
8ea169 |
else:
|
|
Packit |
8ea169 |
print_result(machineids, sys.stdout, not ARGS['noprefix'])
|
|
Packit |
8ea169 |
# print_results() omits new-line for one-liners
|
|
Packit |
8ea169 |
if len(machineids) == 1:
|
|
Packit |
8ea169 |
sys.stdout.write('\n')
|
|
Packit |
8ea169 |
|
|
Packit |
8ea169 |
sys.exit(len(requested_generators) - len(machineids))
|