diskimage-builder/diskimage_builder/elements/pkg-map/bin/pkg-map

201 lines
6.5 KiB
Plaintext
Executable File

#!/usr/local/bin/dib-python
# Copyright 2014 Red Hat Inc.
#
# 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.
import argparse
import json
import logging
import os
import sys
log = logging.getLogger()
def os_family(distro):
family = None
if distro in ['fedora', 'rhel', 'rhel7', 'centos', 'centos7']:
family = 'redhat'
elif distro in ['debian', 'ubuntu']:
family = 'debian'
elif distro == 'opensuse':
family = 'suse'
elif distro == 'gentoo':
family = 'gentoo'
return family
def main():
parser = argparse.ArgumentParser(
description="Translate package name to distro specific name."
" Exits with 1 if error is encountered, 2 if no pkg-map"
" file is found. Otherwise exits with 0.")
parser.add_argument('--element', default='',
help='The element (namespace) to use for translation.')
parser.add_argument('--pkg-map', default='',
help='Path to specific pkg-map file. '
'(Useful for testing)')
parser.add_argument('--distro', default=os.environ.get('DISTRO_NAME'),
help='The distro name to use for translation.'
' Defaults to DISTRO_NAME')
parser.add_argument('--release', default=os.environ.get('DIB_RELEASE'),
help='A more specfic name for distribution release')
parser.add_argument('--missing-ok', action="store_true",
help='Do not consider missing mappings an error.'
' Causes packages where no mapping is set to be'
' printed.')
# This tool has traditionally output status and debug messages on
# stderr. The problem is if a caller has stderr > stdout then
# actual output gets messed in with the logs. This allows callers
# to disambiguate actual output by specifying a unique prefix.
parser.add_argument('--prefix', default='',
help='Output mapped packages with this prefix')
parser.add_argument('--debug', dest='debug', action="store_true",
help="Enable debugging output")
args, extra = parser.parse_known_args()
# Logs have traditionally gone to stderr with this tool. Maintain
# compatibility
level = logging.DEBUG if args.debug else logging.INFO
logging.basicConfig(stream=sys.stderr, level=level)
if not args.element and not args.pkg_map:
log.error('Please specify an --element argument.')
sys.exit(1)
if args.element and args.pkg_map:
log.error('Specify either --element or --pkg-map')
sys.exit(1)
if not args.distro:
log.error('Please specify a --distro argument or set DISTRO_NAME.')
sys.exit(1)
if args.pkg_map:
# specifying the pkg-map by hand is just for manual testing
element = "<%s>" % args.pkg_map
map_file = args.pkg_map
else:
element = args.element
map_file = '/usr/share/pkg-map/%s' % element
log.info("Mapping for %s : %s" % (element, ' '.join(extra)))
if not os.path.exists(map_file):
if args.missing_ok:
log.info("No package map for %s, done" % element)
for name in extra:
print('%s%s' % (args.prefix, name))
sys.exit(0)
else:
log.error('Required pkg-map for %s element does not exist.'
% args.element)
sys.exit(2)
with open(map_file) as fd:
try:
package_names = json.loads(fd.read())
# log.debug(pprint.pformat(package_names))
except ValueError:
log.error('Unable to parse %s' % map_file)
raise
# Parse mapping data in this form using release/distro/family/default
# Most specific takes priority; order is
# - release
# - distro
# - family
# - default
# An empty package list can be provided.
#
# Example for Nova and Glance (using fictitious name for Fedora and SUSE
# and package mapping for SUSE family)
# {
# "release": {
# "fedora" : {
# "23" : {
# "nova_package": "openstack-compute-foo"
# }
# }
# }
# "distro": {
# "fedora": {
# "nova_package": "openstack-compute",
# "glance_package": "openstack-image"
# }
# },
# "family": {
# "redhat": {
# "nova_package": "openstack-nova",
# "glance_package": "openstack-glance"
# },
# "suse": {
# "nova_package": ""
# }
# },
# "default": {
# "nova_package": "nova",
# "glance_package": "glance"
# }
# }
name_map = package_names.get('default', {})
if 'family' in package_names:
family_map = package_names['family'].get(os_family(args.distro))
if family_map:
name_map.update(family_map)
if 'distro' in package_names:
distro_map = package_names['distro'].get(args.distro)
if distro_map:
name_map.update(distro_map)
if 'release' in package_names:
try:
# release is a sub-concept of distro
release_map = package_names['release'][args.distro][args.release]
name_map.update(release_map)
except KeyError:
pass
# log.debug(pprint.pformat(name_map))
for name in extra:
pkg_name = name_map.get(name)
if pkg_name:
log.debug("map %s -> %s" % (name, pkg_name))
print('%s%s' % (args.prefix, pkg_name))
elif name in name_map:
log.debug("map %s -> <skip>" % (name))
continue
else:
if args.missing_ok:
log.debug("pass -> %s" % (name))
print('%s%s' % (args.prefix, name))
else:
log.error("%s has no valid mapping for package %s" %
(element, name))
sys.exit(1)
sys.exit(0)
if __name__ == '__main__':
main()
# Tell emacs to use python-mode
# Local variables:
# mode: python
# End: