pyldb: avoid segfault when adding an element with no name
[kai/samba-autobuild/.git] / selftest / target / Samba4.pm
index c0f557999ebf54f2d5248ad519ffb210fb416fa1..6f4a31d357af22aa247a35ecf08f5ea752c7db5d 100755 (executable)
@@ -217,9 +217,9 @@ sub wait_for_start($$)
                $count++;
        } while ($ret != 0 && $count < 20);
        if ($count == 20) {
-               warn("nbt not reachable after 20 retries\n");
                teardown_env($self, $testenv_vars);
-               return 0;
+               warn("nbt not reachable after 20 retries\n");
+               return -1;
        }
 
        # Ensure we have the first RID Set before we start tests.  This makes the tests more reliable.
@@ -254,10 +254,11 @@ sub wait_for_start($$)
                while (system("$cmd >/dev/null") != 0) {
                        $count++;
                        if ($count > $max_wait) {
+                               teardown_env($self, $testenv_vars);
                                warn("Timed out ($max_wait sec) waiting for working LDAP and a RID Set to be allocated by $testenv_vars->{NETBIOSNAME} PID $testenv_vars->{SAMBA_PID}");
-                               $ret = -1;
-                               last;
+                               return -1;
                        }
+                       print "Waiting for working LDAP...\n";
                        sleep(1);
                }
        }
@@ -278,14 +279,45 @@ sub wait_for_start($$)
                $count++;
        } while ($ret != 0 && $count < 20);
        if ($count == 20) {
-               warn("winbind not reachable after 20 retries\n");
                teardown_env($self, $testenv_vars);
-               return 0;
+               warn("winbind not reachable after 20 retries\n");
+               return -1;
+       }
+
+       # Ensure we registered all our names
+       if ($testenv_vars->{SERVER_ROLE} eq "domain controller") {
+               my $max_wait = 60;
+               print "Waiting for dns_update_cache to be created.\n";
+               $count = 0;
+               while (not -e "$testenv_vars->{PRIVATEDIR}/dns_update_cache") {
+                       $count++;
+                       if ($count > $max_wait) {
+                               teardown_env($self, $testenv_vars);
+                               warn("Timed out ($max_wait sec) waiting for dns_update_cache PID $testenv_vars->{SAMBA_PID}");
+                               return -1;
+                       }
+                       print "Waiting for dns_update_cache to be created...\n";
+                       sleep(1);
+               }
+               print "Waiting for dns_update_cache to be filled.\n";
+               $count = 0;
+               while ((-s "$testenv_vars->{PRIVATEDIR}/dns_update_cache") == 0) {
+                       $count++;
+                       if ($count > $max_wait) {
+                               teardown_env($self, $testenv_vars);
+                               warn("Timed out ($max_wait sec) waiting for dns_update_cache PID $testenv_vars->{SAMBA_PID}");
+                               return -1;
+                       }
+                       print "Waiting for dns_update_cache to be filled...\n";
+                       sleep(1);
+               }
        }
 
        print $self->getlog_env($testenv_vars);
 
-       return $ret
+       print "READY ($testenv_vars->{SAMBA_PID})\n";
+
+       return 0
 }
 
 sub write_ldb_file($$$)
@@ -301,12 +333,13 @@ sub write_ldb_file($$$)
 sub add_wins_config($$)
 {
        my ($self, $privatedir) = @_;
+       my $client_ip = Samba::get_ipv4_addr("client");
 
        return $self->write_ldb_file("$privatedir/wins_config.ldb", "
 dn: name=TORTURE_11,CN=PARTNERS
 objectClass: wreplPartner
 name: TORTURE_11
-address: 127.0.0.11
+address: $client_ip
 pullInterval: 0
 pushChangeCount: 0
 type: 0x3
@@ -353,25 +386,19 @@ sub setup_dns_hub_internal($$$)
                warn("Unable to clean up");
        }
 
-       my $swiface = Samba::get_interface($hostname);
-
        my $env = undef;
-       $env->{prefix} = $prefix;
-       $env->{prefix_abs} = $prefix_abs;
+       $env->{NETBIOSNAME} = $hostname;
 
-       $env->{hostname} = $hostname;
-       $env->{swiface} = $swiface;
-
-       $env->{ipv4} = "127.0.0.$swiface";
-       $env->{ipv6} = sprintf("fd00:0000:0000:0000:0000:0000:5357:5f%02x", $swiface);
+       $env->{SERVER_IP} = Samba::get_ipv4_addr($hostname);
+       $env->{SERVER_IPV6} = Samba::get_ipv6_addr($hostname);
 
        $env->{DNS_HUB_LOG} = "$prefix_abs/dns_hub.log";
 
        $env->{RESOLV_CONF} = "$prefix_abs/resolv.conf";
 
        open(RESOLV_CONF, ">$env->{RESOLV_CONF}");
-       print RESOLV_CONF "nameserver $env->{ipv4}\n";
-       print RESOLV_CONF "nameserver $env->{ipv6}\n";
+       print RESOLV_CONF "nameserver $env->{SERVER_IP}\n";
+       print RESOLV_CONF "nameserver $env->{SERVER_IPV6}\n";
        close(RESOLV_CONF);
 
        # use a pipe for stdin in the child processes. This allows
@@ -388,6 +415,7 @@ sub setup_dns_hub_internal($$$)
                open STDOUT, "| tee $env->{DNS_HUB_LOG} 1>&2";
                open STDERR, '>&STDOUT';
 
+               my $swiface = Samba::get_interface($hostname);
                SocketWrapper::set_default_iface($swiface);
                my $pcap_file = "$ENV{SOCKET_WRAPPER_PCAP_DIR}/env-$hostname$.pcap";
                SocketWrapper::setup_pcap($pcap_file);
@@ -403,7 +431,8 @@ sub setup_dns_hub_internal($$$)
                }
                $ENV{MAKE_TEST_BINARY} = "$self->{srcdir}/selftest/target/dns_hub.py";
                push (@args, "$self->{server_maxtime}");
-               push (@args, "$env->{ipv4}");
+               push (@args, "$env->{SERVER_IP}");
+               push (@args, Samba::realm_to_ip_mappings());
                close($env->{STDIN_PIPE});
                open STDIN, ">&", $STDIN_READER or die "can't dup STDIN_READER to STDIN: $!";
 
@@ -411,7 +440,7 @@ sub setup_dns_hub_internal($$$)
                        or die("Unable to start $ENV{MAKE_TEST_BINARY}: $!");
        }
        $env->{SAMBA_PID} = $pid;
-       $env->{KRB5_CONFIG} = "${prefix_abs}/no_krb5.conf";
+       $env->{KRB5_CONFIG} = "$prefix_abs/no_krb5.conf";
        close($STDIN_READER);
 
        print "DONE\n";
@@ -443,6 +472,25 @@ sub get_dns_hub_env($)
        return undef;
 }
 
+# Returns the environmental variables that we pass to samba-tool commands
+sub get_cmd_env_vars
+{
+       my ($self, $localenv) = @_;
+
+       my $cmd_env = "NSS_WRAPPER_HOSTS='$localenv->{NSS_WRAPPER_HOSTS}' ";
+       $cmd_env .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$localenv->{SOCKET_WRAPPER_DEFAULT_IFACE}\" ";
+       if (defined($localenv->{RESOLV_WRAPPER_CONF})) {
+               $cmd_env .= "RESOLV_WRAPPER_CONF=\"$localenv->{RESOLV_WRAPPER_CONF}\" ";
+       } else {
+               $cmd_env .= "RESOLV_WRAPPER_HOSTS=\"$localenv->{RESOLV_WRAPPER_HOSTS}\" ";
+       }
+       $cmd_env .= " KRB5_CONFIG=\"$localenv->{KRB5_CONFIG}\" ";
+       $cmd_env .= "KRB5CCNAME=\"$localenv->{KRB5_CCACHE}\" ";
+       $cmd_env .= "RESOLV_CONF=\"$localenv->{RESOLV_CONF}\" ";
+
+       return $cmd_env;
+}
+
 sub setup_namespaces($$:$$)
 {
        my ($self, $localenv, $upn_array, $spn_array) = @_;
@@ -461,16 +509,7 @@ sub setup_namespaces($$:$$)
 
        my $samba_tool =  Samba::bindir_path($self, "samba-tool");
 
-       my $cmd_env = "NSS_WRAPPER_HOSTS='$localenv->{NSS_WRAPPER_HOSTS}' ";
-       $cmd_env .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$localenv->{SOCKET_WRAPPER_DEFAULT_IFACE}\" ";
-       if (defined($localenv->{RESOLV_WRAPPER_CONF})) {
-               $cmd_env .= "RESOLV_WRAPPER_CONF=\"$localenv->{RESOLV_WRAPPER_CONF}\" ";
-       } else {
-               $cmd_env .= "RESOLV_WRAPPER_HOSTS=\"$localenv->{RESOLV_WRAPPER_HOSTS}\" ";
-       }
-       $cmd_env .= " KRB5_CONFIG=\"$localenv->{KRB5_CONFIG}\" ";
-       $cmd_env .= "KRB5CCNAME=\"$localenv->{KRB5_CCACHE}\" ";
-       $cmd_env .= "RESOLV_CONF=\"$localenv->{RESOLV_CONF}\" ";
+       my $cmd_env = $self->get_cmd_env_vars($localenv);
 
        my $cmd_config = " $localenv->{CONFIGURATION}";
 
@@ -490,9 +529,7 @@ sub setup_trust($$$$$)
        my ($self, $localenv, $remoteenv, $type, $extra_args) = @_;
 
        $localenv->{TRUST_SERVER} = $remoteenv->{SERVER};
-       $localenv->{TRUST_SERVER_IP} = $remoteenv->{SERVER_IP};
-       $localenv->{TRUST_SERVER_IPV6} = $remoteenv->{SERVER_IPV6};
-       $localenv->{TRUST_NETBIOSNAME} = $remoteenv->{NETBIOSNAME};
+
        $localenv->{TRUST_USERNAME} = $remoteenv->{USERNAME};
        $localenv->{TRUST_PASSWORD} = $remoteenv->{PASSWORD};
        $localenv->{TRUST_DOMAIN} = $remoteenv->{DOMAIN};
@@ -502,16 +539,7 @@ sub setup_trust($$$$$)
        my $samba_tool =  Samba::bindir_path($self, "samba-tool");
 
        # setup the trust
-       my $cmd_env = "NSS_WRAPPER_HOSTS='$localenv->{NSS_WRAPPER_HOSTS}' ";
-       $cmd_env .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$localenv->{SOCKET_WRAPPER_DEFAULT_IFACE}\" ";
-       if (defined($localenv->{RESOLV_WRAPPER_CONF})) {
-               $cmd_env .= "RESOLV_WRAPPER_CONF=\"$localenv->{RESOLV_WRAPPER_CONF}\" ";
-       } else {
-               $cmd_env .= "RESOLV_WRAPPER_HOSTS=\"$localenv->{RESOLV_WRAPPER_HOSTS}\" ";
-       }
-       $cmd_env .= " KRB5_CONFIG=\"$localenv->{KRB5_CONFIG}\" ";
-       $cmd_env .= "KRB5CCNAME=\"$localenv->{KRB5_CCACHE}\" ";
-       $cmd_env .= "RESOLV_CONF=\"$localenv->{RESOLV_CONF}\" ";
+       my $cmd_env = $self->get_cmd_env_vars($localenv);
 
        my $cmd_config = " $localenv->{CONFIGURATION}";
        my $cmd_creds = $cmd_config;
@@ -642,9 +670,8 @@ sub provision_raw_prepare($$$$$$$$$$$$)
 
        $ctx->{tlsdir} = "$ctx->{privatedir}/tls";
 
-       $ctx->{ipv4} = "127.0.0.$swiface";
-       $ctx->{ipv6} = sprintf("fd00:0000:0000:0000:0000:0000:5357:5f%02x", $swiface);
-       $ctx->{interfaces} = "$ctx->{ipv4}/8 $ctx->{ipv6}/64";
+       $ctx->{ipv4} = Samba::get_ipv4_addr($hostname);
+       $ctx->{ipv6} = Samba::get_ipv6_addr($hostname);
 
        push(@{$ctx->{directories}}, $ctx->{privatedir});
        push(@{$ctx->{directories}}, $ctx->{binddnsdir});
@@ -752,6 +779,8 @@ sub provision_raw_step1($$)
                $services = "+smb -s3fs";
        }
 
+       my $interfaces = Samba::get_interfaces_config($ctx->{netbiosname});
+
        print CONFFILE "
 [global]
        netbios name = $ctx->{netbiosname}
@@ -768,7 +797,7 @@ sub provision_raw_step1($$)
        winbindd socket directory = $ctx->{winbindd_socket_dir}
        ntp signd socket directory = $ctx->{ntp_signd_socket_dir}
        winbind separator = /
-       interfaces = $ctx->{interfaces}
+       interfaces = $interfaces
        tls dh params file = $ctx->{tlsdir}/dhparms.pem
        tls crlfile = ${crlfile}
        tls verify peer = no_check
@@ -801,6 +830,7 @@ sub provision_raw_step1($$)
        winbind enum groups = yes
 
         rpc server port:netlogon = 1026
+       include system krb5 conf = no
 
 ";
 
@@ -875,21 +905,30 @@ nogroup:x:65534:nobody
                return undef;
        }
 
+       # Return the environment variables for the new testenv DC.
+       # Note that we have SERVER_X and DC_SERVER_X variables (which have the same
+       # value initially). In a 2 DC setup, $DC_SERVER_X will always be the PDC.
        my $ret = {
                KRB5_CONFIG => $ctx->{krb5_conf},
                KRB5_CCACHE => $ctx->{krb5_ccache},
                MITKDC_CONFIG => $ctx->{mitkdc_conf},
                PIDDIR => $ctx->{piddir},
                SERVER => $ctx->{hostname},
+               DC_SERVER => $ctx->{hostname},
                SERVER_IP => $ctx->{ipv4},
+               DC_SERVER_IP => $ctx->{ipv4},
                SERVER_IPV6 => $ctx->{ipv6},
+               DC_SERVER_IPV6 => $ctx->{ipv6},
                NETBIOSNAME => $ctx->{netbiosname},
+               DC_NETBIOSNAME => $ctx->{netbiosname},
                DOMAIN => $ctx->{domain},
                USERNAME => $ctx->{username},
+               DC_USERNAME => $ctx->{username},
                REALM => $ctx->{realm},
                DNSNAME => $ctx->{dnsname},
                SAMSID => $ctx->{samsid},
                PASSWORD => $ctx->{password},
+               DC_PASSWORD => $ctx->{password},
                LDAPDIR => $ctx->{ldapdir},
                LDAP_INSTANCE => $ctx->{ldap_instance},
                SELFTEST_WINBINDD_SOCKET_DIR => $ctx->{winbindd_socket_dir},
@@ -959,6 +998,7 @@ sub provision_raw_step2($$$)
        $ldbmodify .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" ";
        $ldbmodify .= "KRB5CCNAME=\"$ret->{KRB5_CCACHE}\" ";
        $ldbmodify .= Samba::bindir_path($self, "ldbmodify");
+       $ldbmodify .=  " --configfile=$ctx->{smb_conf}";
        my $base_dn = "DC=".join(",DC=", split(/\./, $ctx->{realm}));
 
        if ($ctx->{server_role} ne "domain controller") {
@@ -1059,7 +1099,7 @@ servicePrincipalName: http/testupnspn.$ctx->{dnsname}
        $ldbmodify .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" ";
        $ldbmodify .= "KRB5CCNAME=\"$ret->{KRB5_CCACHE}\" ";
        $ldbmodify .= Samba::bindir_path($self, "ldbmodify");
-
+       $ldbmodify .=  " --configfile=$ctx->{smb_conf}";
        my $base_dn = "DC=".join(",DC=", split(/\./, $ctx->{realm}));
        my $user_dn = "cn=jane,cn=users,$base_dn";
 
@@ -1233,6 +1273,22 @@ $extra_smbconf_shares
        return $self->provision_raw_step2($ctx, $ret);
 }
 
+# For multi-DC testenvs, we want $DC_SERVER to always be the PDC (i.e. the
+# original DC) in the testenv. $SERVER is always the joined DC that we are
+# actually running the test against
+sub set_pdc_env_vars
+{
+       my ($self, $env, $dcvars) = @_;
+
+       $env->{DC_SERVER} = $dcvars->{DC_SERVER};
+       $env->{DC_SERVER_IP} = $dcvars->{DC_SERVER_IP};
+       $env->{DC_SERVER_IPV6} = $dcvars->{DC_SERVER_IPV6};
+       $env->{DC_SERVERCONFFILE} = $dcvars->{SERVERCONFFILE};
+       $env->{DC_NETBIOSNAME} = $dcvars->{DC_NETBIOSNAME};
+       $env->{DC_USERNAME} = $dcvars->{DC_USERNAME};
+       $env->{DC_PASSWORD} = $dcvars->{DC_PASSWORD};
+}
+
 sub provision_s4member($$$$$)
 {
        my ($self, $prefix, $dcvars, $hostname, $more_conf) = @_;
@@ -1275,16 +1331,7 @@ rpc_server:tcpip = no
        }
 
        my $samba_tool =  Samba::bindir_path($self, "samba-tool");
-       my $cmd = "NSS_WRAPPER_HOSTS='$ret->{NSS_WRAPPER_HOSTS}' ";
-       $cmd .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$ret->{SOCKET_WRAPPER_DEFAULT_IFACE}\" ";
-       if (defined($ret->{RESOLV_WRAPPER_CONF})) {
-               $cmd .= "RESOLV_WRAPPER_CONF=\"$ret->{RESOLV_WRAPPER_CONF}\" ";
-       } else {
-               $cmd .= "RESOLV_WRAPPER_HOSTS=\"$ret->{RESOLV_WRAPPER_HOSTS}\" ";
-       }
-       $cmd .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" ";
-       $cmd .= "KRB5CCNAME=\"$ret->{KRB5_CCACHE}\" ";
-       $cmd .= "RESOLV_CONF=\"$ret->{RESOLV_CONF}\" ";
+       my $cmd = $self->get_cmd_env_vars($ret);
        $cmd .= "$samba_tool domain join $ret->{CONFIGURATION} $dcvars->{REALM} member";
        $cmd .= " -U$dcvars->{DC_USERNAME}\%$dcvars->{DC_PASSWORD}";
        $cmd .= " --machinepass=machine$ret->{PASSWORD}";
@@ -1294,20 +1341,8 @@ rpc_server:tcpip = no
                return undef;
        }
 
-       $ret->{MEMBER_SERVER} = $ret->{SERVER};
-       $ret->{MEMBER_SERVER_IP} = $ret->{SERVER_IP};
-       $ret->{MEMBER_SERVER_IPV6} = $ret->{SERVER_IPV6};
-       $ret->{MEMBER_NETBIOSNAME} = $ret->{NETBIOSNAME};
-       $ret->{MEMBER_USERNAME} = $ret->{USERNAME};
-       $ret->{MEMBER_PASSWORD} = $ret->{PASSWORD};
-
        $ret->{DOMSID} = $dcvars->{DOMSID};
-       $ret->{DC_SERVER} = $dcvars->{DC_SERVER};
-       $ret->{DC_SERVER_IP} = $dcvars->{DC_SERVER_IP};
-       $ret->{DC_SERVER_IPV6} = $dcvars->{DC_SERVER_IPV6};
-       $ret->{DC_NETBIOSNAME} = $dcvars->{DC_NETBIOSNAME};
-       $ret->{DC_USERNAME} = $dcvars->{DC_USERNAME};
-       $ret->{DC_PASSWORD} = $dcvars->{DC_PASSWORD};
+       $self->set_pdc_env_vars($ret, $dcvars);
 
        return $ret;
 }
@@ -1358,16 +1393,7 @@ sub provision_rpc_proxy($$$)
        my $samba_tool =  Samba::bindir_path($self, "samba-tool");
 
        # The joind runs in the context of the rpc_proxy/member for now
-       my $cmd = "NSS_WRAPPER_HOSTS='$ret->{NSS_WRAPPER_HOSTS}' ";
-       $cmd .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$ret->{SOCKET_WRAPPER_DEFAULT_IFACE}\" ";
-       if (defined($ret->{RESOLV_WRAPPER_CONF})) {
-               $cmd .= "RESOLV_WRAPPER_CONF=\"$ret->{RESOLV_WRAPPER_CONF}\" ";
-       } else {
-               $cmd .= "RESOLV_WRAPPER_HOSTS=\"$ret->{RESOLV_WRAPPER_HOSTS}\" ";
-       }
-       $cmd .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" ";
-       $cmd .= "KRB5CCNAME=\"$ret->{KRB5_CCACHE}\" ";
-       $cmd .= "RESOLV_CONF=\"$ret->{RESOLV_CONF}\" ";
+       my $cmd = $self->get_cmd_env_vars($ret);
        $cmd .= "$samba_tool domain join $ret->{CONFIGURATION} $dcvars->{REALM} member";
        $cmd .= " -U$dcvars->{DC_USERNAME}\%$dcvars->{DC_PASSWORD}";
        $cmd .= " --machinepass=machine$ret->{PASSWORD}";
@@ -1406,20 +1432,8 @@ sub provision_rpc_proxy($$$)
                return undef;
        }
 
-       $ret->{RPC_PROXY_SERVER} = $ret->{SERVER};
-       $ret->{RPC_PROXY_SERVER_IP} = $ret->{SERVER_IP};
-       $ret->{RPC_PROXY_SERVER_IPV6} = $ret->{SERVER_IPV6};
-       $ret->{RPC_PROXY_NETBIOSNAME} = $ret->{NETBIOSNAME};
-       $ret->{RPC_PROXY_USERNAME} = $ret->{USERNAME};
-       $ret->{RPC_PROXY_PASSWORD} = $ret->{PASSWORD};
-
        $ret->{DOMSID} = $dcvars->{DOMSID};
-       $ret->{DC_SERVER} = $dcvars->{DC_SERVER};
-       $ret->{DC_SERVER_IP} = $dcvars->{DC_SERVER_IP};
-       $ret->{DC_SERVER_IPV6} = $dcvars->{DC_SERVER_IPV6};
-       $ret->{DC_NETBIOSNAME} = $dcvars->{DC_NETBIOSNAME};
-       $ret->{DC_USERNAME} = $dcvars->{DC_USERNAME};
-       $ret->{DC_PASSWORD} = $dcvars->{DC_PASSWORD};
+       $self->set_pdc_env_vars($ret, $dcvars);
 
        return $ret;
 }
@@ -1464,16 +1478,7 @@ sub provision_promoted_dc($$$)
        }
 
        my $samba_tool =  Samba::bindir_path($self, "samba-tool");
-       my $cmd = "NSS_WRAPPER_HOSTS='$ret->{NSS_WRAPPER_HOSTS}' ";
-       $cmd .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$ret->{SOCKET_WRAPPER_DEFAULT_IFACE}\" ";
-       if (defined($ret->{RESOLV_WRAPPER_CONF})) {
-               $cmd .= "RESOLV_WRAPPER_CONF=\"$ret->{RESOLV_WRAPPER_CONF}\" ";
-       } else {
-               $cmd .= "RESOLV_WRAPPER_HOSTS=\"$ret->{RESOLV_WRAPPER_HOSTS}\" ";
-       }
-       $cmd .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" ";
-       $cmd .= "KRB5CCNAME=\"$ret->{KRB5_CCACHE}\" ";
-       $cmd .= "RESOLV_CONF=\"$ret->{RESOLV_CONF}\" ";
+       my $cmd = $self->get_cmd_env_vars($ret);
        $cmd .= "$samba_tool domain join $ret->{CONFIGURATION} $dcvars->{REALM} MEMBER --realm=$dcvars->{REALM}";
        $cmd .= " -U$dcvars->{DC_USERNAME}\%$dcvars->{DC_PASSWORD}";
        $cmd .= " --machinepass=machine$ret->{PASSWORD}";
@@ -1484,16 +1489,7 @@ sub provision_promoted_dc($$$)
        }
 
        my $samba_tool =  Samba::bindir_path($self, "samba-tool");
-       my $cmd = "NSS_WRAPPER_HOSTS='$ret->{NSS_WRAPPER_HOSTS}' ";
-       $cmd .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$ret->{SOCKET_WRAPPER_DEFAULT_IFACE}\" ";
-       if (defined($ret->{RESOLV_WRAPPER_CONF})) {
-               $cmd .= "RESOLV_WRAPPER_CONF=\"$ret->{RESOLV_WRAPPER_CONF}\" ";
-       } else {
-               $cmd .= "RESOLV_WRAPPER_HOSTS=\"$ret->{RESOLV_WRAPPER_HOSTS}\" ";
-       }
-       $cmd .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" ";
-       $cmd .= "KRB5CCNAME=\"$ret->{KRB5_CCACHE}\" ";
-       $cmd .= "RESOLV_CONF=\"$ret->{RESOLV_CONF}\" ";
+       my $cmd = $self->get_cmd_env_vars($ret);
        $cmd .= "$samba_tool domain dcpromo $ret->{CONFIGURATION} $dcvars->{REALM} DC --realm=$dcvars->{REALM}";
        $cmd .= " -U$dcvars->{DC_USERNAME}\%$dcvars->{DC_PASSWORD}";
        $cmd .= " --machinepass=machine$ret->{PASSWORD} --use-ntvfs --dns-backend=BIND9_DLZ";
@@ -1503,17 +1499,7 @@ sub provision_promoted_dc($$$)
                return undef;
        }
 
-       $ret->{PROMOTED_DC_SERVER} = $ret->{SERVER};
-       $ret->{PROMOTED_DC_SERVER_IP} = $ret->{SERVER_IP};
-       $ret->{PROMOTED_DC_SERVER_IPV6} = $ret->{SERVER_IPV6};
-       $ret->{PROMOTED_DC_NETBIOSNAME} = $ret->{NETBIOSNAME};
-
-       $ret->{DC_SERVER} = $dcvars->{DC_SERVER};
-       $ret->{DC_SERVER_IP} = $dcvars->{DC_SERVER_IP};
-       $ret->{DC_SERVER_IPV6} = $dcvars->{DC_SERVER_IPV6};
-       $ret->{DC_NETBIOSNAME} = $dcvars->{DC_NETBIOSNAME};
-       $ret->{DC_USERNAME} = $dcvars->{DC_USERNAME};
-       $ret->{DC_PASSWORD} = $dcvars->{DC_PASSWORD};
+       $self->set_pdc_env_vars($ret, $dcvars);
 
        return $ret;
 }
@@ -1568,16 +1554,7 @@ sub provision_vampire_dc($$$)
        }
 
        my $samba_tool =  Samba::bindir_path($self, "samba-tool");
-       my $cmd = "NSS_WRAPPER_HOSTS='$ret->{NSS_WRAPPER_HOSTS}' ";
-       $cmd .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$ret->{SOCKET_WRAPPER_DEFAULT_IFACE}\" ";
-       if (defined($ret->{RESOLV_WRAPPER_CONF})) {
-               $cmd .= "RESOLV_WRAPPER_CONF=\"$ret->{RESOLV_WRAPPER_CONF}\" ";
-       } else {
-               $cmd .= "RESOLV_WRAPPER_HOSTS=\"$ret->{RESOLV_WRAPPER_HOSTS}\" ";
-       }
-       $cmd .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" ";
-       $cmd .= "KRB5CCNAME=\"$ret->{KRB5_CCACHE}\" ";
-       $cmd .= "RESOLV_CONF=\"$ret->{RESOLV_CONF}\" ";
+       my $cmd = $self->get_cmd_env_vars($ret);
        $cmd .= "$samba_tool domain join $ret->{CONFIGURATION} $dcvars->{REALM} DC --realm=$dcvars->{REALM}";
        $cmd .= " -U$dcvars->{DC_USERNAME}\%$dcvars->{DC_PASSWORD} --domain-critical-only";
        $cmd .= " --machinepass=machine$ret->{PASSWORD} --use-ntvfs";
@@ -1588,23 +1565,7 @@ sub provision_vampire_dc($$$)
                return undef;
        }
 
-        if ($fl == "2000") {
-               $ret->{VAMPIRE_2000_DC_SERVER} = $ret->{SERVER};
-               $ret->{VAMPIRE_2000_DC_SERVER_IP} = $ret->{SERVER_IP};
-               $ret->{VAMPIRE_2000_DC_SERVER_IPV6} = $ret->{SERVER_IPV6};
-               $ret->{VAMPIRE_2000_DC_NETBIOSNAME} = $ret->{NETBIOSNAME};
-        } else {
-               $ret->{VAMPIRE_DC_SERVER} = $ret->{SERVER};
-               $ret->{VAMPIRE_DC_SERVER_IP} = $ret->{SERVER_IP};
-               $ret->{VAMPIRE_DC_SERVER_IPV6} = $ret->{SERVER_IPV6};
-               $ret->{VAMPIRE_DC_NETBIOSNAME} = $ret->{NETBIOSNAME};
-        }
-       $ret->{DC_SERVER} = $dcvars->{DC_SERVER};
-       $ret->{DC_SERVER_IP} = $dcvars->{DC_SERVER_IP};
-       $ret->{DC_SERVER_IPV6} = $dcvars->{DC_SERVER_IPV6};
-       $ret->{DC_NETBIOSNAME} = $dcvars->{DC_NETBIOSNAME};
-       $ret->{DC_USERNAME} = $dcvars->{DC_USERNAME};
-       $ret->{DC_PASSWORD} = $dcvars->{DC_PASSWORD};
+       $self->set_pdc_env_vars($ret, $dcvars);
        $ret->{DC_REALM} = $dcvars->{DC_REALM};
 
        return $ret;
@@ -1651,16 +1612,7 @@ sub provision_subdom_dc($$$)
        Samba::mk_mitkdc_conf($ctx, abs_path(Samba::bindir_path($self, "shared")));
 
        my $samba_tool =  Samba::bindir_path($self, "samba-tool");
-       my $cmd = "NSS_WRAPPER_HOSTS='$ret->{NSS_WRAPPER_HOSTS}' ";
-       $cmd .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$ret->{SOCKET_WRAPPER_DEFAULT_IFACE}\" ";
-       if (defined($ret->{RESOLV_WRAPPER_CONF})) {
-               $cmd .= "RESOLV_WRAPPER_CONF=\"$ret->{RESOLV_WRAPPER_CONF}\" ";
-       } else {
-               $cmd .= "RESOLV_WRAPPER_HOSTS=\"$ret->{RESOLV_WRAPPER_HOSTS}\" ";
-       }
-       $cmd .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" ";
-       $cmd .= "KRB5CCNAME=\"$ret->{KRB5_CCACHE}\" ";
-       $cmd .= "RESOLV_CONF=\"$ret->{RESOLV_CONF}\" ";
+       my $cmd = $self->get_cmd_env_vars($ret);
        $cmd .= "$samba_tool domain join $ret->{CONFIGURATION} $ctx->{dnsname} subdomain ";
        $cmd .= "--parent-domain=$dcvars->{REALM} -U$dcvars->{DC_USERNAME}\@$dcvars->{REALM}\%$dcvars->{DC_PASSWORD}";
        $cmd .= " --machinepass=machine$ret->{PASSWORD} --use-ntvfs";
@@ -1672,16 +1624,8 @@ sub provision_subdom_dc($$$)
        }
 
        $ret->{SUBDOM_DC_SERVER} = $ret->{SERVER};
-       $ret->{SUBDOM_DC_SERVER_IP} = $ret->{SERVER_IP};
-       $ret->{SUBDOM_DC_SERVER_IPV6} = $ret->{SERVER_IPV6};
-       $ret->{SUBDOM_DC_NETBIOSNAME} = $ret->{NETBIOSNAME};
 
-       $ret->{DC_SERVER} = $dcvars->{DC_SERVER};
-       $ret->{DC_SERVER_IP} = $dcvars->{DC_SERVER_IP};
-       $ret->{DC_SERVER_IPV6} = $dcvars->{DC_SERVER_IPV6};
-       $ret->{DC_NETBIOSNAME} = $dcvars->{DC_NETBIOSNAME};
-       $ret->{DC_USERNAME} = $dcvars->{DC_USERNAME};
-       $ret->{DC_PASSWORD} = $dcvars->{DC_PASSWORD};
+       $self->set_pdc_env_vars($ret, $dcvars);
 
        return $ret;
 }
@@ -1730,12 +1674,6 @@ sub provision_ad_dc_ntvfs($$)
                return undef;
        }
        $ret->{NETBIOSALIAS} = "localdc1-a";
-       $ret->{DC_SERVER} = $ret->{SERVER};
-       $ret->{DC_SERVER_IP} = $ret->{SERVER_IP};
-       $ret->{DC_SERVER_IPV6} = $ret->{SERVER_IPV6};
-       $ret->{DC_NETBIOSNAME} = $ret->{NETBIOSNAME};
-       $ret->{DC_USERNAME} = $ret->{USERNAME};
-       $ret->{DC_PASSWORD} = $ret->{PASSWORD};
        $ret->{DC_REALM} = $ret->{REALM};
 
        return $ret;
@@ -1776,12 +1714,6 @@ sub provision_fl2000dc($$)
                warn("Unable to add wins configuration");
                return undef;
        }
-       $ret->{DC_SERVER} = $ret->{SERVER};
-       $ret->{DC_SERVER_IP} = $ret->{SERVER_IP};
-       $ret->{DC_SERVER_IPV6} = $ret->{SERVER_IPV6};
-       $ret->{DC_NETBIOSNAME} = $ret->{NETBIOSNAME};
-       $ret->{DC_USERNAME} = $ret->{USERNAME};
-       $ret->{DC_PASSWORD} = $ret->{PASSWORD};
        $ret->{DC_REALM} = $ret->{REALM};
 
        return $ret;
@@ -1790,14 +1722,14 @@ sub provision_fl2000dc($$)
 sub provision_fl2003dc($$$)
 {
        my ($self, $prefix, $dcvars) = @_;
-       my $swiface1 = Samba::get_interface("fakednsforwarder1");
-       my $swiface2 = Samba::get_interface("fakednsforwarder2");
+       my $ip_addr1 = Samba::get_ipv4_addr("fakednsforwarder1");
+       my $ip_addr2 = Samba::get_ipv4_addr("fakednsforwarder2");
 
        print "PROVISIONING DC WITH FOREST LEVEL 2003...\n";
        my $extra_conf_options = "allow dns updates = nonsecure and secure
        dcesrv:header signing = no
        dcesrv:max auth states = 0
-       dns forwarder = 127.0.0.$swiface1 127.0.0.$swiface2";
+       dns forwarder = $ip_addr1 $ip_addr2";
        my $extra_provision_options = ["--use-ntvfs"];
        my $ret = $self->provision($prefix,
                                   "domain controller",
@@ -1815,14 +1747,8 @@ sub provision_fl2003dc($$$)
                return undef;
        }
 
-       $ret->{DC_SERVER} = $ret->{SERVER};
-       $ret->{DC_SERVER_IP} = $ret->{SERVER_IP};
-       $ret->{DC_SERVER_IPV6} = $ret->{SERVER_IPV6};
-       $ret->{DC_NETBIOSNAME} = $ret->{NETBIOSNAME};
-       $ret->{DC_USERNAME} = $ret->{USERNAME};
-       $ret->{DC_PASSWORD} = $ret->{PASSWORD};
-       $ret->{DNS_FORWARDER1} = "127.0.0.$swiface1";
-       $ret->{DNS_FORWARDER2} = "127.0.0.$swiface2";
+       $ret->{DNS_FORWARDER1} = $ip_addr1;
+       $ret->{DNS_FORWARDER2} = $ip_addr2;
 
        my @samba_tool_options;
        push (@samba_tool_options, Samba::bindir_path($self, "samba-tool"));
@@ -1875,12 +1801,6 @@ sub provision_fl2008r2dc($$$)
                warn("Unable to add wins configuration");
                return undef;
        }
-       $ret->{DC_SERVER} = $ret->{SERVER};
-       $ret->{DC_SERVER_IP} = $ret->{SERVER_IP};
-       $ret->{DC_SERVER_IPV6} = $ret->{SERVER_IPV6};
-       $ret->{DC_NETBIOSNAME} = $ret->{NETBIOSNAME};
-       $ret->{DC_USERNAME} = $ret->{USERNAME};
-       $ret->{DC_PASSWORD} = $ret->{PASSWORD};
        $ret->{DC_REALM} = $ret->{REALM};
 
        return $ret;
@@ -1939,16 +1859,7 @@ sub provision_rodc($$$)
        }
 
        my $samba_tool =  Samba::bindir_path($self, "samba-tool");
-       my $cmd = "NSS_WRAPPER_HOSTS='$ret->{NSS_WRAPPER_HOSTS}' ";
-       $cmd .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$ret->{SOCKET_WRAPPER_DEFAULT_IFACE}\" ";
-       if (defined($ret->{RESOLV_WRAPPER_CONF})) {
-               $cmd .= "RESOLV_WRAPPER_CONF=\"$ret->{RESOLV_WRAPPER_CONF}\" ";
-       } else {
-               $cmd .= "RESOLV_WRAPPER_HOSTS=\"$ret->{RESOLV_WRAPPER_HOSTS}\" ";
-       }
-       $cmd .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" ";
-       $cmd .= "KRB5CCNAME=\"$ret->{KRB5_CCACHE}\" ";
-       $cmd .= "RESOLV_CONF=\"$ret->{RESOLV_CONF}\" ";
+       my $cmd = $self->get_cmd_env_vars($ret);
        $cmd .= "$samba_tool domain join $ret->{CONFIGURATION} $dcvars->{REALM} RODC";
        $cmd .= " -U$dcvars->{DC_USERNAME}\%$dcvars->{DC_PASSWORD}";
        $cmd .= " --server=$dcvars->{DC_SERVER} --use-ntvfs";
@@ -1980,17 +1891,7 @@ sub provision_rodc($$$)
        Samba::mk_krb5_conf($ctx);
        Samba::mk_mitkdc_conf($ctx, abs_path(Samba::bindir_path($self, "shared")));
 
-       $ret->{RODC_DC_SERVER} = $ret->{SERVER};
-       $ret->{RODC_DC_SERVER_IP} = $ret->{SERVER_IP};
-       $ret->{RODC_DC_SERVER_IPV6} = $ret->{SERVER_IPV6};
-       $ret->{RODC_DC_NETBIOSNAME} = $ret->{NETBIOSNAME};
-
-       $ret->{DC_SERVER} = $dcvars->{DC_SERVER};
-       $ret->{DC_SERVER_IP} = $dcvars->{DC_SERVER_IP};
-       $ret->{DC_SERVER_IPV6} = $dcvars->{DC_SERVER_IPV6};
-       $ret->{DC_NETBIOSNAME} = $dcvars->{DC_NETBIOSNAME};
-       $ret->{DC_USERNAME} = $dcvars->{DC_USERNAME};
-       $ret->{DC_PASSWORD} = $dcvars->{DC_PASSWORD};
+       $self->set_pdc_env_vars($ret, $dcvars);
 
        return $ret;
 }
@@ -2152,13 +2053,6 @@ sub provision_ad_dc($$$$$$)
                return undef;
        }
 
-       $ret->{DC_SERVER} = $ret->{SERVER};
-       $ret->{DC_SERVER_IP} = $ret->{SERVER_IP};
-       $ret->{DC_SERVER_IPV6} = $ret->{SERVER_IPV6};
-       $ret->{DC_NETBIOSNAME} = $ret->{NETBIOSNAME};
-       $ret->{DC_USERNAME} = $ret->{USERNAME};
-       $ret->{DC_PASSWORD} = $ret->{PASSWORD};
-
        return $ret;
 }
 
@@ -2205,13 +2099,7 @@ sub provision_chgdcpass($$)
                warn("Unable to remove $ret->{PRIVATEDIR}/secrets.tdb added during provision");
                return undef;
        }
-           
-       $ret->{DC_SERVER} = $ret->{SERVER};
-       $ret->{DC_SERVER_IP} = $ret->{SERVER_IP};
-       $ret->{DC_SERVER_IPV6} = $ret->{SERVER_IPV6};
-       $ret->{DC_NETBIOSNAME} = $ret->{NETBIOSNAME};
-       $ret->{DC_USERNAME} = $ret->{USERNAME};
-       $ret->{DC_PASSWORD} = $ret->{PASSWORD};
+
        $ret->{UNACCEPTABLE_PASSWORD} = $unacceptable_password;
 
        return $ret;
@@ -2373,9 +2261,54 @@ sub check_env($$)
        offlinebackupdc      => ["backupfromdc"],
        labdc                => ["backupfromdc"],
 
+       # aliases in order to split autbuild tasks
+       fl2008dc             => ["ad_dc_ntvfs"],
+       ad_dc_default        => ["ad_dc_ntvfs"],
+       ad_dc_slowtests      => ["ad_dc_ntvfs"],
+       ad_dc_backup         => ["ad_dc"],
+
+       schema_dc      => ["dns_hub"],
+       schema_pair_dc => ["schema_dc"],
+
        none                 => [],
 );
 
+%Samba4::ENV_DEPS_POST = (
+       schema_dc => ["schema_pair_dc"],
+);
+
+sub return_alias_env
+{
+       my ($self, $path, $env) = @_;
+
+       # just an alias
+       return $env;
+}
+
+sub setup_fl2008dc
+{
+       my ($self, $path, $dep_env) = @_;
+       return $self->return_alias_env($path, $dep_env)
+}
+
+sub setup_ad_dc_default
+{
+       my ($self, $path, $dep_env) = @_;
+       return $self->return_alias_env($path, $dep_env)
+}
+
+sub setup_ad_dc_slowtests
+{
+       my ($self, $path, $dep_env) = @_;
+       return $self->return_alias_env($path, $dep_env)
+}
+
+sub setup_ad_dc_backup
+{
+       my ($self, $path, $dep_env) = @_;
+       return $self->return_alias_env($path, $dep_env)
+}
+
 sub setup_s4member
 {
        my ($self, $path, $dc_vars) = @_;
@@ -2528,16 +2461,7 @@ sub setup_generic_vampire_dc
                # as 'vampired' dc may add data in its local replica
                # we need to synchronize data between DCs
                my $base_dn = "DC=".join(",DC=", split(/\./, $dc_vars->{REALM}));
-               my $cmd = "NSS_WRAPPER_HOSTS='$env->{NSS_WRAPPER_HOSTS}' ";
-               $cmd .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$env->{SOCKET_WRAPPER_DEFAULT_IFACE}\" ";
-               if (defined($env->{RESOLV_WRAPPER_CONF})) {
-                       $cmd .= "RESOLV_WRAPPER_CONF=\"$env->{RESOLV_WRAPPER_CONF}\" ";
-               } else {
-                       $cmd .= "RESOLV_WRAPPER_HOSTS=\"$env->{RESOLV_WRAPPER_HOSTS}\" ";
-               }
-               $cmd .= " KRB5_CONFIG=\"$env->{KRB5_CONFIG}\"";
-               $cmd .= "KRB5CCNAME=\"$env->{KRB5_CCACHE}\" ";
-               $cmd .= "RESOLV_CONF=\"$env->{RESOLV_CONF}\" ";
+               my $cmd = $self->get_cmd_env_vars($env);
                $cmd .= " $samba_tool drs replicate $env->{DC_SERVER} $env->{SERVER}";
                $cmd .= " $dc_vars->{CONFIGURATION}";
                $cmd .= " -U$dc_vars->{DC_USERNAME}\%$dc_vars->{DC_PASSWORD}";
@@ -2556,16 +2480,7 @@ sub setup_generic_vampire_dc
 
                # Pull in a full set of changes from the main DC
                my $base_dn = "DC=".join(",DC=", split(/\./, $dc_vars->{REALM}));
-               $cmd = "NSS_WRAPPER_HOSTS='$env->{NSS_WRAPPER_HOSTS}' ";
-               $cmd .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$env->{SOCKET_WRAPPER_DEFAULT_IFACE}\" ";
-               if (defined($env->{RESOLV_WRAPPER_CONF})) {
-                       $cmd .= "RESOLV_WRAPPER_CONF=\"$env->{RESOLV_WRAPPER_CONF}\" ";
-               } else {
-                       $cmd .= "RESOLV_WRAPPER_HOSTS=\"$env->{RESOLV_WRAPPER_HOSTS}\" ";
-               }
-               $cmd .= " KRB5_CONFIG=\"$env->{KRB5_CONFIG}\"";
-               $cmd .= "KRB5CCNAME=\"$env->{KRB5_CCACHE}\" ";
-               $cmd .= "RESOLV_CONF=\"$env->{RESOLV_CONF}\" ";
+               $cmd = $self->get_cmd_env_vars($env);
                $cmd .= " $samba_tool drs replicate $env->{SERVER} $env->{DC_SERVER}";
                $cmd .= " $dc_vars->{CONFIGURATION}";
                $cmd .= " -U$dc_vars->{DC_USERNAME}\%$dc_vars->{DC_PASSWORD}";
@@ -2875,6 +2790,101 @@ sub setup_proclimitdc
        return $env;
 }
 
+# Used to test a live upgrade of the schema on a 2 DC network.
+sub setup_schema_dc
+{
+       my ($self, $path) = @_;
+
+       # provision the PDC using an older base schema
+       my $provision_args = ["--base-schema=2008_R2", "--backend-store=mdb"];
+
+       my $env = $self->provision_ad_dc($path, "liveupgrade1dc", "SCHEMADOMAIN",
+                                        "schema.samba.example.com",
+                                        "drs: max link sync = 2",
+                                        $provision_args);
+       unless ($env) {
+               return undef;
+       }
+
+       if (not defined($self->check_or_start($env, "prefork"))) {
+           return undef;
+       }
+
+       my $upn_array = ["$env->{REALM}.upn"];
+       my $spn_array = ["$env->{REALM}.spn"];
+
+       $self->setup_namespaces($env, $upn_array, $spn_array);
+
+       return $env;
+}
+
+# the second DC in the live schema upgrade pair
+sub setup_schema_pair_dc
+{
+       # note: dcvars contains the env info for the dependent testenv ('schema_dc')
+       my ($self, $prefix, $dcvars) = @_;
+       print "Preparing SCHEMA UPGRADE PAIR DC...\n";
+
+       my ($env, $ctx) = $self->prepare_dc_testenv($prefix, "liveupgrade2dc",
+                                                   $dcvars->{DOMAIN},
+                                                   $dcvars->{REALM},
+                                                   $dcvars->{PASSWORD},
+                                                   "");
+
+       my $samba_tool =  Samba::bindir_path($self, "samba-tool");
+       my $cmd_vars = "NSS_WRAPPER_HOSTS='$env->{NSS_WRAPPER_HOSTS}' ";
+       $cmd_vars .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$env->{SOCKET_WRAPPER_DEFAULT_IFACE}\" ";
+       if (defined($env->{RESOLV_WRAPPER_CONF})) {
+               $cmd_vars .= "RESOLV_WRAPPER_CONF=\"$env->{RESOLV_WRAPPER_CONF}\" ";
+       } else {
+               $cmd_vars .= "RESOLV_WRAPPER_HOSTS=\"$env->{RESOLV_WRAPPER_HOSTS}\" ";
+       }
+       $cmd_vars .= "KRB5_CONFIG=\"$env->{KRB5_CONFIG}\" ";
+       $cmd_vars .= "KRB5CCNAME=\"$env->{KRB5_CCACHE}\" ";
+       $cmd_vars .= "RESOLV_CONF=\"$env->{RESOLV_CONF}\" ";
+
+       my $join_cmd = $cmd_vars;
+       $join_cmd .= "$samba_tool domain join $env->{CONFIGURATION} $dcvars->{REALM} DC --realm=$dcvars->{REALM}";
+       $join_cmd .= " -U$dcvars->{DC_USERNAME}\%$dcvars->{DC_PASSWORD} ";
+       $join_cmd .= " --backend-store=mdb";
+
+       my $upgrade_cmd = $cmd_vars;
+       $upgrade_cmd .= "$samba_tool domain schemaupgrade $dcvars->{CONFIGURATION}";
+       $upgrade_cmd .= " -U$dcvars->{USERNAME}\%$dcvars->{PASSWORD}";
+
+       my $repl_cmd = $cmd_vars;
+       $repl_cmd .= "$samba_tool drs replicate $env->{SERVER} $dcvars->{SERVER}";
+        $repl_cmd .= " CN=Schema,CN=Configuration,DC=schema,DC=samba,DC=example,DC=com";
+       $repl_cmd .= " -U$dcvars->{DC_USERNAME}\%$dcvars->{DC_PASSWORD}";
+
+       unless (system($join_cmd) == 0) {
+               warn("Join failed\n$join_cmd");
+               return undef;
+       }
+
+       $env->{DC_SERVER} = $dcvars->{SERVER};
+       $env->{DC_SERVER_IP} = $dcvars->{SERVER_IP};
+       $env->{DC_SERVER_IPV6} = $dcvars->{SERVER_IPV6};
+       $env->{DC_NETBIOSNAME} = $dcvars->{NETBIOSNAME};
+
+       # start samba for the new DC
+       if (not defined($self->check_or_start($env, "standard"))) {
+           return undef;
+       }
+
+       unless (system($upgrade_cmd) == 0) {
+               warn("Schema upgrade failed\n$upgrade_cmd");
+               return undef;
+       }
+
+       unless (system($repl_cmd) == 0) {
+               warn("Post-update schema replication failed\n$repl_cmd");
+               return undef;
+       }
+
+       return $env;
+}
+
 # Sets up a DC that's solely used to do a domain backup from. We then use the
 # backupfrom-DC to create the restore-DC - this proves that the backup/restore
 # process will create a Samba DC that will actually start up.
@@ -3058,13 +3068,6 @@ sub prepare_dc_testenv
 
        my $env = $self->provision_raw_step1($ctx);
 
-       $env->{DC_SERVER} = $env->{SERVER};
-       $env->{DC_SERVER_IP} = $env->{SERVER_IP};
-       $env->{DC_SERVER_IPV6} = $env->{SERVER_IPV6};
-       $env->{DC_NETBIOSNAME} = $env->{NETBIOSNAME};
-       $env->{DC_USERNAME} = $env->{USERNAME};
-       $env->{DC_PASSWORD} = $env->{PASSWORD};
-
     return ($env, $ctx);
 }
 
@@ -3081,7 +3084,8 @@ sub setup_restoredc
        # we arbitrarily designate the restored DC as having SMBv1 disabled
        my $extra_conf = "
        server min protocol = SMB2
-       client min protocol = SMB2";
+       client min protocol = SMB2
+       prefork children = 1";
 
        my ($env, $ctx) = $self->prepare_dc_testenv($prefix, "restoredc",
                                                    $dcvars->{DOMAIN},
@@ -3124,11 +3128,12 @@ sub setup_renamedc
        # note: dcvars contains the env info for the dependent testenv ('backupfromdc')
        my ($self, $prefix, $dcvars) = @_;
        print "Preparing RENAME DC...\n";
+       my $extra_conf = "prefork children = 1";
 
        my $realm = "renamedom.samba.example.com";
        my ($env, $ctx) = $self->prepare_dc_testenv($prefix, "renamedc",
                                                    "RENAMEDOMAIN", $realm,
-                                                   $dcvars->{PASSWORD}, "");
+                                                   $dcvars->{PASSWORD}, $extra_conf);
 
        # create a backup of the 'backupfromdc' which renames the domain
        my $backupdir = File::Temp->newdir();
@@ -3171,11 +3176,12 @@ sub setup_offlinebackupdc
        # note: dcvars contains the env info for the dependent testenv ('backupfromdc')
        my ($self, $prefix, $dcvars) = @_;
        print "Preparing OFFLINE BACKUP DC...\n";
+       my $extra_conf = "prefork children = 1";
 
        my ($env, $ctx) = $self->prepare_dc_testenv($prefix, "offlinebackupdc",
                                                    $dcvars->{DOMAIN},
                                                    $dcvars->{REALM},
-                                                   $dcvars->{PASSWORD}, "");
+                                                   $dcvars->{PASSWORD}, $extra_conf);
 
        # create an offline backup of the 'backupfromdc' target
        my $backupdir = File::Temp->newdir();
@@ -3215,11 +3221,12 @@ sub setup_labdc
        # note: dcvars contains the env info for the dependent testenv ('backupfromdc')
        my ($self, $prefix, $dcvars) = @_;
        print "Preparing LAB-DOMAIN DC...\n";
+       my $extra_conf = "prefork children = 1";
 
        my ($env, $ctx) = $self->prepare_dc_testenv($prefix, "labdc",
                                                    "LABDOMAIN",
                                                    "labdom.samba.example.com",
-                                                   $dcvars->{PASSWORD}, "");
+                                                   $dcvars->{PASSWORD}, $extra_conf);
 
        # create a backup of the 'backupfromdc' which renames the domain and uses
        # the --no-secrets option to scrub any sensitive info