97c01e48ed
Currently we have all our elements and library files in a top-level directory and install them into <root>/share/diskimage-builder/[elements|lib] (where root is either / or the root of a virtualenv). The problem with this is that editable/development installs (pip -e) do *not* install data_files. Thus we have no canonical location to look for elements -- leading to the various odd things we do such as a whole bunch of guessing at the top of disk-image-create and having a special test-loader in tests/test_elements.py so we can run python unit tests on those elements that have it. data_files is really the wrong thing to use for what are essentially assets of the program. data_files install works well for things like config-files, init.d files or dropping documentation files. By moving the elements under the diskimage_builder package, we always know where they are relative to where we import from. In fact, pkg_resources has an api for this which we wrap in the new diskimage_builder/paths.py helper [1]. We use this helper to find the correct path in the couple of places we need to find the base-elements dir, and for the paths to import the library shell functions. Elements such as svc-map and pkg-map include python unit-tests, which we do not need tests/test_elements.py to special-case load any more. They just get found automatically by the normal subunit loader. I have a follow-on change (I69ca3d26fede0506a6353c077c69f735c8d84d28) to move disk-image-create to a regular python entry-point. Unfortunately, this has to move to work with setuptools. You'd think a symlink under diskimage_builder/[elements|lib] would work, but it doesn't. [1] this API handles stuff like getting files out of .zip archive modules, which we don't do. Essentially for us it's returning __file__. Change-Id: I5e3e3c97f385b1a4ff2031a161a55b231895df5b
179 lines
5.5 KiB
Plaintext
Executable File
179 lines
5.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 pprint
|
|
import sys
|
|
|
|
|
|
def eprint(msg):
|
|
sys.stderr.write(msg)
|
|
sys.stderr.write("\n")
|
|
|
|
|
|
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.')
|
|
parser.add_argument('--debug', dest='debug', action="store_true",
|
|
help="Enable debugging output")
|
|
|
|
args, extra = parser.parse_known_args()
|
|
|
|
if args.debug:
|
|
logging.basicConfig(level=logging.DEBUG)
|
|
|
|
if not args.element and not args.pkg_map:
|
|
eprint('Please specify an --element argument.')
|
|
sys.exit(1)
|
|
|
|
if args.element and args.pkg_map:
|
|
eprint('Specify either --element or --pkg-map')
|
|
sys.exit(1)
|
|
|
|
if not args.distro:
|
|
eprint('Please specify a --distro argument or set DISTRO_NAME.')
|
|
sys.exit(1)
|
|
|
|
if args.pkg_map:
|
|
map_file = args.pkg_map
|
|
else:
|
|
map_file = '/usr/share/pkg-map/%s' % args.element
|
|
|
|
logging.debug("Map file is %s" % map_file)
|
|
if not os.path.exists(map_file):
|
|
if os.environ.get('DIB_DEBUG_TRACE', '0') != '0':
|
|
eprint('Map file for %s element does not exist.' % args.element)
|
|
if args.missing_ok:
|
|
for name in extra:
|
|
print(name)
|
|
sys.exit(0)
|
|
sys.exit(2)
|
|
|
|
with open(map_file) as fd:
|
|
try:
|
|
package_names = json.loads(fd.read())
|
|
logging.debug(pprint.pformat(package_names))
|
|
except ValueError:
|
|
eprint('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
|
|
|
|
for name in extra:
|
|
pkg_name = name_map.get(name)
|
|
if pkg_name:
|
|
print(pkg_name)
|
|
elif name in name_map:
|
|
continue
|
|
else:
|
|
err_msg = 'Missing package name for distro/element: %s/%s'
|
|
eprint(err_msg % (args.distro, args.element))
|
|
if args.missing_ok:
|
|
print(name)
|
|
else:
|
|
sys.exit(1)
|
|
|
|
sys.exit(0)
|
|
|
|
if __name__ == '__main__':
|
|
main()
|