From: Andrew Bartlett Date: Tue, 23 Nov 2010 06:38:31 +0000 (+1100) Subject: wintest Evolve wintest to handle it's own BIND nameserver X-Git-Tag: samba-4.0.0alpha14~858 X-Git-Url: http://git.samba.org/?p=samba.git;a=commitdiff_plain;h=95edbc382d8167b59a79a570aff664ba806de809 wintest Evolve wintest to handle it's own BIND nameserver The changes here start our own copy of BIND, listening on a new interface that we create at the start of the script. The user must specify the IP address etc that this interface will have, and BIND and Samba will bind to that interface only. This means that we won't conflict with an existing BIND on the system, so long as it isn't configured to listen on all interfaces. We also auto-create the /etc/resolv.conf and restore it at the end of the script, using the existing server value from the script as a forwarder. Andrew Bartlett Autobuild-User: Andrew Bartlett Autobuild-Date: Tue Nov 23 08:30:34 CET 2010 on sn-devel-104 --- diff --git a/wintest/conf/abartlet.conf b/wintest/conf/abartlet.conf index a521f75e3c3..ea8a5cfa67e 100644 --- a/wintest/conf/abartlet.conf +++ b/wintest/conf/abartlet.conf @@ -13,14 +13,15 @@ DEBUGLEVEL : 1 VM_POWEROFF : virsh destroy ${VMNAME} VM_RESTORE : virsh snapshot-revert ${VMNAME} ${SNAPSHOT} -# interfaces to listen on -INTERFACES : virbr0 - -DNSSERVER : 192.168.1.172 +# interfaces to create +INTERFACE : virbr0:0 +INTERFACE_IP : 192.168.122.2 +INTERFACE_NET : 192.168.122.0/24 # how to run bind9 -BIND9 : /usr/sbin/named -u named +BIND9 : /usr/sbin/named RNDC : /usr/sbin/rndc +BIND_USER : named # provision information REALM : S4.HOWTO.ABARTLET.NET diff --git a/wintest/test-s4-howto.py b/wintest/test-s4-howto.py index 2f7ee1a8596..b28370af18c 100755 --- a/wintest/test-s4-howto.py +++ b/wintest/test-s4-howto.py @@ -11,8 +11,8 @@ def check_prerequesites(t): t.setvar('HOSTNAME', t.cmd_output("hostname -s").strip()) if os.getuid() != 0: raise Exception("You must run this script as root") - t.cmd_contains("grep 127.0.0.1 /etc/resolv.conf", ["nameserver 127.0.0.1"]) t.putenv("KRB5_CONFIG", '${PREFIX}/private/krb5.conf') + t.run_cmd('ifconfig ${INTERFACE} ${INTERFACE_IP} up') def build_s4(t): '''build samba4''' @@ -24,26 +24,27 @@ def build_s4(t): t.run_cmd('rm -rf ${PREFIX}') t.run_cmd('make -j install') -def provision_s4(t, func_level="2008", interfaces=None): +def provision_s4(t, func_level="2008", interface=None): '''provision s4 as a DC''' t.info('Provisioning s4') t.chdir('${PREFIX}') t.del_files(["var", "etc", "private"]) options=' --function-level=%s -d${DEBUGLEVEL}' % func_level - if interfaces: - options += ' --option=interfaces=%s' % interfaces + if interface: + options += ' --option=interfaces=%s' % interface + options += ' --host-ip=%s' % interface t.run_cmd('sbin/provision --realm=${LCREALM} --domain=${DOMAIN} --adminpass=${PASSWORD1} --server-role="domain controller"' + options) t.run_cmd('bin/samba-tool newuser testallowed ${PASSWORD1}') t.run_cmd('bin/samba-tool newuser testdenied ${PASSWORD1}') t.run_cmd('bin/samba-tool group addmembers "Allowed RODC Password Replication Group" testallowed') -def start_s4(t, interfaces=None): +def start_s4(t, interface=None): t.info('Starting Samba4') t.chdir("${PREFIX}") t.run_cmd('killall -9 -q samba smbd nmbd winbindd', checkfail=False) t.run_cmd(['sbin/samba', '--option', 'panic action=gnome-terminal -e "gdb --pid %PID%"', - '--option', 'interfaces=%s' % interfaces]) + '--option', 'interfaces=%s' % interface]) t.port_wait("localhost", 139) def test_smbclient(t): @@ -82,13 +83,88 @@ def restart_bind(t): t.info("Restarting bind9") t.putenv('KEYTAB_FILE', '${PREFIX}/private/dns.keytab') t.putenv('KRB5_KTNAME', '${PREFIX}/private/dns.keytab') - t.run_cmd('killall -9 -q named', checkfail=False) - t.port_wait("localhost", 53, wait_for_fail=True) - t.run_cmd("${BIND9}") - t.port_wait("localhost", 53) - t.run_cmd("${RNDC} flush") - t.run_cmd("${RNDC} freeze") - t.run_cmd("${RNDC} thaw") + t.chdir('${PREFIX}') + t.run_cmd("mkdir -p var/named/data") + t.run_cmd("chown -R ${BIND_USER} var/named") + + nameserver = t.get_nameserver() + if nameserver == t.vars['INTERFACE_IP']: + raise RuntimeError("old /etc/resolv.conf must not contain %s as a nameserver, this will create loops with the generated dns configuration") + t.setvar('DNSSERVER', nameserver) + + t.write_file("etc/named.conf", ''' +options { + listen-on port 53 { ${INTERFACE_IP}; }; + directory "${PREFIX}/var/named"; + dump-file "${PREFIX}/var/named/data/cache_dump.db"; + pid-file "${PREFIX}/var/named/named.pid"; + statistics-file "${PREFIX}/var/named/data/named_stats.txt"; + memstatistics-file "${PREFIX}/var/named/data/named_mem_stats.txt"; + allow-query { ${INTERFACE_NET}; 127.0.0.0/8; }; + recursion yes; + tkey-gssapi-credential "DNS/${LCREALM}"; + tkey-domain "${REALM}"; + + forward only; + forwarders { + ${DNSSERVER}; + }; + +}; + +key "rndc-key" { + algorithm hmac-md5; + secret "lA/cTrno03mt5Ju17ybEYw=="; +}; + +controls { + inet ${INTERFACE_IP} + allow { 127.0.0.0/8; ${INTERFACE_NET}; } keys { "rndc-key"; }; +}; + +include "${PREFIX}/private/named.conf"; +''') + + t.write_file("etc/rndc.conf", ''' +# Start of rndc.conf +key "rndc-key" { + algorithm hmac-md5; + secret "lA/cTrno03mt5Ju17ybEYw=="; +}; + +options { + default-key "rndc-key"; + default-server ${INTERFACE_IP}; + default-port 953; +}; +''') + + t.run_cmd("${RNDC} -c ${PREFIX}/etc/rndc.conf stop", checkfail=False) + t.port_wait("${INTERFACE_IP}", 53, wait_for_fail=True) + t.bind_child = t.run_child("${BIND9} -u ${BIND_USER} -c ${PREFIX}/etc/named.conf -g") + + t.run_cmd("mv -f /etc/resolv.conf /etc/resolv.conf.wintest-bak") + t.write_file("/etc/resolv.conf", ''' +# Generated by wintest, the Samba v Windows automated testing system + +nameserver ${INTERFACE_IP} + +# your original resolv.conf appears below: + +''') + + t.run_cmd('cat /etc/resolv.conf.wintest-bak >> /etc/resolv.conf') + + t.resolv_conf_backup = '/etc/resolv.conf.wintest-bak'; + + t.port_wait("${INTERFACE_IP}", 53) + t.run_cmd("${RNDC} -c ${PREFIX}/etc/rndc.conf flush") + t.run_cmd("${RNDC} -c ${PREFIX}/etc/rndc.conf freeze") + t.run_cmd("${RNDC} -c ${PREFIX}/etc/rndc.conf thaw") + +def restore_resolv_conf(t): + if getattr(t, 'resolv_conf_backup', False): + t.run_cmd("mv -f %s /etc/resolv.conf" % t.resolv_conf_backup) def test_dns(t): t.info("Testing DNS") @@ -109,7 +185,7 @@ def test_kerberos(t): def test_dyndns(t): t.chdir('${PREFIX}') t.run_cmd("sbin/samba_dnsupdate --fail-immediately") - t.run_cmd("${RNDC} flush") + t.run_cmd("${RNDC} -c ${PREFIX}/etc/rndc.conf flush") def run_winjoin(t, vm): @@ -180,8 +256,8 @@ SafeModeAdminPassword=${PASSWORD1} child.expect("C:") child.expect("C:") child.sendline("dcpromo /answer:answers.txt") - i = child.expect(["You must restart this computer", "failed", "C:"], timeout=120) - if i == 1: + i = child.expect(["You must restart this computer", "failed", "Active Directory Domain Services was not installed", "C:"], timeout=120) + if i == 1 or i == 2: raise Exception("dcpromo failed") t.port_wait("${WIN_HOSTNAME}", 139, wait_for_fail=True) t.port_wait("${WIN_HOSTNAME}", 139) @@ -365,7 +441,7 @@ def join_as_dc(t, vm): t.run_cmd('killall -9 -q samba smbd nmbd winbindd', checkfail=False) t.vm_poweroff("${WIN_VM}", checkfail=False) t.vm_restore("${WIN_VM}", "${WIN_SNAPSHOT}") - t.run_cmd('${RNDC} flush') + t.run_cmd('${RNDC} -c ${PREFIX}/etc/rndc.conf flush') t.run_cmd("rm -rf etc private") t.open_telnet("${WIN_HOSTNAME}", "${WIN_DOMAIN}\\administrator", "${WIN_PASS}", set_time=True, set_ip=True) t.retry_cmd("bin/samba-tool drs showrepl ${WIN_HOSTNAME} -Uadministrator%${WIN_PASS}", ['INBOUND NEIGHBORS'] ) @@ -432,7 +508,7 @@ def join_as_rodc(t, vm): t.run_cmd('killall -9 -q samba smbd nmbd winbindd', checkfail=False) t.vm_poweroff("${WIN_VM}", checkfail=False) t.vm_restore("${WIN_VM}", "${WIN_SNAPSHOT}") - t.run_cmd('${RNDC} flush') + t.run_cmd('${RNDC} -c ${PREFIX}/etc/rndc.conf flush') t.run_cmd("rm -rf etc private") t.open_telnet("${WIN_HOSTNAME}", "${WIN_DOMAIN}\\administrator", "${WIN_PASS}", set_time=True, set_ip=True) t.retry_cmd("bin/samba-tool drs showrepl ${WIN_HOSTNAME} -Uadministrator%${WIN_PASS}", ['INBOUND NEIGHBORS'] ) @@ -506,13 +582,13 @@ def test_howto(t): build_s4(t) if not t.skip("provision"): - provision_s4(t) + provision_s4(t, interface='${INTERFACE_IP}') if not t.skip("create-shares"): create_shares(t) if not t.skip("starts4"): - start_s4(t, interfaces='${INTERFACES}') + start_s4(t, interface='${INTERFACE_IP}') if not t.skip("smbclient"): test_smbclient(t) if not t.skip("startbind"): @@ -624,4 +700,10 @@ if __name__ == '__main__': t.chdir('${SOURCETREE}/source4') t.run_cmd('rm -rf bin') - test_howto(t) + try: + test_howto(t) + except Exception, str: + restore_resolv_conf(t) + if getattr(t, 'bind_child', False): + t.bind_child.kill() + raise diff --git a/wintest/wintest.py b/wintest/wintest.py index 27312d20ab1..4c93017f3b8 100644 --- a/wintest/wintest.py +++ b/wintest/wintest.py @@ -127,6 +127,21 @@ class wintest(): else: return subprocess.call(cmd, shell=shell, cwd=dir) + def run_child(self, cmd, dir="."): + cwd = os.getcwd() + cmd = self.substitute(cmd) + if isinstance(cmd, list): + self.info('$ ' + " ".join(cmd)) + else: + self.info('$ ' + cmd) + if isinstance(cmd, list): + shell=False + else: + shell=True + os.chdir(dir) + ret = subprocess.Popen(cmd, shell=shell) + os.chdir(cwd) + return ret def cmd_output(self, cmd): '''return output from and command''' @@ -200,6 +215,13 @@ class wintest(): return ret + def get_nameserver(self): + '''Get the current nameserver from /etc/resolv.conf''' + child = self.pexpect_spawn('cat /etc/resolv.conf') + child.expect('nameserver') + child.expect('\d+.\d+.\d+.\d+') + return child.after + def vm_poweroff(self, vmname, checkfail=True): '''power off a VM''' self.setvar('VMNAME', vmname) @@ -294,7 +316,7 @@ class wintest(): child.expect("C:") def set_dns(self, child): - child.sendline('netsh interface ip set dns "${WIN_NIC}" static ${DNSSERVER} primary') + child.sendline('netsh interface ip set dns "${WIN_NIC}" static ${INTERFACE_IP} primary') i = child.expect(['C:', pexpect.EOF, pexpect.TIMEOUT], timeout=5) if i > 0: return True