diff options
author | Andrew Bartlett <abartlet@samba.org> | 2010-12-10 12:13:58 +1100 |
---|---|---|
committer | Andrew Bartlett <abartlet@samba.org> | 2010-12-10 17:58:13 +1100 |
commit | 4408f8a0dec80c34dfe770cc2a81f2d4e074ba8a (patch) | |
tree | b30eb15a13481ede9f56c635e0d7ca4d109888a6 /wintest/wintest.py | |
parent | 6195dfc0eb310a2362cb949a000979514a52c648 (diff) | |
download | samba-4408f8a0dec80c34dfe770cc2a81f2d4e074ba8a.tar.gz |
wintest Share more of the S4 test code with the s3 test
This allows us to run a private BIND in the S3 test, and allows the S3
test to join a freshly provisioned AD instance if the VM isn't already
configured.
Andrew Bartlett
Diffstat (limited to 'wintest/wintest.py')
-rw-r--r-- | wintest/wintest.py | 239 |
1 files changed, 239 insertions, 0 deletions
diff --git a/wintest/wintest.py b/wintest/wintest.py index 0d65116562a..af4588f5c8e 100644 --- a/wintest/wintest.py +++ b/wintest/wintest.py @@ -16,6 +16,23 @@ class wintest(): os.putenv('PYTHONUNBUFFERED', '1') self.parser = optparse.OptionParser("wintest") + def check_prerequesites(self): + self.info("Checking prerequesites") + self.setvar('HOSTNAME', self.cmd_output("hostname -s").strip()) + if os.getuid() != 0: + raise Exception("You must run this script as root") + self.run_cmd('ifconfig ${INTERFACE} ${INTERFACE_NET} up') + if self.getvar('INTERFACE_IPV6'): + self.run_cmd('ifconfig ${INTERFACE} inet6 del ${INTERFACE_IPV6}/64', checkfail=False) + self.run_cmd('ifconfig ${INTERFACE} inet6 add ${INTERFACE_IPV6}/64 up') + + def stop_vms(self): + '''Shut down any existing alive VMs, so they do not collide with what we are doing''' + self.info('Shutting down any of our VMs already running') + vms = self.get_vms() + for v in vms: + self.vm_poweroff(v, checkfail=False) + def setvar(self, varname, value): '''set a substitution variable''' self.vars[varname] = value @@ -268,6 +285,176 @@ class wintest(): child.expect('\d+.\d+.\d+.\d+') return child.after + def rndc_cmd(self, cmd, checkfail=True): + '''run a rndc command''' + self.run_cmd("${RNDC} -c ${PREFIX}/etc/rndc.conf %s" % cmd, checkfail=checkfail) + + def named_supports_gssapi_keytab(self): + '''see if named supports tkey-gssapi-keytab''' + self.write_file("${PREFIX}/named.conf.test", + 'options { tkey-gssapi-keytab "test"; };') + try: + self.run_cmd("${NAMED_CHECKCONF} ${PREFIX}/named.conf.test") + except subprocess.CalledProcessError: + return False + return True + + def set_nameserver(self, nameserver): + '''set the nameserver in resolv.conf''' + self.write_file("/etc/resolv.conf.wintest", ''' +# Generated by wintest, the Samba v Windows automated testing system +nameserver %s + +# your original resolv.conf appears below: +''' % self.substitute(nameserver)) + child = self.pexpect_spawn("cat /etc/resolv.conf", crlf=False) + i = child.expect(['your original resolv.conf appears below:', pexpect.EOF]) + if i == 0: + child.expect(pexpect.EOF) + contents = child.before.lstrip().replace('\r', '') + self.write_file('/etc/resolv.conf.wintest', contents, mode='a') + self.write_file('/etc/resolv.conf.wintest-bak', contents) + self.run_cmd("mv -f /etc/resolv.conf.wintest /etc/resolv.conf") + self.resolv_conf_backup = '/etc/resolv.conf.wintest-bak'; + + def configure_bind(self, kerberos_support=False, include=None): + self.chdir('${PREFIX}') + + nameserver = self.get_nameserver() + if nameserver == self.getvar('INTERFACE_IP'): + raise RuntimeError("old /etc/resolv.conf must not contain %s as a nameserver, this will create loops with the generated dns configuration" % nameserver) + self.setvar('DNSSERVER', nameserver) + + if self.getvar('INTERFACE_IPV6'): + ipv6_listen = 'listen-on-v6 port 53 { ${INTERFACE_IPV6}; };' + else: + ipv6_listen = '' + self.setvar('BIND_LISTEN_IPV6', ipv6_listen) + + if not kerberos_support: + self.setvar("NAMED_TKEY_OPTION", "") + else: + if self.named_supports_gssapi_keytab(): + self.setvar("NAMED_TKEY_OPTION", + 'tkey-gssapi-keytab "${PREFIX}/private/dns.keytab";') + else: + self.info("LCREALM=${LCREALM}") + self.setvar("NAMED_TKEY_OPTION", + '''tkey-gssapi-credential "DNS/${LCREALM}"; + tkey-domain "${LCREALM}"; + ''') + self.putenv("KRB5_CONFIG", '${PREFIX}/private/krb5.conf') + self.putenv('KEYTAB_FILE', '${PREFIX}/private/dns.keytab') + self.putenv('KRB5_KTNAME', '${PREFIX}/private/dns.keytab') + + if include: + self.setvar("NAMED_INCLUDE", 'include "%s";' % include) + else: + self.setvar("NAMED_INCLUDE", '') + + self.run_cmd("mkdir -p ${PREFIX}/etc") + + self.write_file("etc/named.conf", ''' +options { + listen-on port 53 { ${INTERFACE_IP}; }; + ${BIND_LISTEN_IPV6} + 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 { any; }; + recursion yes; + ${NAMED_TKEY_OPTION} + max-cache-ttl 10; + max-ncache-ttl 10; + + forward only; + forwarders { + ${DNSSERVER}; + }; + +}; + +key "rndc-key" { + algorithm hmac-md5; + secret "lA/cTrno03mt5Ju17ybEYw=="; +}; + +controls { + inet ${INTERFACE_IP} port 953 + allow { any; } keys { "rndc-key"; }; +}; + +${NAMED_INCLUDE} +''') + + # add forwarding for the windows domains + domains = self.get_domains() + for d in domains: + self.write_file('etc/named.conf', + ''' +zone "%s" IN { + type forward; + forward only; + forwarders { + %s; + }; +}; +''' % (d, domains[d]), + mode='a') + + + self.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; +}; +''') + + + def stop_bind(self): + '''Stop our private BIND from listening and operating''' + self.rndc_cmd("stop", checkfail=False) + self.port_wait("${INTERFACE_IP}", 53, wait_for_fail=True) + + self.run_cmd("rm -rf var/named") + + + def start_bind(self): + '''restart the test environment version of bind''' + self.info("Restarting bind9") + self.chdir('${PREFIX}') + + self.set_nameserver(self.getvar('INTERFACE_IP')) + + self.run_cmd("mkdir -p var/named/data") + self.run_cmd("chown -R ${BIND_USER} var/named") + + self.bind_child = self.run_child("${BIND9} -u ${BIND_USER} -n 1 -c ${PREFIX}/etc/named.conf -g") + + self.port_wait("${INTERFACE_IP}", 53) + self.rndc_cmd("flush") + + def restart_bind(self, kerberos_support=False, include=None): + self.configure_bind(keberos_support=kerberos_support, include=include) + self.stop_bind() + self.start_bind() + + def restore_resolv_conf(self): + '''restore the /etc/resolv.conf after testing is complete''' + if getattr(self, 'resolv_conf_backup', False): + self.info("restoring /etc/resolv.conf") + self.run_cmd("mv -f %s /etc/resolv.conf" % self.resolv_conf_backup) + + def vm_poweroff(self, vmname, checkfail=True): '''power off a VM''' self.setvar('VMNAME', vmname) @@ -565,6 +752,58 @@ class wintest(): ret.append(self.vars[v]) return ret + + def run_dcpromo_as_first_dc(self, vm, func_level=None): + self.setwinvars(vm) + self.info("Configuring a windows VM ${WIN_VM} at the first DC in the domain using dcpromo") + child = self.open_telnet("${WIN_HOSTNAME}", "administrator", "${WIN_PASS}", set_time=True) + if self.get_is_dc(child): + return + + if func_level == '2008r2': + self.setvar("FUNCTION_LEVEL_INT", str(4)) + elif func_level == '2003': + self.setvar("FUNCTION_LEVEL_INT", str(1)) + else: + self.setvar("FUNCTION_LEVEL_INT", str(0)) + + child = self.open_telnet("${WIN_HOSTNAME}", "administrator", "${WIN_PASS}", set_ip=True, set_noexpire=True) + + """This server must therefore not yet be a directory server, so we must promote it""" + child.sendline("copy /Y con answers.txt") + child.sendline(''' +[DCInstall] +; New forest promotion +ReplicaOrNewDomain=Domain +NewDomain=Forest +NewDomainDNSName=${WIN_REALM} +ForestLevel=${FUNCTION_LEVEL_INT} +DomainNetbiosName=${WIN_DOMAIN} +DomainLevel=${FUNCTION_LEVEL_INT} +InstallDNS=Yes +ConfirmGc=Yes +CreateDNSDelegation=No +DatabasePath="C:\Windows\NTDS" +LogPath="C:\Windows\NTDS" +SYSVOLPath="C:\Windows\SYSVOL" +; Set SafeModeAdminPassword to the correct value prior to using the unattend file +SafeModeAdminPassword=${WIN_PASS} +; Run-time flags (optional) +RebootOnCompletion=No + +''') + child.expect("copied.") + child.expect("C:") + child.expect("C:") + child.sendline("dcpromo /answer:answers.txt") + i = child.expect(["You must restart this computer", "failed", "Active Directory Domain Services was not installed", "C:"], timeout=240) + if i == 1 or i == 2: + raise Exception("dcpromo failed") + child.sendline("shutdown -r -t 0") + self.port_wait("${WIN_IP}", 139, wait_for_fail=True) + self.port_wait("${WIN_IP}", 139) + + def setup(self, testname, subdir): '''setup for main tests, parsing command line''' self.parser.add_option("--conf", type='string', default='', help='config file') |