1#!/usr/bin/perl -w
2#
3# Copyright (C) 2010, 2012  Internet Systems Consortium, Inc. ("ISC")
4#
5# Permission to use, copy, modify, and/or distribute this software for any
6# purpose with or without fee is hereby granted, provided that the above
7# copyright notice and this permission notice appear in all copies.
8#
9# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11# AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15# PERFORMANCE OF THIS SOFTWARE.
16
17# Id: start.pl,v 1.2 2010/06/17 05:38:05 marka Exp
18
19# Framework for starting test servers.
20# Based on the type of server specified, check for port availability, remove
21# temporary files, start the server, and verify that the server is running.
22# If a server is specified, start it. Otherwise, start all servers for test.
23
24use strict;
25use Cwd 'abs_path';
26use Getopt::Long;
27
28# Option handling
29#   --noclean test [server [options]]
30#
31#   --noclean - Do not cleanup files in server directory
32#   test - name of the test directory
33#   server - name of the server directory
34#   options - alternate options for the server
35
36my $usage = "usage: $0 [--noclean] test-directory [server-directory [server-options]]";
37my $noclean;
38GetOptions('noclean' => \$noclean);
39my $test = $ARGV[0];
40my $server = $ARGV[1];
41my $options = $ARGV[2];
42
43if (!$test) {
44	print "$usage\n";
45}
46if (!-d $test) {
47	print "No test directory: \"$test\"\n";
48}
49if ($server && !-d "$test/$server") {
50	print "No server directory: \"$test/$server\"\n";
51}
52
53# Global variables
54my $topdir = abs_path("$test/..");
55my $testdir = abs_path("$test");
56my $NAMED = $ENV{'NAMED'};
57my $DIG = $ENV{'DIG'};
58my $PERL = $ENV{'PERL'};
59
60# Start the server(s)
61
62if ($server) {
63	if ($server =~ /^ns/) {
64		&check_ports($server);
65	}
66	&start_server($server, $options);
67	if ($server =~ /^ns/) {
68		&verify_server($server);
69	}
70} else {
71	# Determine which servers need to be started for this test.
72	opendir DIR, $testdir;
73	my @files = sort readdir DIR;
74	closedir DIR;
75
76	my @ns = grep /^ns[0-9]*$/, @files;
77
78	# Start the servers we found.
79	&check_ports();
80	foreach (@ns) {
81		&start_server($_);
82	}
83	foreach (@ns) {
84		&verify_server($_);
85	}
86}
87
88# Subroutines
89
90sub check_ports {
91	my $server = shift;
92	my $options = "";
93
94	if ($server && $server =~ /(\d+)$/) {
95		$options = "-i $1";
96	}
97
98	my $tries = 0;
99	while (1) {
100		my $return = system("$PERL $topdir/testsock.pl -p 5300 $options");
101		last if ($return == 0);
102		if (++$tries > 4) {
103			print "$0: could not bind to server addresses, still running?\n";
104			print "I:server sockets not available\n";
105			print "R:FAIL\n";
106			system("$PERL $topdir/stop.pl $testdir"); # Is this the correct behavior?
107			exit 1;
108		}
109		print "I:Couldn't bind to socket (yet)\n";
110		sleep 2;
111	}
112}
113
114sub start_server {
115	my $server = shift;
116	my $options = shift;
117
118	my $cleanup_files;
119	my $command;
120	my $pid_file;
121
122	if ($server =~ /^ns/) {
123		$cleanup_files = "{*.jnl,*.bk,*.st,named.run}";
124		$command = "sh wrap.sh ";
125		$command .= "$NAMED ";
126		if ($options) {
127			$command .= "$options";
128		} else {
129			$command .= "-m record,size,mctx ";
130			$command .= "-T clienttest ";
131			$command .= "-c named.conf -d 99 -g";
132		}
133		$command .= " >named.run 2>&1 &";
134		$pid_file = "named.pid";
135	} else {
136		print "I:Unknown server type $server\n";
137		print "R:FAIL\n";
138		system "$PERL $topdir/stop.pl $testdir";
139		exit 1;
140	}
141
142#	print "I:starting server $server\n";
143
144	chdir "$testdir/$server";
145
146	unless ($noclean) {
147		unlink glob $cleanup_files;
148	}
149
150	system "$command";
151
152	my $tries = 0;
153	while (!-f $pid_file) {
154		if (++$tries > 14) {
155			print "I:Couldn't start server $server\n";
156			print "R:FAIL\n";
157			system "$PERL $topdir/stop.pl $testdir";
158			exit 1;
159		}
160		sleep 1;
161	}
162}
163
164sub verify_server {
165	my $server = shift;
166	my $n = $server;
167	$n =~ s/^ns//;
168
169	my $tries = 0;
170	while (1) {
171		my $return = system("$DIG +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd -p 5300 version.bind. chaos txt \@10.53.0.$n > dig.out");
172		last if ($return == 0);
173		print `grep ";" dig.out`;
174		if (++$tries >= 30) {
175			print "I:no response from $server\n";
176			print "R:FAIL\n";
177			system("$PERL $topdir/stop.pl $testdir");
178			exit 1;
179		}
180		sleep 2;
181	}
182	unlink "dig.out";
183}
184