diff --git a/elements/pkg-map/README.rst b/elements/pkg-map/README.rst
index efb6ac126..bd8d2bf89 100644
--- a/elements/pkg-map/README.rst
+++ b/elements/pkg-map/README.rst
@@ -16,18 +16,25 @@ Provides the following:
       --element ELEMENT  The element (namespace) to use for translation.
       --distro DISTRO    The distro name to use for translation. Defaults to
                          DISTRO_NAME
+      --release RELEASE  The release to use for translation.  Defaults to
+                         DIB_RELEASE
 
- * Any element may create its own pkg-map JSON config file using
-   the one of 3 sections for the distro/family/ and or default.
-   The family is set automatically within pkg-map based on
-   the supplied distro name. Families include:
+ * Any element may create its own pkg-map JSON config file using the
+   one of 4 sections for the release/distro/family/ and or default.
+   The family is set automatically within pkg-map based on the
+   supplied distro name. Families include:
 
      + redhat: includes centos, fedora, and rhel distros
      + debian: includes debian and ubuntu distros
      + suse: includes the opensuse distro
 
+   The release is a specification of distro; i.e. the distro and
+   release must mach for a translation.
+
    The most specific section takes priority.
+
    An empty package list can be provided.
+
    Example for Nova and Glance (NOTE: using fictitious package names
    for Fedora and package mapping for suse family to provide a good
    example!)
@@ -35,6 +42,13 @@ Provides the following:
    Example format::
 
     {
+      "release": {
+        "fedora": {
+          "23": {
+            "nova_package": "foo" "bar"
+          }
+        }
+      },
       "distro": {
         "fedora": {
           "nova_package": "openstack-compute",
diff --git a/elements/pkg-map/bin/pkg-map b/elements/pkg-map/bin/pkg-map
index 9ece74d19..1b3677f23 100755
--- a/elements/pkg-map/bin/pkg-map
+++ b/elements/pkg-map/bin/pkg-map
@@ -16,7 +16,9 @@
 
 import argparse
 import json
+import logging
 import os
+import pprint
 import sys
 
 
@@ -46,24 +48,44 @@ def main():
                     " 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 not args.element:
+    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)
 
-    map_file = '/usr/share/pkg-map/%s' % args.element
+    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)
@@ -76,16 +98,29 @@ def main():
     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 distro/family/default
-    # Most specific takes priority (distro is most specific).
+    # 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",
@@ -115,6 +150,13 @@ def main():
         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)