From 61dfc78bc2db78f0f53c8ba9413d3a57a96ee808 Mon Sep 17 00:00:00 2001
From: Matthew Harmsen <mharmsen@redhat.com>
Date: Tue, 24 Jul 2012 11:28:29 -0700
Subject: [PATCH] PKI Deployment Scriptlets

* PKI TRAC Ticket #244 - Non-user-friendly message when deleting non-existent
  subsystem with pkidestroy
* PKI TRAC Ticket #246 - Incorrect parameter names in pkispawn configuration
* PKI TRAC Ticket #248 - pki_ds_database should not be a DN
* PKI TRAC Ticket #249 - pki_ds_base_dn causing pkispawn failure
* PKI TRAC Ticket #250 - Creating/removing custom instances should not require
  http/ajp ports
* PKI TRAC Ticket #251 - Instance name may conflict with other files
* PKI TRAC Ticket #253 - Fix pki-destroy removal of
  '/var/log/pki/{pki_instance_id}' directory . . .
* PKI TRAC Ticket #254 - Dogtag 10: Fix spec file to build successfully via mock
  on Fedora 17 . . .
* PKI TRAC Ticket #255 - Missing resteasy-atom-provider.jar
* PKI TRAC Ticket #260 - Dogtag 10: Change the layout of 'pki_instance_id' . . .
---
 base/deploy/config/pkideployment.cfg          |   11 +-
 base/deploy/src/pkidestroy                    |    2 +-
 base/deploy/src/pkispawn                      |    2 +-
 base/deploy/src/scriptlets/initialization.py  |   14 +-
 base/deploy/src/scriptlets/instance_layout.py |    5 +
 base/deploy/src/scriptlets/pkiconfig.py       |   21 +-
 base/deploy/src/scriptlets/pkihelper.py       |  156 +++++++++----
 base/deploy/src/scriptlets/pkijython.py       |    2 +-
 base/deploy/src/scriptlets/pkimessages.py     |    8 +-
 base/deploy/src/scriptlets/pkiparser.py       |  294 ++++++++++++++++---------
 specs/pki-core.spec                           |    9 +-
 11 files changed, 352 insertions(+), 172 deletions(-)

diff --git a/base/deploy/config/pkideployment.cfg b/base/deploy/config/pkideployment.cfg
index fb04c85..d0acd7f 100644
--- a/base/deploy/config/pkideployment.cfg
+++ b/base/deploy/config/pkideployment.cfg
@@ -11,8 +11,8 @@
 pki_admin_password=
 pki_backup_password=
 pki_client_pkcs12_password=
+pki_clone_pkcs12_password=
 pki_ds_password=
-pki_pkcs12_password=
 pki_security_domain_password=
 ###############################################################################
 ##  'Common' Data:                                                           ##
@@ -48,8 +48,8 @@ pki_ds_base_dn=
 pki_ds_bind_dn=cn=Directory Manager
 pki_ds_database=
 pki_ds_hostname=
-pki_ds_http_port=389
-pki_ds_https_port=636
+pki_ds_ldap_port=389
+pki_ds_ldaps_port=636
 pki_ds_remove_data=True
 pki_ds_secure_connection=False
 pki_group=pkiuser
@@ -78,7 +78,7 @@ pki_user=pkiuser
 ##  required information which MAY be overridden by users as necessary.      ##
 ###############################################################################
 [Apache]
-pki_instance_name=apache
+pki_instance_name=pki-apache
 pki_http_port=80
 pki_https_port=443
 ###############################################################################
@@ -102,7 +102,7 @@ pki_clone=False
 pki_enable_java_debugger=False
 pki_http_port=8080
 pki_https_port=8443
-pki_instance_name=tomcat
+pki_instance_name=pki-tomcat
 pki_proxy_http_port=
 pki_proxy_https_port=
 pki_security_manager=false
@@ -183,7 +183,6 @@ pki_ocsp_signing_nickname=
 pki_ocsp_signing_signing_algorithm=SHA256withRSA
 pki_ocsp_signing_subject_dn=
 pki_ocsp_signing_token=
-pki_subordinate=False
 pki_subsystem=OCSP
 pki_subsystem_name=
 pki_war_name=ocsp.war
diff --git a/base/deploy/src/pkidestroy b/base/deploy/src/pkidestroy
index 304b0bd..1e0f020 100755
--- a/base/deploy/src/pkidestroy
+++ b/base/deploy/src/pkidestroy
@@ -80,7 +80,7 @@ def main(argv):
     # Retrieve DNS domainname
     config.pki_dns_domainname = None
     try:
-        config.pki_dns_domainname = subprocess.check_output("domainname",
+        config.pki_dns_domainname = subprocess.check_output("dnsdomainname",
                                                             shell=True)
         config.pki_dns_domainname = config.pki_dns_domainname.rstrip('\n')
         if not len(config.pki_dns_domainname):
diff --git a/base/deploy/src/pkispawn b/base/deploy/src/pkispawn
index 6f32d08..75c1967 100755
--- a/base/deploy/src/pkispawn
+++ b/base/deploy/src/pkispawn
@@ -80,7 +80,7 @@ def main(argv):
     # Retrieve DNS domainname
     config.pki_dns_domainname = None
     try:
-        config.pki_dns_domainname = subprocess.check_output("domainname",
+        config.pki_dns_domainname = subprocess.check_output("dnsdomainname",
                                                             shell=True)
         config.pki_dns_domainname = config.pki_dns_domainname.rstrip('\n')
         if not len(config.pki_dns_domainname):
diff --git a/base/deploy/src/scriptlets/initialization.py b/base/deploy/src/scriptlets/initialization.py
index 368cf25..da1a934 100644
--- a/base/deploy/src/scriptlets/initialization.py
+++ b/base/deploy/src/scriptlets/initialization.py
@@ -32,15 +32,15 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet):
     rv = 0
 
     def spawn(self):
+        # detect and avoid any namespace collisions
+        util.namespace.collision_detection()
+        # begin official logging
         config.pki_log.info(log.PKISPAWN_BEGIN_MESSAGE_2,
                             master['pki_subsystem'],
                             master['pki_instance_id'],
                             extra=config.PKI_INDENTATION_LEVEL_0)
         config.pki_log.info(log.INITIALIZATION_SPAWN_1, __name__,
                             extra=config.PKI_INDENTATION_LEVEL_1)
-        # verify that this type of "subsystem" does NOT yet
-        # exist for this "instance"
-        util.instance.verify_subsystem_does_not_exist()
         # initialize 'uid' and 'gid'
         util.identity.add_uid_and_gid(master['pki_user'], master['pki_group'])
         # establish 'uid' and 'gid'
@@ -56,30 +56,26 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet):
         return self.rv
 
     def respawn(self):
+        # begin official logging
         config.pki_log.info(log.PKIRESPAWN_BEGIN_MESSAGE_2,
                             master['pki_subsystem'],
                             master['pki_instance_id'],
                             extra=config.PKI_INDENTATION_LEVEL_0)
         config.pki_log.info(log.INITIALIZATION_RESPAWN_1, __name__,
                             extra=config.PKI_INDENTATION_LEVEL_1)
-        # verify that this type of "subsystem" currently EXISTS
-        # for this "instance"
-        util.instance.verify_subsystem_exists()
         # establish 'uid' and 'gid'
         util.identity.set_uid(master['pki_user'])
         util.identity.set_gid(master['pki_group'])
         return self.rv
 
     def destroy(self):
+        # begin official logging
         config.pki_log.info(log.PKIDESTROY_BEGIN_MESSAGE_2,
                             master['pki_subsystem'],
                             master['pki_instance_id'],
                             extra=config.PKI_INDENTATION_LEVEL_0)
         config.pki_log.info(log.INITIALIZATION_DESTROY_1, __name__,
                             extra=config.PKI_INDENTATION_LEVEL_1)
-        # verify that this type of "subsystem" currently EXISTS
-        # for this "instance"
-        util.instance.verify_subsystem_exists()
         # establish 'uid' and 'gid'
         util.identity.set_uid(master['pki_user'])
         util.identity.set_gid(master['pki_group'])
diff --git a/base/deploy/src/scriptlets/instance_layout.py b/base/deploy/src/scriptlets/instance_layout.py
index 2fd7165..7829e24 100644
--- a/base/deploy/src/scriptlets/instance_layout.py
+++ b/base/deploy/src/scriptlets/instance_layout.py
@@ -112,6 +112,8 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet):
                 master['pki_cmsutil_jar_link'])
             util.symlink.create(master['pki_nsutil'],
                 master['pki_nsutil_jar_link'])
+            util.symlink.create(master['pki_resteasy_atom_provider_jar'],
+                master['pki_resteasy_atom_provider_jar_link'])
             util.symlink.create(master['pki_resteasy_jaxb_provider_jar'],
                 master['pki_resteasy_jaxb_provider_jar_link'])
             util.symlink.create(master['pki_resteasy_jaxrs_jar'],
@@ -202,6 +204,7 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet):
             util.symlink.modify(master['pki_cms_jar_link'])
             util.symlink.modify(master['pki_cmsutil_jar_link'])
             util.symlink.modify(master['pki_nsutil_jar_link'])
+            util.symlink.modify(master['pki_resteasy_atom_provider_jar_link'])
             util.symlink.modify(master['pki_resteasy_jaxb_provider_jar_link'])
             util.symlink.modify(master['pki_resteasy_jaxrs_jar_link'])
             util.symlink.modify(
@@ -244,6 +247,7 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet):
                 # remove Tomcat instance base
                 util.directory.delete(master['pki_instance_path'])
                 # remove Tomcat instance logs
+                util.directory.delete(master['pki_instance_log_path'])
                 # remove shared NSS security database path for this instance
                 util.directory.delete(master['pki_database_path'])
                 # remove Tomcat instance configuration
@@ -270,6 +274,7 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet):
                 # remove Tomcat instance base
                 util.directory.delete(master['pki_instance_path'])
                 # remove Tomcat instance logs
+                util.directory.delete(master['pki_instance_log_path'])
                 # remove shared NSS security database path for this instance
                 util.directory.delete(master['pki_database_path'])
                 # remove Tomcat instance configuration
diff --git a/base/deploy/src/scriptlets/pkiconfig.py b/base/deploy/src/scriptlets/pkiconfig.py
index e300c1e..6418322 100644
--- a/base/deploy/src/scriptlets/pkiconfig.py
+++ b/base/deploy/src/scriptlets/pkiconfig.py
@@ -40,6 +40,13 @@ PKI_SUBSYSTEMS = ["CA","KRA","OCSP","RA","TKS","TPS"]
 PKI_SIGNED_AUDIT_SUBSYSTEMS = ["CA","KRA","OCSP","TKS","TPS"]
 PKI_APACHE_SUBSYSTEMS = ["RA","TPS"]
 PKI_TOMCAT_SUBSYSTEMS = ["CA","KRA","OCSP","TKS"]
+PKI_BASE_RESERVED_NAMES = ["alias", "bin", "ca", "common", "conf", "kra",
+                           "lib", "logs", "ocsp", "temp", "tks", "webapps",
+                           "work"]
+PKI_CONFIGURATION_RESERVED_NAMES = ["CA", "java", "nssdb", "rpm-gpg",
+                                    "rsyslog", "tls"]
+PKI_APACHE_REGISTRY_RESERVED_NAMES = ["ra", "tps"]
+PKI_TOMCAT_REGISTRY_RESERVED_NAMES = ["ca", "kra", "ocsp", "tks"]
 
 PKI_INDENTATION_LEVEL_0 = {'indent' : ''}
 PKI_INDENTATION_LEVEL_1 = {'indent' : '... '}
@@ -73,17 +80,19 @@ PKI_DEPLOYMENT_LOG_ROOT = "/var/log/pki"
 #        should always match the 'default' instance name specified below).
 PKI_DEPLOYMENT_REGISTRY_ROOT = "/etc/sysconfig/pki"
 PKI_DEPLOYMENT_DEFAULT_ADMIN_DOMAIN_NAME = None
-PKI_DEPLOYMENT_DEFAULT_APACHE_INSTANCE_NAME = "apache"
-PKI_DEPLOYMENT_DEFAULT_TOMCAT_INSTANCE_NAME = "tomcat"
+PKI_DEPLOYMENT_DEFAULT_APACHE_SERVICE_NAME = "apache"
+PKI_DEPLOYMENT_DEFAULT_TOMCAT_SERVICE_NAME = "tomcat"
+PKI_DEPLOYMENT_DEFAULT_APACHE_INSTANCE_NAME = "pki-apache"
+PKI_DEPLOYMENT_DEFAULT_TOMCAT_INSTANCE_NAME = "pki-tomcat"
 PKI_DEPLOYMENT_DEFAULT_CONFIGURATION_FILE = "pkideployment.cfg"
 PKI_DEPLOYMENT_SLOTS_CONFIGURATION_FILE =\
     "/usr/share/pki/deployment/config/pkislots.cfg"
 
 # default ports (for defined selinux policy)
-PKI_DEPLOYMENT_DEFAULT_HTTP_PORT = 8080
-PKI_DEPLOYMENT_DEFAULT_HTTPS_PORT = 8443
+PKI_DEPLOYMENT_DEFAULT_TOMCAT_HTTP_PORT = 8080
+PKI_DEPLOYMENT_DEFAULT_TOMCAT_HTTPS_PORT = 8443
 PKI_DEPLOYMENT_DEFAULT_TOMCAT_SERVER_PORT = 8005
-PKI_DEPLOYMENT_DEFAULT_AJP_PORT = 8009
+PKI_DEPLOYMENT_DEFAULT_TOMCAT_AJP_PORT = 8009
 
 # PKI Deployment Jython 2.2 Constants
 PKI_JYTHON_CRITICAL_LOG_LEVEL = 1
@@ -105,6 +114,7 @@ pki_one_time_pin = None
 
 # PKI Deployment "Mandatory" Command-Line Variables
 pki_subsystem = None
+#     'pkispawn' ONLY
 pkideployment_cfg = "/usr/share/pki/deployment/config/pkideployment.cfg"
 
 # PKI Deployment "Optional" Command-Line Variables
@@ -115,6 +125,7 @@ pki_update_flag = False
 # PKI Deployment "Custom" Command-Line Variables
 custom_pki_admin_domain_name = None
 custom_pki_instance_name = None
+#     'pkispawn' ONLY
 custom_pki_http_port = None
 custom_pki_https_port = None
 custom_pki_ajp_port = None
diff --git a/base/deploy/src/scriptlets/pkihelper.py b/base/deploy/src/scriptlets/pkihelper.py
index 1ceb658..31877bf 100644
--- a/base/deploy/src/scriptlets/pkihelper.py
+++ b/base/deploy/src/scriptlets/pkihelper.py
@@ -305,6 +305,113 @@ class identity:
         return pki_gid
 
 
+# PKI Deployment Namespace Class
+class namespace:
+    # Silently verify that the selected 'pki_instance_name' will
+    # NOT produce any namespace collisions
+    def collision_detection(self):
+        # Run simple checks for pre-existing namespace collisions
+        if os.path.exists(master['pki_instance_path']):
+            if os.path.exists(master['pki_subsystem_path']):
+                # Top-Level PKI base path collision
+                config.pki_log.error(
+                    log.PKIHELPER_NAMESPACE_COLLISION_2,
+                    master['pki_instance_id'],
+                    master['pki_instance_path'],
+                    extra=config.PKI_INDENTATION_LEVEL_2)
+                sys.exit(1)
+        else:
+            if os.path.exists(master['pki_target_tomcat_conf_instance_id']):
+                # Top-Level "/etc/sysconfig" path collision
+                config.pki_log.error(
+                    log.PKIHELPER_NAMESPACE_COLLISION_2,
+                    master['pki_instance_id'],
+                    master['pki_target_tomcat_conf_instance_id'],
+                    extra=config.PKI_INDENTATION_LEVEL_2)
+                sys.exit(1)
+            if os.path.exists(master['pki_cgroup_systemd_service']):
+                # Systemd cgroup path collision
+                config.pki_log.error(
+                    log.PKIHELPER_NAMESPACE_COLLISION_2,
+                    master['pki_instance_id'],
+                    master['pki_cgroup_systemd_service_path'],
+                    extra=config.PKI_INDENTATION_LEVEL_2)
+                sys.exit(1)
+            if os.path.exists(master['pki_cgroup_cpu_systemd_service']):
+                # Systemd cgroup CPU path collision
+                config.pki_log.error(
+                    log.PKIHELPER_NAMESPACE_COLLISION_2,
+                    master['pki_instance_id'],
+                    master['pki_cgroup_cpu_systemd_service_path'],
+                    extra=config.PKI_INDENTATION_LEVEL_2)
+                sys.exit(1)
+        if os.path.exists(master['pki_instance_log_path']) and\
+           os.path.exists(master['pki_subsystem_log_path']):
+            # Top-Level PKI log path collision
+            config.pki_log.error(
+                log.PKIHELPER_NAMESPACE_COLLISION_2,
+                master['pki_instance_id'],
+                master['pki_instance_log_path'],
+                extra=config.PKI_INDENTATION_LEVEL_2)
+            sys.exit(1)
+        if os.path.exists(master['pki_instance_configuration_path']) and\
+           os.path.exists(master['pki_subsystem_configuration_path']):
+            # Top-Level PKI configuration path collision
+            config.pki_log.error(
+                log.PKIHELPER_NAMESPACE_COLLISION_2,
+                master['pki_instance_id'],
+                master['pki_instance_configuration_path'],
+                extra=config.PKI_INDENTATION_LEVEL_2)
+            sys.exit(1)
+        if os.path.exists(master['pki_instance_registry_path']) and\
+           os.path.exists(master['pki_subsystem_registry_path']):
+            # Top-Level PKI registry path collision
+            config.pki_log.error(
+                log.PKIHELPER_NAMESPACE_COLLISION_2,
+                master['pki_instance_id'],
+                master['pki_instance_registry_path'],
+                extra=config.PKI_INDENTATION_LEVEL_2)
+            sys.exit(1)
+        # Run simple checks for reserved name namespace collisions
+        if master['pki_instance_id'] in config.PKI_BASE_RESERVED_NAMES:
+            # Top-Level PKI base path reserved name collision
+            config.pki_log.error(
+                log.PKIHELPER_NAMESPACE_RESERVED_NAME_2,
+                master['pki_instance_id'],
+                master['pki_instance_path'],
+                extra=config.PKI_INDENTATION_LEVEL_2)
+            sys.exit(1)
+        # No need to check for reserved name under Top-Level PKI log path
+        if master['pki_instance_id'] in config.PKI_CONFIGURATION_RESERVED_NAMES:
+            # Top-Level PKI configuration path reserved name collision
+            config.pki_log.error(
+                log.PKIHELPER_NAMESPACE_RESERVED_NAME_2,
+                master['pki_instance_id'],
+                master['pki_instance_configuration_path'],
+                extra=config.PKI_INDENTATION_LEVEL_2)
+            sys.exit(1)
+        if master['pki_subsystem'] in config.PKI_APACHE_SUBSYSTEMS:
+            # Top-Level Apache PKI registry path reserved name collision
+            if master['pki_instance_id'] in\
+               config.PKI_APACHE_REGISTRY_RESERVED_NAMES:
+                config.pki_log.error(
+                    log.PKIHELPER_NAMESPACE_RESERVED_NAME_2,
+                    master['pki_instance_id'],
+                    master['pki_instance_registry_path'],
+                    extra=config.PKI_INDENTATION_LEVEL_2)
+                sys.exit(1)
+        elif master['pki_subsystem'] in config.PKI_TOMCAT_SUBSYSTEMS:
+            # Top-Level Tomcat PKI registry path reserved name collision
+            if master['pki_instance_id'] in\
+               config.PKI_TOMCAT_REGISTRY_RESERVED_NAMES:
+                config.pki_log.error(
+                    log.PKIHELPER_NAMESPACE_RESERVED_NAME_2,
+                    master['pki_instance_id'],
+                    master['pki_instance_registry_path'],
+                    extra=config.PKI_INDENTATION_LEVEL_2)
+                sys.exit(1)
+
+
 # PKI Deployment Configuration File Class
 class configuration_file:
     def verify_sensitive_data(self):
@@ -346,22 +453,18 @@ class configuration_file:
                 sys.exit(1)
             # Verify existence of PKCS #12 Password (ONLY for Clones)
             if config.str2bool(master['pki_clone']):
-                if not sensitive.has_key('pki_pkcs12_password') or\
-                   not len(sensitive['pki_pkcs12_password']):
+                if not sensitive.has_key('pki_clone_pkcs12_password') or\
+                   not len(sensitive['pki_clone_pkcs12_password']):
                     config.pki_log.error(
-                        log.PKIHELPER_UNDEFINED_PKCS12_PASSWORD_1,
+                        log.PKIHELPER_UNDEFINED_CLONE_PKCS12_PASSWORD_1,
                         config.pkideployment_cfg,
                         extra=config.PKI_INDENTATION_LEVEL_2)
                     sys.exit(1)
             # Verify existence of Security Domain Password File
-            # (ONLY for Clones, Subordinate CA, KRA, OCSP, RA, TKS, or TPS)
+            # (ONLY for Clones, KRA, OCSP, TKS, or Subordinate CA)
             if config.str2bool(master['pki_clone']) or\
-               config.str2bool(master['pki_subordinate']) or\
-               master['pki_subsystem'] == "KRA" or\
-               master['pki_subsystem'] == "OCSP" or\
-               master['pki_subsystem'] == "RA" or\
-               master['pki_subsystem'] == "TKS" or\
-               master['pki_subsystem'] == "TPS":
+               not master['pki_subsystem'] == "CA" or\
+               config.str2bool(master['pki_subordinate']):
                 if not sensitive.has_key('pki_security_domain_password') or\
                    not len(sensitive['pki_security_domain_password']):
                     config.pki_log.error(
@@ -407,16 +510,16 @@ class configuration_file:
 
     def populate_non_default_ports(self):
         if master['pki_http_port'] != \
-            config.PKI_DEPLOYMENT_DEFAULT_HTTP_PORT:
+            config.PKI_DEPLOYMENT_DEFAULT_TOMCAT_HTTP_PORT:
                 ports.append(master['pki_http_port'])
         if master['pki_https_port'] != \
-            config.PKI_DEPLOYMENT_DEFAULT_HTTPS_PORT:
+            config.PKI_DEPLOYMENT_DEFAULT_TOMCAT_HTTPS_PORT:
                 ports.append(master['pki_https_port'])
         if master['pki_tomcat_server_port'] != \
             config.PKI_DEPLOYMENT_DEFAULT_TOMCAT_SERVER_PORT:
                 ports.append(master['pki_tomcat_server_port'])
         if master['pki_ajp_port'] != \
-            config.PKI_DEPLOYMENT_DEFAULT_AJP_PORT:
+            config.PKI_DEPLOYMENT_DEFAULT_TOMCAT_AJP_PORT:
                 ports.append(master['pki_ajp_port'])
         return
 
@@ -574,32 +677,6 @@ class instance:
             sys.exit(1)
         return rv
 
-    def verify_subsystem_exists(self):
-        try:
-            if not os.path.exists(master['pki_subsystem_path']):
-                config.pki_log.error(log.PKI_SUBSYSTEM_DOES_NOT_EXIST_2,
-                                     master['pki_subsystem'],
-                                     master['pki_instance_id'],
-                                     extra=config.PKI_INDENTATION_LEVEL_1)
-                sys.exit(1)
-        except OSError as exc:
-            config.pki_log.error(log.PKI_OSERROR_1, exc,
-                                 extra=config.PKI_INDENTATION_LEVEL_2)
-            sys.exit(1)
-
-    def verify_subsystem_does_not_exist(self):
-        try:
-            if os.path.exists(master['pki_subsystem_path']):
-                config.pki_log.error(log.PKI_SUBSYSTEM_ALREADY_EXISTS_2,
-                                     master['pki_subsystem'],
-                                     master['pki_instance_id'],
-                                     extra=config.PKI_INDENTATION_LEVEL_1)
-                sys.exit(1)
-        except OSError as exc:
-            config.pki_log.error(log.PKI_OSERROR_1, exc,
-                                 extra=config.PKI_INDENTATION_LEVEL_2)
-            sys.exit(1)
-
 
 # PKI Deployment Directory Class
 class directory:
@@ -2099,6 +2176,7 @@ class jython:
 
 # PKI Deployment Helper Class Instances
 identity = identity()
+namespace = namespace()
 configuration_file = configuration_file()
 #xml_file = xml_file()
 instance = instance()
diff --git a/base/deploy/src/scriptlets/pkijython.py b/base/deploy/src/scriptlets/pkijython.py
index b55c9ec..cb1c1d9 100644
--- a/base/deploy/src/scriptlets/pkijython.py
+++ b/base/deploy/src/scriptlets/pkijython.py
@@ -373,7 +373,7 @@ class rest_client:
             # Directory Server Information
             if master['pki_subsystem'] != "RA":
                 data.setDsHost(master['pki_ds_hostname'])
-                data.setDsPort(master['pki_ds_http_port'])
+                data.setDsPort(master['pki_ds_ldap_port'])
                 data.setBaseDN(master['pki_ds_base_dn'])
                 data.setBindDN(master['pki_ds_bind_dn'])
                 data.setDatabase(master['pki_ds_database'])
diff --git a/base/deploy/src/scriptlets/pkimessages.py b/base/deploy/src/scriptlets/pkimessages.py
index e4da468..9dfd454 100644
--- a/base/deploy/src/scriptlets/pkimessages.py
+++ b/base/deploy/src/scriptlets/pkimessages.py
@@ -189,6 +189,10 @@ PKIHELPER_MUTUALLY_EXCLUSIVE_CLONE_SUB_CA = "cloned CAs and subordinate "\
 PKIHELPER_MUTUALLY_EXCLUSIVE_EXTERNAL_SUB_CA = "external CAs and subordinate "\
                                                "CAs MUST be MUTUALLY "\
                                                "EXCLUSIVE in '%s'"
+PKIHELPER_NAMESPACE_COLLISION_2 = "PKI instance '%s' would produce a "\
+                                  "namespace collision with '%s'!"
+PKIHELPER_NAMESPACE_RESERVED_NAME_2 = "PKI instance '%s' is already a "\
+                                      "reserved name under '%s'!"
 PKIHELPER_NOISE_FILE_2 = "generating noise file called '%s' and "\
                          "filling it with '%d' random bytes"
 PKIHELPER_PASSWORD_CONF_1 = "generating '%s'"
@@ -211,10 +215,10 @@ PKIHELPER_UNDEFINED_BACKUP_PASSWORD_1 =\
     "A value for 'pki_backup_password' MUST be defined in '%s'"
 PKIHELPER_UNDEFINED_CLIENT_PKCS12_PASSWORD_1 =\
     "A value for 'pki_client_pkcs12_password' MUST be defined in '%s'"
+PKIHELPER_UNDEFINED_CLONE_PKCS12_PASSWORD_1 =\
+    "A value for 'pki_clone_pkcs12_password' MUST be defined in '%s'"
 PKIHELPER_UNDEFINED_DS_PASSWORD_1 =\
     "A value for 'pki_ds_password' MUST be defined in '%s'"
-PKIHELPER_UNDEFINED_PKCS12_PASSWORD_1 =\
-    "A value for 'pki_pkcs12_password' MUST be defined in '%s'"
 PKIHELPER_UNDEFINED_SECURITY_DOMAIN_PASSWORD_1 =\
     "A value for 'pki_security_domain_password' MUST be defined in '%s'"
 PKIHELPER_USER_1 = "retrieving UID for '%s' . . ."
diff --git a/base/deploy/src/scriptlets/pkiparser.py b/base/deploy/src/scriptlets/pkiparser.py
index e824c8a..7f27d89 100644
--- a/base/deploy/src/scriptlets/pkiparser.py
+++ b/base/deploy/src/scriptlets/pkiparser.py
@@ -58,6 +58,7 @@ def process_command_line_arguments(argv):
                                dest='pkideployment_cfg', action='store',
                                nargs=1, required=True, metavar='<file>',
                                help='specifies configuration filename')
+
     optional = parser.add_argument_group('optional arguments')
     optional.add_argument('--dry_run',
                           dest='pki_dry_run_flag', action='store_true',
@@ -74,26 +75,38 @@ def process_command_line_arguments(argv):
                           help='display verbose information (details below)')
     custom = parser.add_argument_group('custom arguments '
                                        '(OVERRIDES configuration file values)')
-    custom.add_argument('-d',
-                        dest='custom_pki_admin_domain_name', action='store',
-                        nargs=1, metavar='<admin_domain>',
-                        help='PKI admin domain name (instance name prefix)')
-    custom.add_argument('-i',
-                        dest='custom_pki_instance_name', action='store',
-                        nargs=1, metavar='<instance>',
-                        help='PKI instance name (MUST specify REQUIRED ports)')
-    custom.add_argument('--http_port',
-                        dest='custom_pki_http_port', action='store',
-                        nargs=1, metavar='<port>',
-                        help='HTTP port (CA, KRA, OCSP, RA, TKS, TPS)')
-    custom.add_argument('--https_port',
-                        dest='custom_pki_https_port', action='store',
-                        nargs=1, metavar='<port>',
-                        help='HTTPS port (CA, KRA, OCSP, RA, TKS, TPS)')
-    custom.add_argument('--ajp_port',
-                        dest='custom_pki_ajp_port', action='store',
-                        nargs=1, metavar='<port>',
-                        help='AJP port (CA, KRA, OCSP, TKS)')
+    if os.path.basename(argv[0]) == 'pkispawn':
+        custom.add_argument('-i',
+                            dest='custom_pki_instance_name', action='store',
+                            nargs=1, metavar='<instance>',
+                            help='PKI instance name '
+                                 '(MUST specify REQUIRED ports)')
+        custom.add_argument('-d',
+                            dest='custom_pki_admin_domain_name', action='store',
+                            nargs=1, metavar='<admin_domain>',
+                            help='PKI admin domain name (instance name suffix)')
+        custom.add_argument('--http_port',
+                            dest='custom_pki_http_port', action='store',
+                            nargs=1, metavar='<port>',
+                            help='HTTP port (CA, KRA, OCSP, RA, TKS, TPS)')
+        custom.add_argument('--https_port',
+                            dest='custom_pki_https_port', action='store',
+                            nargs=1, metavar='<port>',
+                            help='HTTPS port (CA, KRA, OCSP, RA, TKS, TPS)')
+        custom.add_argument('--ajp_port',
+                            dest='custom_pki_ajp_port', action='store',
+                            nargs=1, metavar='<port>',
+                            help='AJP port (CA, KRA, OCSP, TKS)')
+    elif os.path.basename(argv[0]) == 'pkidestroy':
+        custom.add_argument('-i',
+                            dest='custom_pki_instance_name', action='store',
+                            nargs=1, metavar='<instance>',
+                            help='PKI instance name')
+        custom.add_argument('-d',
+                            dest='custom_pki_admin_domain_name', action='store',
+                            nargs=1, metavar='<admin_domain>',
+                            help='PKI admin domain name (instance name suffix)')
+
     test = parser.add_argument_group('test arguments')
     test.add_argument('-p',
                       dest='pki_root_prefix', action='store',
@@ -119,8 +132,7 @@ def process_command_line_arguments(argv):
         parser.print_help()
         parser.exit(-1);
     if os.path.basename(argv[0]) == 'pkispawn':
-        if args.pki_update_flag:
-            config.pki_update_flag = args.pki_update_flag
+        config.pki_update_flag = args.pki_update_flag
     if args.pki_verbosity == 1:
         config.pki_jython_log_level = config.PKI_JYTHON_INFO_LOG_LEVEL
         config.pki_console_log_level = logging.INFO
@@ -143,104 +155,151 @@ def process_command_line_arguments(argv):
         config.pki_jython_log_level = config.PKI_JYTHON_WARNING_LOG_LEVEL
         config.pki_console_log_level = logging.WARNING
         config.pki_log_level = logging.INFO
-    if not args.custom_pki_admin_domain_name is None:
-        config.custom_pki_admin_domain_name =\
-            str(args.custom_pki_admin_domain_name).strip('[\']')
     if not args.custom_pki_instance_name is None:
         config.custom_pki_instance_name =\
             str(args.custom_pki_instance_name).strip('[\']')
-    if not args.custom_pki_http_port is None:
-        config.custom_pki_http_port =\
-            str(args.custom_pki_http_port).strip('[\']')
-    if not args.custom_pki_https_port is None:
-        config.custom_pki_https_port =\
-            str(args.custom_pki_https_port).strip('[\']')
-    if not args.custom_pki_ajp_port is None:
-        if config.pki_subsystem in config.PKI_TOMCAT_SUBSYSTEMS:
-            config.custom_pki_ajp_port =\
-                str(args.custom_pki_ajp_port).strip('[\']')
+    if not args.custom_pki_admin_domain_name is None:
+        config.custom_pki_admin_domain_name =\
+            str(args.custom_pki_admin_domain_name).strip('[\']')
+    if config.pki_subsystem in config.PKI_APACHE_SUBSYSTEMS:
+        if not config.custom_pki_instance_name is None:
+            default_pki_instance_name = config.custom_pki_instance_name
         else:
-            print "ERROR:  " +\
-                  log.PKI_CUSTOM_TOMCAT_AJP_PORT_1 %\
-                  config.pki_subsystem
-            print
-            parser.print_help()
-            parser.exit(-1);
-    if not args.custom_pki_instance_name is None or\
-       not args.custom_pki_http_port is None or\
-       not args.custom_pki_https_port is None or\
-       not args.custom_pki_ajp_port is None:
-        if config.pki_subsystem in config.PKI_APACHE_SUBSYSTEMS:
-            if args.custom_pki_instance_name is None or\
-               args.custom_pki_http_port is None or\
-               args.custom_pki_https_port is None:
-                print "ERROR:  " + log.PKI_CUSTOM_APACHE_INSTANCE_1 %\
-                      config.pki_subsystem
+            default_pki_instance_name =\
+                config.PKI_DEPLOYMENT_DEFAULT_APACHE_INSTANCE_NAME
+        if not config.custom_pki_admin_domain_name is None:
+            default_pki_instance_path =\
+                config.pki_root_prefix +\
+                config.PKI_DEPLOYMENT_BASE_ROOT + "/" +\
+                default_pki_instance_name + "." +\
+                config.custom_pki_admin_domain_name + "/" +\
+                config.pki_subsystem.lower()
+        else:
+            default_pki_instance_path =\
+                config.pki_root_prefix +\
+                config.PKI_DEPLOYMENT_BASE_ROOT + "/" +\
+                default_pki_instance_name + "/" +\
+                config.pki_subsystem.lower()
+    elif config.pki_subsystem in config.PKI_TOMCAT_SUBSYSTEMS:
+        if not config.custom_pki_instance_name is None:
+            default_pki_instance_name = config.custom_pki_instance_name
+        else:
+            default_pki_instance_name =\
+                config.PKI_DEPLOYMENT_DEFAULT_TOMCAT_INSTANCE_NAME
+        if not config.custom_pki_admin_domain_name is None:
+            default_pki_instance_path =\
+                config.pki_root_prefix +\
+                config.PKI_DEPLOYMENT_BASE_ROOT + "/" +\
+                default_pki_instance_name + "." +\
+                config.custom_pki_admin_domain_name + "/" +\
+                config.pki_subsystem.lower()
+        else:
+            default_pki_instance_path =\
+                config.pki_root_prefix +\
+                config.PKI_DEPLOYMENT_BASE_ROOT + "/" +\
+                default_pki_instance_name + "/" +\
+                config.pki_subsystem.lower()
+    if os.path.basename(argv[0]) == 'pkispawn':
+        if args.pki_update_flag:
+            # "respawn"
+            if not os.path.exists(default_pki_instance_path):
+                print "ERROR:  " + log.PKI_SUBSYSTEM_DOES_NOT_EXIST_2 %\
+                      (config.pki_subsystem, default_pki_instance_name)
                 print
-                parser.print_help()
                 parser.exit(-1);
-        elif config.pki_subsystem in config.PKI_TOMCAT_SUBSYSTEMS:
-            if args.custom_pki_instance_name is None or\
-               args.custom_pki_http_port is None or\
-               args.custom_pki_https_port is None or\
-               args.custom_pki_ajp_port is None:
-                print "ERROR:  " + log.PKI_CUSTOM_TOMCAT_INSTANCE_1 %\
+        else:
+            # "spawn"
+            if os.path.exists(default_pki_instance_path):
+                print "ERROR:  " + log.PKI_SUBSYSTEM_ALREADY_EXISTS_2 %\
+                      (config.pki_subsystem, default_pki_instance_name)
+                print
+                parser.exit(-1);
+        config.pkideployment_cfg = str(args.pkideployment_cfg).strip('[\']')
+        if not args.custom_pki_http_port is None:
+            config.custom_pki_http_port =\
+                str(args.custom_pki_http_port).strip('[\']')
+        if not args.custom_pki_https_port is None:
+            config.custom_pki_https_port =\
+                str(args.custom_pki_https_port).strip('[\']')
+        if not args.custom_pki_ajp_port is None:
+            if config.pki_subsystem in config.PKI_TOMCAT_SUBSYSTEMS:
+                config.custom_pki_ajp_port =\
+                    str(args.custom_pki_ajp_port).strip('[\']')
+            else:
+                print "ERROR:  " +\
+                      log.PKI_CUSTOM_TOMCAT_AJP_PORT_1 %\
                       config.pki_subsystem
                 print
                 parser.print_help()
                 parser.exit(-1);
-    if os.path.basename(argv[0]) == 'pkispawn':
-        config.pkideployment_cfg = str(args.pkideployment_cfg).strip('[\']')
+        if not args.custom_pki_instance_name is None or\
+           not args.custom_pki_http_port is None or\
+           not args.custom_pki_https_port is None or\
+           not args.custom_pki_ajp_port is None:
+            if config.pki_subsystem in config.PKI_APACHE_SUBSYSTEMS:
+                if args.custom_pki_instance_name is None or\
+                   args.custom_pki_http_port is None or\
+                   args.custom_pki_https_port is None:
+                    print "ERROR:  " + log.PKI_CUSTOM_APACHE_INSTANCE_1 %\
+                          config.pki_subsystem
+                    print
+                    parser.print_help()
+                    parser.exit(-1);
+            elif config.pki_subsystem in config.PKI_TOMCAT_SUBSYSTEMS:
+                if args.custom_pki_instance_name is None or\
+                   args.custom_pki_http_port is None or\
+                   args.custom_pki_https_port is None or\
+                   args.custom_pki_ajp_port is None:
+                    print "ERROR:  " + log.PKI_CUSTOM_TOMCAT_INSTANCE_1 %\
+                          config.pki_subsystem
+                    print
+                    parser.print_help()
+                    parser.exit(-1);
     elif os.path.basename(argv[0]) == 'pkidestroy':
-        # NOTE:  When performing 'pkidestroy', a configuration file must be
-        #        explicitly specified if it does not use the default location
-        #        and/or default configuration file name.
+        # NOTE:  When performing 'pkidestroy', a 'pki_instance_name' and/or
+        #        a 'pki_admin_domain_name' MUST be explicitly specified if
+        #        a PKI instance has NOT been installed in the default location
+        #        using the default PKI instance name!
+        if not os.path.exists(default_pki_instance_path):
+            print "ERROR:  " + log.PKI_SUBSYSTEM_DOES_NOT_EXIST_2 %\
+                  (config.pki_subsystem, default_pki_instance_name)
+            print
+            parser.exit(-1);
         if config.pki_subsystem in config.PKI_APACHE_SUBSYSTEMS:
-            if not config.custom_pki_instance_name is None:
-                default_pki_instance_name = config.custom_pki_instance_name
-            else:
-                default_pki_instance_name =\
-                    config.PKI_DEPLOYMENT_DEFAULT_APACHE_INSTANCE_NAME
             if not config.custom_pki_admin_domain_name is None:
-                config.pkideployment_cfg =\
+                default_pki_instance_registry_path =\
                     config.pki_root_prefix +\
                     config.PKI_DEPLOYMENT_REGISTRY_ROOT + "/" +\
-                    config.PKI_DEPLOYMENT_DEFAULT_APACHE_INSTANCE_NAME + "/" +\
-                    config.custom_pki_admin_domain_name + "-" +\
-                    default_pki_instance_name +"/" +\
-                    config.pki_subsystem.lower() +"/" +\
-                    config.PKI_DEPLOYMENT_DEFAULT_CONFIGURATION_FILE
+                    config.PKI_DEPLOYMENT_DEFAULT_APACHE_SERVICE_NAME + "/" +\
+                    default_pki_instance_name + "." +\
+                    config.custom_pki_admin_domain_name + "/" +\
+                    config.pki_subsystem.lower()
             else:
-                config.pkideployment_cfg =\
+                default_pki_instance_registry_path =\
                     config.pki_root_prefix +\
                     config.PKI_DEPLOYMENT_REGISTRY_ROOT + "/" +\
-                    config.PKI_DEPLOYMENT_DEFAULT_APACHE_INSTANCE_NAME + "/" +\
-                    default_pki_instance_name +"/" +\
-                    config.pki_subsystem.lower() +"/" +\
-                    config.PKI_DEPLOYMENT_DEFAULT_CONFIGURATION_FILE
+                    config.PKI_DEPLOYMENT_DEFAULT_APACHE_SERVICE_NAME + "/" +\
+                    default_pki_instance_name + "/" +\
+                    config.pki_subsystem.lower()
         elif config.pki_subsystem in config.PKI_TOMCAT_SUBSYSTEMS:
-            if not config.custom_pki_instance_name is None:
-                default_pki_instance_name = config.custom_pki_instance_name
-            else:
-                default_pki_instance_name =\
-                    config.PKI_DEPLOYMENT_DEFAULT_TOMCAT_INSTANCE_NAME
             if not config.custom_pki_admin_domain_name is None:
-                config.pkideployment_cfg =\
+                default_pki_instance_registry_path =\
                     config.pki_root_prefix +\
                     config.PKI_DEPLOYMENT_REGISTRY_ROOT + "/" +\
-                    config.PKI_DEPLOYMENT_DEFAULT_TOMCAT_INSTANCE_NAME + "/" +\
-                    config.custom_pki_admin_domain_name + "-" +\
-                    default_pki_instance_name +"/" +\
-                    config.pki_subsystem.lower() +"/" +\
-                    config.PKI_DEPLOYMENT_DEFAULT_CONFIGURATION_FILE
+                    config.PKI_DEPLOYMENT_DEFAULT_TOMCAT_SERVICE_NAME + "/" +\
+                    default_pki_instance_name + "." +\
+                    config.custom_pki_admin_domain_name + "/" +\
+                    config.pki_subsystem.lower()
             else:
-                config.pkideployment_cfg =\
+                default_pki_instance_registry_path =\
                     config.pki_root_prefix +\
                     config.PKI_DEPLOYMENT_REGISTRY_ROOT + "/" +\
-                    config.PKI_DEPLOYMENT_DEFAULT_TOMCAT_INSTANCE_NAME + "/" +\
-                    default_pki_instance_name +"/" +\
-                    config.pki_subsystem.lower() +"/" +\
-                    config.PKI_DEPLOYMENT_DEFAULT_CONFIGURATION_FILE
+                    config.PKI_DEPLOYMENT_DEFAULT_TOMCAT_SERVICE_NAME + "/" +\
+                    default_pki_instance_name + "/" +\
+                    config.pki_subsystem.lower()
+        config.pkideployment_cfg =\
+            default_pki_instance_registry_path + "/" +\
+            config.PKI_DEPLOYMENT_DEFAULT_CONFIGURATION_FILE
     if not os.path.exists(config.pkideployment_cfg) or\
        not os.path.isfile(config.pkideployment_cfg):
         print "ERROR:  " +\
@@ -333,21 +392,21 @@ def compose_pki_master_dictionary():
         #             two pki subystems.
         #
         #             Optionally, to more clearly distinguish a "PKI instance",
-        #             a common PKI "Admin Domain" may be used as a prefix to
+        #             a common PKI "Admin Domain" may be used as a suffix to
         #             either an "Apache web instance", or a
         #             "Tomcat web instance".
         #
         #             Thus, a specific "PKI instance" of a CA, KRA, OCSP,
         #             or TKS subystem must be referenced via the name of
         #             the particular PKI "Tomcat web instance" containing
-        #             this PKI subsystem optionally preceded by a
-        #             specified PKI "Admin Domain" separated via a "-".
+        #             this PKI subsystem optionally followed by a
+        #             specified PKI "Admin Domain" separated via a ".".
         #
         #             Likewise, a specific "PKI instance" of an RA, or TPS
         #             subystem must be referenced via the name of
         #             the particular PKI "Apache web instance" containing
-        #             this PKI subsystem optionally preceded by a
-        #             specified PKI "Admin Domain" separated via a "-".
+        #             this PKI subsystem optionally followed by a
+        #             specified PKI "Admin Domain" separated via a ".".
         #
         #             To emulate the original behavior of having a CA and
         #             KRA be unique PKI instances, each must be located
@@ -362,13 +421,13 @@ def compose_pki_master_dictionary():
         #           (e. g. Tomcat:  "pki-ca", "pki-kra", "pki-ocsp", "pki-tks")
         #           (e. g. Apache:  "pki-ra", "pki-tps")
         #     NEW:  "[${pki_admin_domain_name}-]${pki_instance_name}"
-        #           (e. g. Tomcat:  "tomcat", "example.com-tomcat")
-        #           (e. g. Apache:  "apache", "example.com-apache")
+        #           (e. g. Tomcat:  "pki-tomcat", "pki-tomcat.example.com")
+        #           (e. g. Apache:  "pki-apache", "pki-apache.example.com")
         #
         if len(config.pki_master_dict['pki_admin_domain_name']):
             config.pki_master_dict['pki_instance_id'] =\
-                config.pki_master_dict['pki_admin_domain_name'] +\
-                "-" + config.pki_master_dict['pki_instance_name']
+                config.pki_master_dict['pki_instance_name'] + "." +\
+                config.pki_master_dict['pki_admin_domain_name']
         else:
             config.pki_master_dict['pki_instance_id'] =\
                 config.pki_master_dict['pki_instance_name']
@@ -512,6 +571,20 @@ def compose_pki_master_dictionary():
                 config.pki_master_dict['pki_source_transportcert_profile'] =\
                     os.path.join(config.pki_master_dict['pki_source_conf_path'],
                                  "transportCert.profile")
+        config.pki_master_dict['pki_cgroup_systemd_service_path'] =\
+            os.path.join("/sys/fs/cgroup/systemd/system",
+                         config.pki_master_dict['pki_systemd_service'])
+        config.pki_master_dict['pki_cgroup_systemd_service'] =\
+            os.path.join(
+                config.pki_master_dict['pki_cgroup_systemd_service_path'],
+                config.pki_master_dict['pki_instance_id'])
+        config.pki_master_dict['pki_cgroup_cpu_systemd_service_path'] =\
+            os.path.join("/sys/fs/cgroup/cpu\,cpuacct/system",
+                         config.pki_master_dict['pki_systemd_service'])
+        config.pki_master_dict['pki_cgroup_cpu_systemd_service'] =\
+            os.path.join(
+                config.pki_master_dict['pki_cgroup_cpu_systemd_service_path'],
+                config.pki_master_dict['pki_instance_id'])
         # PKI top-level file system layout name/value pairs
         # NOTE:  Never use 'os.path.join()' whenever 'pki_root_prefix'
         #        is being prepended!!!
@@ -697,6 +770,9 @@ def compose_pki_master_dictionary():
             config.pki_master_dict['pki_nsutil'] =\
                 os.path.join(config.PKI_DEPLOYMENT_PKI_JAR_SOURCE_ROOT,
                              "pki-nsutil.jar")
+            config.pki_master_dict['pki_resteasy_atom_provider_jar'] =\
+                os.path.join(config.PKI_DEPLOYMENT_RESTEASY_JAR_SOURCE_ROOT,
+                             "resteasy-atom-provider.jar")
             config.pki_master_dict['pki_resteasy_jaxb_provider_jar'] =\
                 os.path.join(config.PKI_DEPLOYMENT_RESTEASY_JAR_SOURCE_ROOT,
                              "resteasy-jaxb-provider.jar")
@@ -793,6 +869,10 @@ def compose_pki_master_dictionary():
                 os.path.join(
                     config.pki_master_dict['pki_tomcat_common_lib_path'],
                     "pki-nsutil.jar")
+            config.pki_master_dict['pki_resteasy_atom_provider_jar_link'] =\
+                os.path.join(
+                    config.pki_master_dict['pki_tomcat_common_lib_path'],
+                    "resteasy-atom-provider.jar")
             config.pki_master_dict['pki_resteasy_jaxb_provider_jar_link'] =\
                 os.path.join(
                     config.pki_master_dict['pki_tomcat_common_lib_path'],
@@ -1588,8 +1668,8 @@ def compose_pki_master_dictionary():
         #     deployment configuration file and are NOT redefined below:
         #
         #         config.pki_master_dict['pki_ds_bind_dn']
-        #         config.pki_master_dict['pki_ds_http_port']
-        #         config.pki_master_dict['pki_ds_https_port']
+        #         config.pki_master_dict['pki_ds_ldap_port']
+        #         config.pki_master_dict['pki_ds_ldaps_port']
         #         config.pki_sensitive_dict['pki_ds_password']
         #         config.pki_master_dict['pki_ds_remove_data']
         #         config.pki_master_dict['pki_ds_secure_connection']
@@ -1606,7 +1686,7 @@ def compose_pki_master_dictionary():
                 "o=" + config.pki_master_dict['pki_instance_id']
         if not len(config.pki_master_dict['pki_ds_database']):
             config.pki_master_dict['pki_ds_database'] =\
-                "o=" + config.pki_master_dict['pki_instance_id']
+                config.pki_master_dict['pki_instance_id']
         if not len(config.pki_master_dict['pki_ds_hostname']):
             # Guess that the Directory Server resides on the local host
             config.pki_master_dict['pki_ds_hostname'] =\
diff --git a/specs/pki-core.spec b/specs/pki-core.spec
index 1ef05cc..58b8df0 100644
--- a/specs/pki-core.spec
+++ b/specs/pki-core.spec
@@ -14,7 +14,7 @@ distutils.sysconfig import get_python_lib; print(get_python_lib(1))")}
 
 Name:             pki-core
 Version:          10.0.0
-Release:          %{?relprefix}19%{?prerel}%{?dist}
+Release:          %{?relprefix}20%{?prerel}%{?dist}
 Summary:          Certificate System - PKI Core Components
 URL:              http://pki.fedoraproject.org/
 License:          GPLv2
@@ -44,6 +44,9 @@ BuildRequires:    xerces-j2
 %if 0%{?fedora} >= 17
 BuildRequires:    resteasy >= 2.3.2-1
 BuildRequires:    junit
+# NOTE:  The following requirement is for nightly 'mock' builds ONLY since
+#        Dogtag 10 will NEVER be officially released on Fedora 17!
+BuildRequires:    tomcatjss >= 7.0.0
 %else
 BuildRequires:    junit4
 %endif
@@ -1431,6 +1434,10 @@ fi
 
 
 %changelog
+* Tue Jul 24 2012 Matthew Harmsen <mharmsen@redhat.com> 10.0.0-0.20.a1
+- PKI TRAC Task #254 - Dogtag 10: Fix spec file to build successfully
+  via mock on Fedora 17 . . .
+
 * Wed Jul 11 2012 Matthew Harmsen <mharmsen@redhat.com> 10.0.0-0.19.a1
 - Moved 'pki-jndi-real.jar' link from 'tomcat6' to 'tomcat' (Tomcat 7)
 
-- 
1.7.10.4

