diff options
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/README | 139 | ||||
| -rw-r--r-- | tools/TODO | 26 | ||||
| -rwxr-xr-x | tools/apply-baseupdate.sh | 14 | ||||
| -rwxr-xr-x | tools/create-shellconf.pl | 51 | ||||
| -rwxr-xr-x | tools/dhcp6-nets.pl | 12 | ||||
| -rwxr-xr-x | tools/dlink-ng2dns.pl | 77 | ||||
| -rwxr-xr-x | tools/fetch-debinstall.sh | 17 | ||||
| -rwxr-xr-x | tools/fetch-portlist.sh | 42 | ||||
| -rwxr-xr-x | tools/generate-dnsrr.pl | 147 | ||||
| -rwxr-xr-x | tools/init-sshkeys.sh | 14 | ||||
| -rwxr-xr-x | tools/install-dependencies.sh | 53 | ||||
| -rwxr-xr-x | tools/make-accesspoints.pl | 24 | ||||
| -rwxr-xr-x | tools/make-base-requires.sh | 60 | ||||
| -rwxr-xr-x | tools/make-bind-include.pl | 51 | ||||
| -rwxr-xr-x | tools/make-dhcpd-include.pl | 18 | ||||
| -rwxr-xr-x | tools/make-dhcpd.pl | 104 | ||||
| -rwxr-xr-x | tools/make-first-zones.pl | 124 | ||||
| -rwxr-xr-x | tools/make-linknet-hosts.pl | 34 | ||||
| -rwxr-xr-x | tools/make-missing-conf.pl | 187 | ||||
| -rwxr-xr-x | tools/make-named.pl | 156 | ||||
| -rwxr-xr-x | tools/make-pxeboot.sh | 26 | ||||
| -rwxr-xr-x | tools/make-reverse4-files.pl | 164 | ||||
| -rwxr-xr-x | tools/make-switch-placements.pl | 88 | ||||
| -rwxr-xr-x | tools/make-switches.pl | 33 | ||||
| -rwxr-xr-x | tools/update-baseservice.sh | 29 | ||||
| -rwxr-xr-x | tools/update-tools.sh | 21 | 
26 files changed, 1711 insertions, 0 deletions
diff --git a/tools/README b/tools/README new file mode 100644 index 0000000..2276ebb --- /dev/null +++ b/tools/README @@ -0,0 +1,139 @@ +Outline: +------------------------------------------------------------------ + +  1 Install OS on three boxes +  2 Bootstrap: +     * Install tgmanage on one, the bootstrap (tools, include, netlist.txt) +     * Install dependencies on bootstrap +     * Push SSH key key to the other boxes (init-sshkeys.sh) +     * Update configuration +     * Update netlist.txt +     * Bootstrap the primary and secondary (make-base-requires.sh) +  3 Create new networks/scopes/zones Update during the party using  +    update-baseservice.sh from bootstrap +  4 Apply changes usling tools/apply-baseupdate.sh (reloads bind, restarts dhcpd) +  5 Changes to generated scopes, pools, zones are done on the primary, in the files +  6 If tools need patching, patch on boot and push with update-tools.sh +  7 Before wednesday evening, the infra.tgXX.gathering.org zone should be updated! +  * Only use make-base-requires.sh during bootstrap !!!!!!! :P + +Detailed instructions and description: +================================================================== +  +1: Install Debian +------------------------------------------------------------------ + +The following three hosts/servers are normally used: + * A 'bootstrap' box. This server will be used to configure +   the first TG-servers, and may end up hosting the switch-config and NMS. + * The server to use as Primary DNS and DHCP server + * The server to use as Secondary DNS and SMTP. +Add the three hosts to /etc/hosts, DNS is not available yet... + +2: Perform bootstrapping. +------------------------------------------------------------------ + +Start by placing the 'tgmanage' directory as '/root/tgmanage' on the bootstrap +box.  Change into the 'tgmanage' directory. Next, run +'tools/install-dependencies.sh boot' + + +Edit 'include/config.local.pm' and update for this year's TG.  Use +'tools/create-shellconf.pl' to extract configuration from the perl module to +create/update the 'include/tgmanage.cfg.sh' configuration script. + + +The tools make extensive use of key-based SSH logins, to make this work +seamlessly, run 'tools/init-sshkeys.sh' to create an RSA priv/pub keypair, and +push the pubkey to the Primary and Secondary boxes. + + +The Network-list is _not_ automagically updated. A copy of last year's +netlist.txt should be included in the goodiebag. With that as a base, update +for this year's address plan. Remember that client nets in the hall are +supposed to be pulled from switches.txt ... +The rest of the information needed should be pulled from techwiki.g.o The +format of the file is: one net per line, lines starting with # are skipped, +format of each net-line is: +176.110.124.0 24 noc +# <network adress> <prefixlen> <network-name> + + +Run 'tools/make-base-requires.sh'. This script will log in on the Primary and +Secondary boxes, install dependencies and the BIND/DHCP packages, create all +needed directories, create the initial configuration files. + +A short listing of the tasks of scripts called by make-base-requires: +tools/install-dependencies.sh	Installs needed base software to boot, primary and secondary +tools/make-named.pl		Basic BIND setup (creates named.conf et.al) +tools/make-first-zones.pl	Creates static zone-files (tgname, infra, ipv6zone) +tools/make-reverse4-files.pl	Creates reverse-zones for IPv4 +tools/make-dhcpd.pl		Sets up the base setup for DHCP +NOTE: these scripts are run by tools/make-base-requires.sh, you should not need to +run these individually + +3++: Update during the party using update-baseservice.sh from bootstrap +------------------------------------------------------------------ + +After 'tools/make-base-requires.sh' has been run, further updating should be +managed by the following three files: +tools/update-baseservice.sh	Used to add/update bind and DHCP configuration +tools/apply-baseupdate.sh	Used to reload bind and restart DHCP +tools/update-tools.sh		Used to push changes to the tgmanage toolchain + +This means, after the base setup is completed, updating and managing the +configuration is done by updating netlist.txt and running tools/update-baseservice.sh +from the bootstrap box, or from the NMS box if the toolchain gets moved there during +the party.  + +To create a new DHCP scope, add DNS forward and reverse zone for a new network: + +  * Add the network to netlist.txt +  * Run tools/update-baseservice.sh to generate new .conf and .zone files +  * Run tools/apply-baseupdate.sh to load new configuration + +To do changes to DHCP config after the scope .conf file has been created  +(read: later in the party), log in to the primary/dhcp server, and make  +the changes in the appropriate .conf file .. + +To do DNS changes to the main DNS zone or the infra-zone, make the changes +in the appropriate zone file on the primary DNS server. + +To add DNS records to any other DNS zone (forward or reverse), you have +to use 'nsupdate'. To simplify the process, use tools/generate-dnsrr.pl +Usage on this tool is documented in the "header" of the script... + + +The update prosess is handled by a bunch of "sub-tools", these should typically +not need to be run individually: +tools/make-bind-include.pl	Run via update-baseservice, adds new net's to DNS include +tools/make-dhcpd-include.pl	Run via update-baseservice, adds new net's to DHCP include +tools/make-missing-conf.pl	Run via update-baseservice, adds missing net-conf to BIND/DHCP + + +7: Generation of linknet dns content +------------------------------------------------------------------ + +Format for linknet.txt is documented in make-linknet-hosts.pl + +Generate IPv4 infra hostnames and IP address assignments +by using tools/generate-dnsrr.pl + +> cat linknet.txt | tools/make-linknet-hosts.pl | tools/generate-dnsrr.pl --domain infra.tgXX.gathering.org  +Output from this shuld go in infra.tgXX.gathering.org.zone on primary + +> cat linknet.txt | tools/make-linknet-hosts.pl | tools/generate-dnsrr.pl --domain infra.tgXX.gathering.org -ns -rev +Output from this should go as input to nsupdate, see doc in generate-dnsrr.pl + + +Other stuff.... +------------------------------------------------------------------ +Files that are not used? Need to revisit these files... + +>tools/make-switch-placements.pl + +Updates positions for switches in NMS map (png) + +> tools/make-switches.pl +> tools/fetch-portlist.sh + diff --git a/tools/TODO b/tools/TODO new file mode 100644 index 0000000..70898a3 --- /dev/null +++ b/tools/TODO @@ -0,0 +1,26 @@ +make-first-zones.pl does not add AAAA records for NS'es (pri/sec) +None of the tools add IPv4 reverse for pri/sec +nsupdate log for adding reverse after building base-requires: + +	nsupdate -k Kdhcp_updater.+157+57267.key +	server 176.110.126.2 +	prereq nxdomain 2.126.110.176.in-addr.arpa. +	update add 2.126.110.176.in-addr.arpa. 3600  in ptr abscess.tg12.gathering.org. +	send +	prereq nxdomain 2.125.110.176.in-addr.arpa. +	update add 2.125.110.176.in-addr.arpa. 3600  in ptr acetat.tg12.gathering.org. +	send +	prereq nxdomain 3.125.110.176.in-addr.arpa. +	update add 3.125.110.176.in-addr.arpa. 3600  in ptr abc.tg12.gathering.org. +	send + +Another handy dump, not a TODO-item, just a reminder: + +	prereq nxdomain 3.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.5.2.1.0.a.6.7.0.8.9.7.0.1.0.a.2.ip6.arpa. +	update add 3.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.5.2.1.0.a.6.7.0.8.9.7.0.1.0.a.2.ip6.arpa. 3600 IN PTR abc.tg12.gathering.org. +	send + + +Uhm, our $dhcp_server1 = "176.110.126.2"; <- wtf? + +Opps, forgot to asdd CiscoWLC magic to make-dhcpd.pl includes... diff --git a/tools/apply-baseupdate.sh b/tools/apply-baseupdate.sh new file mode 100755 index 0000000..055320c --- /dev/null +++ b/tools/apply-baseupdate.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +set -e + +source include/tgmanage.cfg.sh +if [ -z ${PRIMARY} ] +then +	echo "Not configured!"; +	exit 1; +fi; + +ssh -l root ${PRIMARY} "/etc/init.d/isc-dhcp-server restart" +ssh -l root ${PRIMARY} "/usr/sbin/rndc reload" +ssh -l root ${SECONDARY} "/usr/sbin/rndc reload" diff --git a/tools/create-shellconf.pl b/tools/create-shellconf.pl new file mode 100755 index 0000000..8e2582d --- /dev/null +++ b/tools/create-shellconf.pl @@ -0,0 +1,51 @@ +#!/usr/bin/perl -I /root/tgmanage +use strict; + +BEGIN { +        require "include/config.pm"; +        eval { +                require "include/config.local.pm"; +        }; +} + +my $bind_base = "/etc/bind/"; +my $dhcpd_base = "/etc/dhcp/"; + +my $shellconf_file = "include/tgmanage.cfg.sh"; + +my $tgname    = $nms::config::tgname; + +my $pri_a     = $nms::config::pri_a; +my $pri_ptr   = $nms::config::pri_ptr; +my $pri_v6    = $nms::config::pri_v6; + +my $sec_a     = $nms::config::sec_a; +my $sec_ptr   = $nms::config::sec_ptr; +my $sec_v6    = $nms::config::sec_v6; + +my $ddns_key  = $nms::config::ddns_key; + +my $base_ipv4net    = $nms::config::base_ipv4net; +my $base_ipv4prefix = $nms::config::base_ipv4prefix; + +my $base_ipv6net    = $nms::config::base_ipv6net; +my $base_ipv6prefix = $nms::config::base_ipv6prefix; + +open CFG, ">" . $shellconf_file or die ($! . " " . $shellconf_file ); + +print CFG "# This file is autogenerated by tools/create-shellconf.pl,\n"; +print CFG "# using data from nms::config.\n"; +print CFG "#\n"; +print CFG "# Do you need new common/configuration variables?\n"; +print CFG "# Add/update include/config.local.pm and tools/create-shellconf.pl\n\n"; +print CFG "PRIMARY=\"$pri_a.$tgname.gathering.org\"\n"; +print CFG "SECONDARY=\"$sec_a.$tgname.gathering.org\"\n"; +print CFG "TGNAME=\"$tgname\"\n\n"; +print CFG "PRI_PTR=\"$pri_ptr\"\n"; +print CFG "SEC_PTR=\"$sec_ptr\"\n\n"; +print CFG "DDNS_KEY=\"$ddns_key\"\n\n"; +print CFG "BASEV4=\"$base_ipv4net\"\n"; +print CFG "PREFIXV4=\"$base_ipv4prefix\"\n"; +print CFG "BASEV6=\"$base_ipv6net\"\n"; +print CFG "PREFIXV6=\"$base_ipv6prefix\"\n"; +close CFG; diff --git a/tools/dhcp6-nets.pl b/tools/dhcp6-nets.pl new file mode 100755 index 0000000..3866ac5 --- /dev/null +++ b/tools/dhcp6-nets.pl @@ -0,0 +1,12 @@ +#!/usr/bin/perl +use strict; +use warnings; + +while(<STDIN>){ +	my ($row, $v6) = split; +	$v6 =~ s/::1/::/; + +	print "subnet6 $v6 {\n"; +	print "\toption domain-name \"$row.tg13.gathering.org\";\n"; +	print "}\n\n"; +} diff --git a/tools/dlink-ng2dns.pl b/tools/dlink-ng2dns.pl new file mode 100755 index 0000000..2b6f965 --- /dev/null +++ b/tools/dlink-ng2dns.pl @@ -0,0 +1,77 @@ +#!/usr/bin/perl +use strict; + +BEGIN { +        require "include/config.pm"; +        eval { +                require "include/config.local.pm"; +        }; +} + +use Net::IP; +use Getopt::Long; + +my ($delete); + +if (@ARGV > 0) { +        GetOptions( +        'del|delete'            => \$delete, +        ) +} + +print "server $nms::config::pri_ptr\n"; + +while (<STDIN>) +{ +	my ( $sysname, $distro, $ponum, $cidr, $ipaddr, $gwaddr, $v6addr, @ports ) = split; +	 +	 +	my $ip = new Net::IP($ipaddr); + +	my $v4gw = new Net::IP($gwaddr); + +	( my $gw6 = $v6addr ) =~ s/\/.*//; +	my $v6gw = new Net::IP($gw6); + +	my $fqdn = $sysname . "." . $nms::config::tgname . ".gathering.org."; +	my $sw_fqdn = $sysname . "-sw." . $fqdn; +	my $text_info = $distro . " - " . join(' + ', @ports) . ", po" . $ponum . ", gwaddr " . $gwaddr; + +	# A-record to the switch +	print "prereq nxdomain " . $sw_fqdn . "\n" unless $delete; +	print "update add " . $sw_fqdn . " \t 3600 IN A \t " . $ipaddr . "\n" unless $delete; +	print "update delete " . $sw_fqdn . " \t IN A\n" if $delete; +	print "send\n"; + +	# PTR to the switch +	print "prereq nxdomain " . $ip->reverse_ip() . "\n" unless $delete; +	print "update add " . $ip->reverse_ip() . " \t 3600 IN PTR \t " . $sw_fqdn . "\n" unless $delete; +	print "update delete " . $ip->reverse_ip() . " \t IN PTR\n" if $delete; +	print "send\n"; + +	# TXT-record with details +	print "update delete " . $sw_fqdn . " IN TXT\n" unless $delete; +	print "update add " . $sw_fqdn . " \t 3600 IN TXT \t \"" . $text_info . "\"\n" unless $delete; +	print "update delete " . $sw_fqdn . " \t IN TXT\n" if $delete; +	print "send\n"; + +	# A and AAAA-record to the gateway/router +	print "prereq nxrrset gw." . $fqdn . " IN A\n" unless $delete; +        print "update add gw." . $fqdn . " \t 3600 IN A \t " . $gwaddr . "\n" unless $delete; +	print "update delete gw." . $fqdn . " \t IN A\n" if $delete; +        print "send\n"; +	print "prereq nxrrset gw." . $fqdn . " IN AAAA\n" unless $delete; +        print "update add gw." . $fqdn . " \t 3600 IN AAAA \t " . $gw6 . "\n" unless $delete; +	print "update delete gw." . $fqdn . " \t IN AAAA\n" if $delete; +        print "send\n"; + +	# PTR to the gateway/router +	print "prereq nxdomain " . $v4gw->reverse_ip() . "\n" unless $delete; +        print "update add " . $v4gw->reverse_ip() . " \t 3600 IN PTR \t gw." . $fqdn . "\n" unless $delete; +	print "update delete " . $v4gw->reverse_ip() . " \t IN PTR\n" if $delete; +        print "send\n"; +	print "prereq nxdomain " . $v6gw->reverse_ip() . "\n" unless $delete; +        print "update add " . $v6gw->reverse_ip() . " \t 3600 IN PTR \t gw." . $fqdn . "\n" unless $delete; +	print "update delete " . $v6gw->reverse_ip() . " \t IN PTR\n" if $delete; +        print "send\n"; +} diff --git a/tools/fetch-debinstall.sh b/tools/fetch-debinstall.sh new file mode 100755 index 0000000..069e39a --- /dev/null +++ b/tools/fetch-debinstall.sh @@ -0,0 +1,17 @@ +#!/bin/bash -xe +INSTALLER_DEST=$1 +DEBINSTROOT=http://ftp.no.debian.org/debian/dists + +mkdir -p ${INSTALLER_DEST}/{squeeze,wheezy}/{amd64,i386} +for DIST in squeeze wheezy +do  +  for ARCH in i386 amd64;  +  do  +    for FILE in initrd.gz linux +    do  +      wget ${DEBINSTROOT}/${DIST}/main/installer-${ARCH}/current/images/netboot/debian-installer/${ARCH}/${FILE} \ +           -O ${INSTALLER_DEST}/${DIST}/${ARCH}/${FILE} +    done +  done +done + diff --git a/tools/fetch-portlist.sh b/tools/fetch-portlist.sh new file mode 100755 index 0000000..94ca41c --- /dev/null +++ b/tools/fetch-portlist.sh @@ -0,0 +1,42 @@ +print_range() { +	FIRST=$1 +	LAST=$2 +	if [ "$1" = "$2" ]; then +		echo $FIRST +	else +		echo $FIRST-$LAST +	fi +} + +walk_ports() { +	IP=$1 +	COMMUNITY=$2 + +	FIRST_PORT= +	LAST_PORT= + +	for PORT in $( snmpwalk -Os -m IF-MIB -v 2c -c $COMMUNITY $IP ifDescr 2>/dev/null | grep -E 'GigE|Ethernet' | cut -d. -f2 | cut -d" " -f1 ); do +		if ! snmpget -m IF-MIB -v 2c -c $COMMUNITY $IP ifHCInOctets.$PORT 2>/dev/null | grep -q 'No Such Instance'; then +			if [ "$LAST_PORT" ] && [ `expr $LAST_PORT + 1` = $PORT ]; then +				LAST_PORT=$PORT +			else +				if [ "$LAST_PORT" ]; then +					print_range $FIRST_PORT $LAST_PORT +				fi +				FIRST_PORT=$PORT +				LAST_PORT=$PORT +			fi +		fi +	done + +	print_range $FIRST_PORT $LAST_PORT +} + +COMMUNITY=$1 +IP=$2 +SYSNAME=$3 +PORTS=$( walk_ports $IP $COMMUNITY | tr "\n" "," | sed 's/,$//' ) + +echo "insert into switchtypes values ('$SYSNAME','$PORTS',true);" +echo "insert into switches values (default,'$IP','$SYSNAME','$SYSNAME',null,default, default, '1 minute', '$COMMUNITY');" + diff --git a/tools/generate-dnsrr.pl b/tools/generate-dnsrr.pl new file mode 100755 index 0000000..789f268 --- /dev/null +++ b/tools/generate-dnsrr.pl @@ -0,0 +1,147 @@ +#!/usr/bin/perl -I /root/tgmanage +# +# USAGE: +#  Generate BIND Zone-file data based on the file hosts-to-add.txt +#  cat hosts-to-add.txt | tools/generate-dnsrr.pl  +# +#  Generate input data for nsupdate, to add FORWARD records based on hosts-to-add.txt +#  cat hosts-to-add.txt | tools/generate-dnsrr.pl --domain foo.tgXX.gathering.org -ns +#   +#  Generate input data for nsupdate, to add REVERSE records based on hosts-to-add.txt +#  cat hosts-to-add.txt | tools/generate-dnsrr.pl --domain foo.tgXX.gathering.org -ns -rev +# +#  Generate input data for nsupdate, to DELETE forward records based on hosts-to-add.txt +#  cat hosts-to-DELETE.txt | tools/generate-dnsrr.pl --domain foo.tgXX.gathering.org -ns -del +#   +#  Generate input data for nsupdate, to DELETE reverse records based on hosts-to-add.txt +#  cat hosts-to-DELETE.txt | tools/generate-dnsrr.pl --domain foo.tgXX.gathering.org -ns -rev -del +#  +#  Command-syntax to send this to nsupdate, running it on the DNS server: +#  cat file.txt | tools/generate-dnsrr.pl --dom foo -ns | ssh $dnsserver "nsupdate -k /etc/bind/Kdhcp_updater.+157+XXXXX" +# +# Format of input: +# hostname  ipv4-adress ipv6-address +#  If any of ipv4-address or ipv6-address are NOT set for the host, specify "nope" +#  Lines starting with # will (should) be skipped (comments) +# +# Example: +# +# host1  192.168.0.1 2001:db8:f00::1 +# host2  nope        2001:db8:f00::2 +# host3  192.168.0.3 nope +# # comment, to be ignored. +# host4  192.168.0.4 + +use strict; +use warnings; +use lib '..'; +BEGIN { +        require "include/config.pm"; +        eval { +                require "include/config.local.pm"; +        }; +} +use Net::IP; +use Getopt::Long; + +my ($delete, $auto, $nsupdate, $reverse, $domain); + +if (@ARGV > 0) { +	GetOptions( +	'del|delete'		=> \$delete, +	'a|auto'		=> \$auto, +	'ns|nsupdate'		=> \$nsupdate, +	'r|reverse'		=> \$reverse, +	'domain=s'		=> \$domain +	) +} + +if ($nsupdate || $reverse){ +	unless (defined($domain)){ +		print "Missing domain.\n"; +		exit 1 unless defined($domain); +	} +} + +$domain = "." . $domain if defined($domain); + +print "server $nms::config::pri_ptr\n" if ($nsupdate || $reverse); + +while (<STDIN>) { +	next if /^(#|\s+$)/;	# skip if comment, or blank line + +	my ($hostname, $ipv4, $ipv6) = split; +	$hostname = lc($hostname); +	 +	unless ($ipv6){ +		if ($auto){ +			# Get IPv6-address based on IPv4-address +		 +			my ($first, $second, $third, $fourth) = split('\.', $ipv4); +			$ipv6 = $nms::config::base_ipv6net . $third . "::" . $fourth; +		} +	} +	 +	if ($reverse){ +		# print ptr +		print_ptr($hostname, $ipv4, $ipv6); +	} else { +		# print forward +		print_fwd($hostname, $ipv4, $ipv6); +	} +} + +sub print_ptr{ +	my ($hostname, $ipv4, $ipv6) = @_; + +	# IPv4 +	unless ( $ipv4 eq "nope" ) { +		my $v4 = new Net::IP($ipv4); +		 +		print "prereq nxdomain " . $v4->reverse_ip() . "\n" unless $delete; +		print "update add " . $v4->reverse_ip() . " 3600 IN PTR " . $hostname . $domain .".\n" unless $delete; +		print "update delete "  . $v4->reverse_ip() . " IN PTR\n" if $delete; +		print "send\n"; +	}	 + +	# IPv6 +	if (( not ($ipv6 eq "nope") ) && ( $ipv6 )) { +		my $v6 = new Net::IP($ipv6); +		 +		print "prereq nxdomain " . $v6->reverse_ip() . "\n" unless $delete; +		print "update add " . $v6->reverse_ip() . " 3600 IN PTR " . $hostname . $domain . ".\n" unless $delete; +		print "update delete " . $v6->reverse_ip() . " IN PTR\n" if $delete; +		print "send\n"; +	} +} + +sub print_fwd{ +	my ($hostname, $ipv4, $ipv6) = @_; +	 +	if ($nsupdate){ + +		unless ( $ipv4 eq "nope" ) { +			# IPv4 +			print "prereq nxrrset " . $hostname . $domain . " IN A\n" unless $delete; +			print "update add " . $hostname . $domain . " 3600 IN A $ipv4\n" unless $delete; +			print "update delete " . $hostname . $domain . " IN A\n" if $delete; +			print "send\n"; +		} +		if (( not ($ipv6 eq "nope") ) && ( $ipv6 )) { +			# IPv6 +			print "prereq nxrrset " . $hostname . $domain . " IN AAAA\n" unless $delete; +                	print "update add " . $hostname . $domain . " 3600 IN AAAA $ipv6\n" unless $delete; +	                print "update delete " . $hostname . $domain . " IN AAAA\n" if $delete; +        	        print "send\n"; +		} +	} else { +		# IPv4 +		unless ( $ipv4 eq "nope" ) { +			printf ("%-24s%s\t%s\t%s\n", $hostname, "IN", "A", $ipv4); +		} +		# IPv6 +		if (( not ($ipv6 eq "nope") ) && ( $ipv6 )) { +			printf ("%-24s%s\t%s\t%s\n", $hostname, "IN", "AAAA", $ipv6) if ($ipv6); +		} +	} +} diff --git a/tools/init-sshkeys.sh b/tools/init-sshkeys.sh new file mode 100755 index 0000000..9427bad --- /dev/null +++ b/tools/init-sshkeys.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +set -e + +source include/tgmanage.cfg.sh +if [ -z ${PRIMARY} ] +then +	echo "Not configured!"; +	exit 1; +fi; + +ssh-keygen -P '' -f ~/.ssh/id_rsa -b 2048 +ssh-copy-id root@${PRIMARY} +ssh-copy-id root@${SECONDARY} diff --git a/tools/install-dependencies.sh b/tools/install-dependencies.sh new file mode 100755 index 0000000..bf68134 --- /dev/null +++ b/tools/install-dependencies.sh @@ -0,0 +1,53 @@ +#!/bin/bash -e + +if [ "$1" != "master" -a "$1" != "slave" -a "$1" != "boot" ]; then +	echo "Run as $0 <boot|master|slave>" +	exit +fi + +# OK, we know the content of $0 is OK. I prefer sane names. +ROLE=$1; + +# Start by installing common packages. Remember to update +# this when a new common dependency is discovered, plx. +apt-get -y install \ +	vim-nox \ +	git \ +	ntp \ +	screen \ +	dnsutils \ +	build-essential \ +	libnet-ip-perl \ +	libnetaddr-ip-perl \ +	libnet-telnet-cisco-perl \ +	libnet-ping-external-perl \ +	perl-modules \ +	libdbi-perl \ +	libdbd-pg-perl \ +	libnet-telnet-perl  + +if [ "${ROLE}" == "boot" ]; then +	# Install-tasks specific for the _bootstrab box_ here +	echo "Installing for bootstrap" +	apt-get -y install \ +		bind9utils +fi + +if [ "${ROLE}" == "master" ]; then +	# Install-tasks specific for the _primary_ here +	echo "Installing for primary/master" +	apt-get -y install \ +		isc-dhcp-server \ +		bind9utils \ +		bind9 +fi + +if [ "${ROLE}" == "slave" ]; then +	# Install-tasks specific for the _secondary_ here +	echo "Installing for secondary/slave" +	apt-get -y install \ +		bind9utils \ +		bind9	 +fi + +echo "Dependency installation for ${ROLE} complete." diff --git a/tools/make-accesspoints.pl b/tools/make-accesspoints.pl new file mode 100755 index 0000000..b84321a --- /dev/null +++ b/tools/make-accesspoints.pl @@ -0,0 +1,24 @@ +#! /usr/bin/perl +use strict; +use warnings; + +while (<>) { +	my @arr = split " "; +	my $ap = 'ap-'.$arr[0]; +	my $core = $arr[1]; +	# Trekk fra 1 +	$core =~ s/^(distro)(\d+)$/$1.($2-1)/e; + +	# Fjerde kabel er aksesspunkt +	my $blade; +	my $port; +	if ($arr[5] =~ /^Gi(\d+)\/(\d+)$/) { +		$blade = $1; +		$port = $2; +	} else { +		die "Unknown port: ".$arr[5]; +	} +	printf "INSERT INTO switches(ip, sysname, switchtype) values(inet '127.0.0.1', '%s', 'ciscoap');\n", $ap; +	printf "INSERT INTO uplinks SELECT (SELECT switch FROM switches WHERE sysname = '%s') AS switch, (SELECT switch FROM switches WHERE sysname = '%s') AS coreswitch, %d AS blade, %d AS port;\n", $ap, $core, $blade, $port; +	printf "INSERT INTO ap_poll(switch) SELECT switch FROM switches WHERE sysname = '%s';\n", $ap; +} diff --git a/tools/make-base-requires.sh b/tools/make-base-requires.sh new file mode 100755 index 0000000..d19ffd9 --- /dev/null +++ b/tools/make-base-requires.sh @@ -0,0 +1,60 @@ +#!/bin/bash + +set -e + +BASE="/etc"; +if [ "$1" != "" ] +then +	BASE=$1 +	echo "Using base path ${BASE}" +fi + +source include/tgmanage.cfg.sh +if [ -z ${PRIMARY} ] +then +	echo "Not configured!"; +	exit 1; +fi; + +tools/update-tools.sh +ssh -l root ${PRIMARY} "~/tgmanage/tools/install-dependencies.sh master" +ssh -l root ${SECONDARY} "~/tgmanage/tools/install-dependencies.sh slave" + +if [ "${BASE}" == "/etc" ]; then +	ssh -l root ${PRIMARY} "cp -pR /etc/bind /etc/bind.dist" +	ssh -l root ${PRIMARY} "cp -pR /etc/dhcp /etc/dhcp.dist" +	ssh -l root ${SECONDARY} "cp -pR /etc/bind /etc/bind.dist" + +	set +e +	ssh -l root ${PRIMARY} "rm /etc/bind/named.conf" +	ssh -l root ${PRIMARY} "rm /etc/dhcp/dhcpd.conf" +	ssh -l root ${SECONDARY} "rm /etc/bind/named.conf" +	set -e +fi + +ssh -l root ${PRIMARY} "mkdir -p ${BASE}/bind/conf-master/" +ssh -l root ${PRIMARY} "mkdir -p ${BASE}/bind/reverse/" +ssh -l root ${PRIMARY} "mkdir -p ${BASE}/bind/dynamic/" +ssh -l root ${PRIMARY} "mkdir -p ${BASE}/dhcp/conf.d/" +ssh -l root ${PRIMARY}   "~/tgmanage/tools/make-named.pl master ${BASE}" +ssh -l root ${PRIMARY}   "~/tgmanage/tools/make-dhcpd.pl ${BASE}" +ssh -l root ${PRIMARY}   "~/tgmanage/tools/make-first-zones.pl ${BASE}" +ssh -l root ${PRIMARY}   "~/tgmanage/tools/make-reverse4-files.pl master ${BASE}" + +ssh -l root ${SECONDARY} "mkdir -p ${BASE}/bind/conf-slave/" +ssh -l root ${SECONDARY} "mkdir -p ${BASE}/bind/slave/" +ssh -l root ${SECONDARY} "~/tgmanage/tools/make-named.pl slave ${BASE}" +ssh -l root ${SECONDARY} "~/tgmanage/tools/make-reverse4-files.pl slave ${BASE}" + +set +e +ssh -l root ${PRIMARY}   "chown -R bind.bind ${BASE}/bind" +ssh -l root ${SECONDARY} "chown -R bind.bind ${BASE}/bind" +set -e + +ssh -l root ${PRIMARY}   "echo THIS COPY OF TGMANAGE IS MANAGED FROM BOOTSTRAP SERVER > ~/tgmanage/NOTICE" +ssh -l root ${SECONDARY} "echo THIS COPY OF TGMANAGE IS MANAGED FROM BOOTSTRAP SERVER > ~/tgmanage/NOTICE" + +# No point in _not_ running update-baseservice at this point.... +tools/update-baseservice.sh ${BASE} + +# all done. diff --git a/tools/make-bind-include.pl b/tools/make-bind-include.pl new file mode 100755 index 0000000..d688dec --- /dev/null +++ b/tools/make-bind-include.pl @@ -0,0 +1,51 @@ +#!/usr/bin/perl -I /root/tgmanage + +# TODO: Port this to the "master|slave base" parameter syntax! + +use strict; + +unless ( (($#ARGV == 0 ) || ( $#ARGV == 1)) +	&& (( $ARGV[0] eq "master" ) || ( $ARGV[0] eq "slave" )) ) +{ +	print STDERR "Invalid usage!\ncat netnames.txt | $0 <master|slave> [basedir]\n"; +	exit 1; +} + +my $role = $ARGV[0]; + +my $base = "/etc"; +$base = $ARGV[1] if $#ARGV == 1; +$base .= "/" if not $base =~ m/\/$/ and not $base eq ""; + +my $bind_base = $base . "bind/"; +my $masterinclude = $bind_base . "named.master-include.conf"; +my $slaveinclude  = $bind_base . "named.slave-include.conf"; + +my $glob; +my @configs; + +if ( $role eq "master" ) +{ +	$glob = $bind_base . "conf-master/*.conf"; +	@configs = glob($glob); + +	open CONF, ">" . $masterinclude or die ( $! . " " . $masterinclude); +	foreach my $config ( @configs ) +	{ +		print CONF "include \"" . $config . "\";\n"; +	} +	close CONF; +} + +if ( $role eq "slave" ) +{ +	$glob = $bind_base . "conf-slave/*.conf"; +	@configs = glob($glob); + +	open CONF, ">" . $slaveinclude or die ( $! . " " . $slaveinclude); +	foreach my $config ( @configs ) +	{ +		print CONF "include \"" . $config . "\";\n"; +	} +	close CONF; +} diff --git a/tools/make-dhcpd-include.pl b/tools/make-dhcpd-include.pl new file mode 100755 index 0000000..ded5551 --- /dev/null +++ b/tools/make-dhcpd-include.pl @@ -0,0 +1,18 @@ +#!/usr/bin/perl -I /root/tgmanage +use strict; +my $base = "/etc"; +$base = $ARGV[0] if $#ARGV > -1; +$base .= "/" if not $base =~ m/\/$/ and not $base eq ""; + +my $dhcpd_base = $base . "dhcp/"; +my $includeconfig = $dhcpd_base . "generated-include.conf"; + +my $glob = $dhcpd_base . "conf.d/*.conf"; +my @configs = glob($glob); + +open CONF, ">" . $includeconfig or die ( $! . " " . $includeconfig); +foreach my $config ( @configs ) +{ +	print CONF "include \"" . $config . "\";\n"; +} +close CONF; diff --git a/tools/make-dhcpd.pl b/tools/make-dhcpd.pl new file mode 100755 index 0000000..2cf388a --- /dev/null +++ b/tools/make-dhcpd.pl @@ -0,0 +1,104 @@ +#!/usr/bin/perl -I /root/tgmanage +use strict; + +use Net::IP; +use Net::IP qw(:PROC); + +BEGIN { +        require "include/config.pm"; +        eval { +                require "include/config.local.pm"; +        }; +} + +my $base = "/etc"; +$base = $ARGV[0] if $#ARGV > -1; +$base .= "/" if not $base =~ m/\/$/ and not $base eq ""; + +my $dhcpd_base = $base . "dhcp/"; +my $dhcpd_conf =  $dhcpd_base . "dhcpd.conf"; +my $dhcp_pxeconf =  $dhcpd_base . "pxe-boot.conf"; +my $dhcp_ciscoapconf =  $dhcpd_base . "ciscowlc.conf"; + +my $tgname    = $nms::config::tgname; +my $pri_ptr   = $nms::config::pri_ptr; +my $pri_net   = $nms::config::pri_net; +my $sec_ptr   = $nms::config::sec_ptr; +my $pxe_server = $nms::config::pxe_server; +my $ddns_key  = $nms::config::ddns_key; +my $ciscowlc_a  = $nms::config::ciscowlc_a; + +my $range = new Net::IP( $pri_net ) or die ("oopxos"); +my $mask = $range->mask();	 +my ($net, undef) = split "/", $pri_net; + + +# Create PXE-boot configuration file for DHCP on master. +if ( not -f $dhcpd_conf ) +{ +		print STDERR "Creating file " . $dhcpd_conf . "\n"; +		open DHCPDFILE, ">" . $dhcpd_conf or die ( $! . " " . $dhcpd_conf); + +		print DHCPDFILE <<"EOF"; +# GENERATED BY make-dhcpd.pl +# +# Central concept: as little config in the main .conf, +# include almost everything from separate files.. +# +# log-facility local7; +option domain-name "$tgname.gathering.org"; +option domain-name-servers $pri_ptr, $sec_ptr; +default-lease-time 3600; +max-lease-time 7200; +authoritative; + +ddns-update-style interim; +key DHCP_UPDATER { +        algorithm HMAC-MD5.SIG-ALG.REG.INT; +        secret $ddns_key; +} + +subnet $net netmask $mask {} + +include "/etc/dhcp/revzones.conf"; +include "/etc/dhcp/generated-include.conf"; +include "/etc/dhcp/pxe-boot.conf"; +include "/etc/dhcp/ciscowlc.conf"; + +EOF +		close DHCPDFILE; +} + +# Create PXE-boot configuration file for DHCP on master. +if ( not -f $dhcp_pxeconf ) +{ +		print STDERR "Creating file " . $dhcp_pxeconf . "\n"; +		open PXEFILE, ">" . $dhcp_pxeconf or die ( $! . " " . $dhcp_pxeconf); + +		print PXEFILE "next-server " . $pxe_server . ";\n"; +		print PXEFILE "filename \"pxelinux.0\";\n"; + +		close PXEFILE; +} + + +# Create PXE-boot configuration file for DHCP on master. +if ( not -f $dhcp_ciscoapconf ) +{ +		print STDERR "Creating file " . $dhcp_ciscoapconf . "\n"; +		open CISCOFILE, ">" . $dhcp_ciscoapconf or die ( $! . " " . $dhcp_pxeconf); + +		print CISCOFILE <<"EOF"; +option space CiscoAP; +option CiscoAP.server-address code 241 = array of ip-address; +set vendor-string = option vendor-class-identifier; + +class "cisco-aps" { +       match if substring (option vendor-class-identifier, 0, 8) = "Cisco AP"; +       vendor-option-space CiscoAP; +       option CiscoAP.server-address $ciscowlc_a; +} +EOF +		close CISCOFILE; +} + diff --git a/tools/make-first-zones.pl b/tools/make-first-zones.pl new file mode 100755 index 0000000..1227129 --- /dev/null +++ b/tools/make-first-zones.pl @@ -0,0 +1,124 @@ +#!/usr/bin/perl -I /root/tgmanage +use strict; + +use Net::IP; + +BEGIN { +        require "include/config.pm"; +        eval { +                require "include/config.local.pm"; +        }; +} + +my $base = "/etc"; +$base = $ARGV[0] if $#ARGV > -1; +$base .= "/" if not $base =~ m/\/$/ and not $base eq ""; + +my $tgname    = $nms::config::tgname; +my $pri_a     = $nms::config::pri_a; +my $pri_ptr   = $nms::config::pri_ptr; +my $pri_v6    = $nms::config::pri_v6; +my $sec_a     = $nms::config::sec_a; +my $sec_ptr   = $nms::config::sec_ptr; +my $sec_v6    = $nms::config::sec_v6; +my $ipv6zone = $nms::config::ipv6zone; + +# FIXME: THIS IS NOT APPRORPIATE! +my $serial = `date +%Y%m%d01`; +chomp $serial; +# FIXME + +my $zonefile; + +$zonefile = $base . "bind/" . $tgname . ".gathering.org.zone"; +if ( not -f  $zonefile ) +{ +	print $zonefile . "\n"; +	open MAINZONE, ">" . $zonefile or die $! . " " . $zonefile; + +	print MAINZONE <<"EOF"; +\$TTL 3600 +@	IN	SOA	$pri_a.$tgname.gathering.org.	abuse.gathering.org. ( +			$serial; serial +			3600 ; refresh  +			1800 ; retry +			608400 ; expire +			3600 ) ; minimum and default TTL + +		IN	NS	ns1.$tgname.gathering.org. +		IN	NS	ns2.$tgname.gathering.org. + +ns1		IN	A	$pri_ptr +ns1		IN	AAAA	$pri_v6 +ns2		IN	A	$sec_ptr +ns2		IN	AAAA	$sec_v6 +$pri_a		IN	A	$pri_ptr +$pri_a		IN	AAAA	$pri_v6 +$sec_a		IN	A	$sec_ptr +$sec_a		IN	AAAA	$sec_v6 + +; Generated by make-all-config.sh on the bootstrapping/nms server. +; Will not be overwritten unless it is missing ;) + +EOF +	close MAINZONE; +} +else { print "Skipped TG-zone, file exists.\n"; } + +$zonefile = $base . "bind/infra." . $tgname . ".gathering.org.zone"; +if ( not -f  $zonefile ) +{ +	print $zonefile . "\n"; +	open MAINZONE, ">" . $zonefile or die $! . " " . $zonefile; + +	print MAINZONE <<"EOF"; +\$TTL 3600 +@	IN	SOA	$pri_a.$tgname.gathering.org.	abuse.gathering.org. ( +			$serial; serial +			3600 ; refresh  +			1800 ; retry +			608400 ; expire +			3600 ) ; minimum and default TTL + +		IN	NS	$pri_a.$tgname.gathering.org. +		IN	NS	$sec_a.$tgname.gathering.org. + +; Generated by make-all-config.sh on the bootstrapping/nms server. +; Will not be overwritten unless it is missing ;) +EOF +	close MAINZONE; +} +else { print "Skipped infra-zone, file exists.\n"; } + +$zonefile = $base . "bind/" . $ipv6zone . ".zone"; +if ( not -f  $zonefile ) +{ +	print $zonefile . "\n"; +	open IPV6ZONE, ">" . $zonefile or die $! . " " . $zonefile; + +	print IPV6ZONE <<"EOF"; +; autogenerated, and updated from dhcpd -- DO NOT TOUCH! +\$TTL 3600 +@       IN      SOA     ns1.$tgname.gathering.org. abuse.gathering.org. ( +			$serial; serial +                        3600 ; refresh +                        1800 ; retry +                        608400 ; expire +                        3600 ) ; minimum and default TTL + +                IN      NS      ns1.$tgname.gathering.org. +                IN      NS      ns2.$tgname.gathering.org. + +; WARNING! Do not edit this file directly! +; on the bootstrapping/nms server! + +EOF +	my $ip_pri = new Net::IP( $pri_v6 ) or die ( "Error, new Net::IP for " . $pri_v6 ); +	my $ip_sec = new Net::IP( $sec_v6 ) or die ( "Error, new Net::IP for " . $sec_v6 ); +	print IPV6ZONE $ip_pri->reverse_ip() . " IN PTR ns1.$tgname.gathering.org.\n"; +	print IPV6ZONE $ip_pri->reverse_ip() . " IN PTR $pri_a.$tgname.gathering.org.\n"; +	print IPV6ZONE $ip_sec->reverse_ip() . " IN PTR ns2.$tgname.gathering.org.\n"; +	print IPV6ZONE $ip_sec->reverse_ip() . " IN PTR $sec_a.$tgname.gathering.org.\n"; +	close IPV6ZONE; +} +else { print "Skipped v6-reverse-zone, file exists.\n"; } diff --git a/tools/make-linknet-hosts.pl b/tools/make-linknet-hosts.pl new file mode 100755 index 0000000..d535832 --- /dev/null +++ b/tools/make-linknet-hosts.pl @@ -0,0 +1,34 @@ +#!/usr/bin/perl +use NetAddr::IP; +use Net::IP; +# +# Input file format: +# +# ipv4-link-network router1 router2 +# +# e.g. +# 151.216.0.2  telegw nocgw +# 151.216.0.4  telegw cam +# 151.216.0.6  nocgw coren +# 151.216.0.8  telegw pressegw +# +# Note: IPv6 linknets use link-local adresses, so they are not included in list. +# +while (<STDIN>) { +        next if /^(#|\s+$)/;    # skip if comment, or blank line +	 +	my ($ipv4_raw, $from, $to) = split; +	my $ipv4; +	 +	# Assumes ipv4 address is the first address in a /31 :-))  +	$ipv4 = NetAddr::IP->new($ipv4_raw."/31") unless $ipv4=~/no/; +	printf STDERR "Missing IPv4 scope for linket %s -> %s\n", $from, $to if not $ipv4; +	next if not $ipv4; + +	 +	# generate-dnsrr.pl format: +	# hostname ipv4 ipv6 (with nope as valid null argument) +	my $ipv4_other =  $ipv4 +1; +	printf("%s-%s %s nope\n", $from, $to, $ipv4->addr);  +	printf("%s-%s %s nope\n", $to, $from, $ipv4_other->addr);  +} diff --git a/tools/make-missing-conf.pl b/tools/make-missing-conf.pl new file mode 100755 index 0000000..f0fb0a0 --- /dev/null +++ b/tools/make-missing-conf.pl @@ -0,0 +1,187 @@ +#!/usr/bin/perl -I /root/tgmanage +use strict; + +BEGIN { +        require "include/config.pm"; +        eval { +                require "include/config.local.pm"; +        }; +} + + +use Net::IP; +use Net::IP qw(:PROC); + +# FIXME: THIS IS NOT APPRORPIATE! +my $serial = `date +%Y%m%d01`; +chomp $serial; +# FIXME + +unless ( (($#ARGV == 0 ) || ( $#ARGV == 1)) +	&& (( $ARGV[0] eq "master" ) || ( $ARGV[0] eq "slave" )) ) +{ +	print STDERR "Invalid usage!\ncat netnames.txt | $0 <master|slave> [basedir]\n"; +	exit 1; +} + +my $role = $ARGV[0]; + +my $base = "/etc"; +$base = $ARGV[1] if $#ARGV == 1; +$base .= "/" if not $base =~ m/\/$/ and not $base eq ""; + + +print STDERR "Role is " . $role . "\n"; +print STDERR "Base dir is " . $base . "\n"; + +my $bind_base =  $base . "bind/"; +my $dhcpd_base = $base . "dhcp/"; + +my $dhcp_dynconf_dir =  $dhcpd_base . "conf.d/"; +my $bind_conf_master = $bind_base . "conf-master/"; +my $bind_conf_slave  = $bind_base . "conf-slave/"; + +my $tgname    = $nms::config::tgname; + +my $pri_a     = $nms::config::pri_a; +my $pri_ptr   = $nms::config::pri_ptr; +my $pri_v6    = $nms::config::pri_v6; + +my $sec_a     = $nms::config::sec_a; +my $sec_ptr   = $nms::config::sec_ptr; +my $sec_v6    = $nms::config::sec_v6; + +my $ext_xfer  = $nms::config::ext_xfer; +my $ext_ns    = $nms::config::ext_ns; + +my $ddns_key  = $nms::config::ddns_key; + +my $base_ipv4net    = $nms::config::base_ipv4net; +my $base_ipv4prefix = $nms::config::base_ipv4prefix; + +my $ddns_to = $nms::config::ddns_to; + +my $base_ipv4 = new Net::IP( $base_ipv4net . "/" . $base_ipv4prefix ); + +$base_ipv4net =~ m/^(\d+)\.(\d+)\.(\d+)\..*/; +my ( $cp_oct, $cs_oct, $ct_oct ) = ( $1, $2, $3 ); + +while ( <STDIN> ) +{ +	next if ( $_ =~ m/^#/); +	my $line = $_; +	chomp $line; +	die ("Invalid format on input") if not $line =~ m/^(\d+)\.(\d+)\.(\d+)\.(\d+)\s+(\d+)\s+([\w|-]+)\s*.*/; +	my ( $p_oct, $s_oct, $t_oct, $f_oct, $size, $name ) = ( $1, $2, $3, $4, $5, $6 ); +	 + +	my $dhconfig = $dhcp_dynconf_dir . $name . ".conf"; +	my $master_config =  $bind_conf_master . $name . ".conf"; +	my $slave_config =  $bind_conf_slave . $name . ".conf"; +	my $zone_file = $bind_base . "dynamic/$name.$tgname.gathering.org.zone"; +	 +	my $net_base = $p_oct . "." .  $s_oct . "." .  $t_oct; +	my $net =  $net_base . "." .  $f_oct; +	my $range = new Net::IP( $net . "/" . $size ) or die ("oopxos"); + +	# Create configuration files for DHCP on master/primary +	if ( ( not -f $dhconfig ) && ( $role eq "master" ) ) +	{ +		print STDERR "Creating file " . $dhconfig . "\n"; +		my $numhosts = $range->size(); +		my $mask = $range->mask();	 +		my $router = $net_base . "." .  ($f_oct+1); +		my $first = $net_base . "." . ( $f_oct + 5 ); + +		my $last = $first; +		if ( $size < 24 ) +		{ +			# Net::IP iteration is crazyslow. So, we stopped using iterations. +			my $last_ip = $range->last_ip(); +			$last_ip =~ m/(\d+)\.(\d+)\.(\d+)\.(\d+)/; +			$last = sprintf("%d.%d.%d.%d", $1, $2, $3, $4-2); +		} +		else { $last = $net_base . "." . ( $f_oct + $numhosts - 2 ); } + +		#print STDERR "Name     : " . $name . "\n"; +		#print STDERR "Net      : " . $net . "\n"; +		#print STDERR "Mask     : " . $mask . "\n"; +		#print STDERR "Router   : " . $router . "\n"; +		#print STDERR "Size     : " . $size . "\n"; +		#print STDERR "Numhosts : " . $numhosts . "\n"; +		#print STDERR "First    : " . $first . "\n"; +		#print STDERR "Last     : " . $last . "\n"; + +		open DFILE, ">" . $dhconfig or die ( $! . " " . $dhconfig); + +		print DFILE "zone $name.$tgname.gathering.org {\n"; +		print DFILE "    primary $ddns_to;\n"; +		print DFILE "    key DHCP_UPDATER;\n"; +		print DFILE "}\n\n"; + +		print DFILE "subnet $net netmask $mask {\n"; +		print DFILE "    authoritative;\n"; +		print DFILE "    option routers $router;\n"; +		print DFILE "    option domain-name \"$name.$tgname.gathering.org\";\n"; +		print DFILE "    ddns-domainname \"$name.$tgname.gathering.org\";\n"; +		print DFILE "    range $first $last;\n"; +		print DFILE "    ignore client-updates;\n"; +		print DFILE "}\n\n"; + +		close DFILE; +	} + +	# Create zone files for bind9 on master/primary +	if ( ( not -f $zone_file ) && ( $role eq "master" ) ) +	{ +		print STDERR "Creating file " . $zone_file . "\n"; +		open ZFILE, ">" . $zone_file or die ( $! . " " . $zone_file); +		print ZFILE << "EOF"; +; Base reverse zones are updated from dhcpd -- DO NOT TOUCH! +\$TTL 3600 +@	IN	SOA	$pri_a.$tgname.gathering.org.	abuse.gathering.org. ( +                        $serial   ; serial +                        3600 ; refresh +                        1800 ; retry +                        608400 ; expire +                        3600 ) ; minimum and default TTL + +		IN	NS	$pri_a.$tgname.gathering.org. +		IN	NS	$sec_a.$tgname.gathering.org. +\$ORIGIN $name.$tgname.gathering.org. +EOF +		close ZFILE; +	} + + +	# Create bind9 configuration files for zones. +	my $bind_file = ""; +	$bind_file = $master_config if ( $role eq "master"); +	$bind_file = $slave_config if ( $role eq "slave"); +	die ("WTF, role does not match 'master' or 'slave'" ) if ( $bind_file eq ""); + +	if ( not -f $bind_file ) +	{ +		print STDERR "Creating file " . $bind_file . "\n"; +		open NFILE, ">" . $bind_file or die ( $! . " " . $bind_file); + +		print NFILE "zone \"$name.$tgname.gathering.org\" {\n"; +		if ( $role eq "master" ) { +			print NFILE "        type master;\n"; +			print NFILE "        notify yes;\n"; +			print NFILE "        allow-update { key DHCP_UPDATER; };\n"; +			print NFILE "        file \"dynamic/$name.$tgname.gathering.org.zone\";\n"; +		} +		else +		{ +			print NFILE "        type slave;\n"; +			print NFILE "        notify no;\n"; +			print NFILE "        masters { bootstrap; };\n"; +			print NFILE "        file \"slave/$name.$tgname.gathering.org.zone\";\n"; +		} +		print NFILE "        allow-transfer { ns-xfr; };\n"; +		print NFILE "};\n"; + +		close NFILE; +	} +} diff --git a/tools/make-named.pl b/tools/make-named.pl new file mode 100755 index 0000000..7e543e1 --- /dev/null +++ b/tools/make-named.pl @@ -0,0 +1,156 @@ +#!/usr/bin/perl -I /root/tgmanage +use strict; + +BEGIN { +        require "include/config.pm"; +        eval { +                require "include/config.local.pm"; +        }; +} + + +use Net::IP; +use Net::IP qw(:PROC); + +unless ( (($#ARGV == 0 ) || ( $#ARGV == 1)) +	&& (( $ARGV[0] eq "master" ) || ( $ARGV[0] eq "slave" )) ) +{ +	print STDERR "Invalid usage!\ncat netnames.txt | $0 <master|slave> [basedir]\n"; +	exit 1; +} + +my $role = $ARGV[0]; + +my $base = "/etc"; +$base = $ARGV[1] if $#ARGV == 1; +$base .= "/" if not $base =~ m/\/$/ and not $base eq ""; + +my $bind_base =  $base . "bind/"; +my $named_file = $bind_base . "named.conf"; + +if ( -f $named_file ) +{ +	print STDERR $named_file . " already exists. Cowardly refusing to continue\n"; +	exit; +} + +my $tgname    = $nms::config::tgname; + +my $pri_a     = $nms::config::pri_a; +my $pri_ptr   = $nms::config::pri_ptr; +my $pri_v6    = $nms::config::pri_v6; + +my $sec_a     = $nms::config::sec_a; +my $sec_ptr   = $nms::config::sec_ptr; +my $sec_v6    = $nms::config::sec_v6; +my $ipv6zone  = $nms::config::ipv6zone; +my $ext_xfer  = $nms::config::ext_xfer; +my $ext_ns    = $nms::config::ext_ns; + +my $ddns_key  = $nms::config::ddns_key; + +my $base_ipv4net    = $nms::config::base_ipv4net; +my $base_ipv4prefix = $nms::config::base_ipv4prefix; + +my $base_ipv6net    = $nms::config::base_ipv6net; +my $base_ipv6prefix = $nms::config::base_ipv6prefix; + +my $noc_nett = $nms::config::noc_nett; + +my $ddns_to = $nms::config::ddns_to; + +my $pxe_server = $nms::config::ddns_to; + +my $run = `date +%Y%m%d-%H%M`; + +open NFILE, ">" . $named_file or die ( $! . " " . $named_file ); + +chomp $run; +print NFILE <<EOF; +// This named.conf was generated by make-named.pl at $run +// The current version of make-named.pl should not overwrite this file. +acl tg-nett  { $base_ipv4net/$base_ipv4prefix; $base_ipv6net:/$base_ipv6prefix; 127.0.0.0/8; ::1; }; +acl ns-xfr   { $ext_ns; $sec_ptr; $sec_v6; $pri_ptr; $pri_v6; $noc_nett; }; +acl ripe-xfr { $ext_ns; $sec_ptr; $sec_v6; $pri_ptr; $pri_v6; $ext_xfer; }; + +options { +        directory "/etc/bind"; +        allow-recursion { tg-nett; }; +        allow-query { any; }; +        allow-transfer { ns-xfr; }; +        recursion yes; +        auth-nxdomain no; +        listen-on-v6 { any; }; +}; + +key DHCP_UPDATER { +        algorithm HMAC-MD5.SIG-ALG.REG.INT; +        secret $ddns_key; +}; +EOF + +if ( $role eq "master" ) +{ +	print NFILE <<EOF; + +zone "$tgname.gathering.org" { +        type master; +        file "$tgname.gathering.org.zone"; +        notify yes; +        allow-transfer { ns-xfr; }; +}; + +zone "infra.$tgname.gathering.org" { +        type master; +        file "infra.$tgname.gathering.org.zone"; +        notify yes; +        allow-transfer { ns-xfr; }; +}; + +zone "$ipv6zone" { +        type master; +        allow-update { key DHCP_UPDATER; }; +        notify yes; +        file "$ipv6zone.zone"; +        allow-transfer { ns-xfr; ripe-xfr; }; +}; + +include "/etc/bind/named.conf.default-zones"; +include "named.reverse4.conf"; +include "named.master-include.conf"; +EOF +} + +if ( $role eq "slave" ) +{ +	print NFILE <<EOF; + +masters bootstrap  { $pri_ptr; }; + +zone "$tgname.gathering.org" { +        type slave; +        file "slave/$tgname.gathering.org"; +        notify no; +	masters { bootstrap; }; +}; + +zone "infra.$tgname.gathering.org" { +        type slave; +        file "slave/infra.$tgname.gathering.org"; +        notify no; +	masters { bootstrap; }; +}; + +zone "$ipv6zone" { +        type slave; +        notify no; +	masters { bootstrap; }; +        file "slave/$ipv6zone:"; +        allow-transfer { ns-xfr; ripe-xfr; }; +}; + +include "named.conf.default-zones"; +include "named.slave-reverse4.conf"; +include "named.slave-include.conf"; +EOF +} diff --git a/tools/make-pxeboot.sh b/tools/make-pxeboot.sh new file mode 100755 index 0000000..0d53e6a --- /dev/null +++ b/tools/make-pxeboot.sh @@ -0,0 +1,26 @@ +#!/bin/bash +# +# TODO: This tool assumes that the bootstrap box +# is used as the PXE server. This should be updated +# to use the configuration information in config.local.pm ... + +apt-get install tftpd-hpa +apt-get install nfs-kernel-server + +cat << END > /etc/default/tftpd-hpa +TFTP_USERNAME="tftp" +TFTP_DIRECTORY="/var/lib/tftpboot" +TFTP_ADDRESS="0.0.0.0:69" +TFTP_OPTIONS="--secure" +END + +/etc/init.d/tftpd-hpa restart + +mkdir -p /var/lib/tftpboot +cp -R pxe/* /var/lib/tftpboot + +tools/fetch-debinstall.sh /var/lib/tftpboot/debian +# tools/fetch-ubuntulive.sh <- this tool does not exist xD +# NOTE! The pxe/ directory contains an 'ubuntu' menu... +# The files required to booting Ubuntu installer or live +# must be fetched manually (for now) diff --git a/tools/make-reverse4-files.pl b/tools/make-reverse4-files.pl new file mode 100755 index 0000000..d20ea37 --- /dev/null +++ b/tools/make-reverse4-files.pl @@ -0,0 +1,164 @@ +#!/usr/bin/perl -I /root/tgmanage +use strict; + +BEGIN { +        require "include/config.pm"; +        eval { +                require "include/config.local.pm"; +        }; +} + + +use Net::IP; +use Net::IP qw(:PROC); + +# FIXME: THIS IS NOT APPRORPIATE! +my $serial = `date +%Y%m%d01`; +chomp $serial; +# FIXME + +unless ( (($#ARGV == 0 ) || ( $#ARGV == 1)) +	&& (( $ARGV[0] eq "master" ) || ( $ARGV[0] eq "slave" )) ) +{ +	print STDERR "Invalid usage!\n$0 <master|slave> [basedir]\n"; +	exit 1; +} + +my $role = $ARGV[0]; + +my $base = "/etc"; +$base = $ARGV[1] if $#ARGV == 1; +$base .= "/" if not $base =~ m/\/$/ and not $base eq ""; + + +my $bind_base =  $base . "bind/"; +my $dhcpd_base = $base . "dhcp/"; + +my $dhcp_revzones_file =  $dhcpd_base . "revzones.conf"; +my $bind_pri_revzones_file = $bind_base . "named.reverse4.conf"; +my $bind_sec_revzones_file = $bind_base . "named.slave-reverse4.conf"; + +my $tgname    = $nms::config::tgname; + +my $pri_a     = $nms::config::pri_a; +my $pri_ptr   = $nms::config::pri_ptr; +my $pri_v6    = $nms::config::pri_v6; + +my $sec_a     = $nms::config::sec_a; +my $sec_ptr   = $nms::config::sec_ptr; +my $sec_v6    = $nms::config::sec_v6; + +my $ext_xfer  = $nms::config::ext_xfer; +my $ext_ns    = $nms::config::ext_ns; + +my $ddns_key  = $nms::config::ddns_key; + +my $base_ipv4net    = $nms::config::base_ipv4net; +my $base_ipv4prefix = $nms::config::base_ipv4prefix; + +my $noc_nett = $nms::config::noc_nett; +my $noc_nett_v6 = $nms::config::noc_nett_v6; + +my $ddns_to = $nms::config::ddns_to; + +my $pxe_server = $nms::config::ddns_to; + +my $base_ipv4 = new Net::IP( $base_ipv4net . "/" . $base_ipv4prefix ); + +$base_ipv4net =~ m/^(\d+)\.(\d+)\.(\d+)\..*/; +my ( $p_oct, $s_oct, $t_oct ) = ( $1, $2, $3 ); + +$pri_ptr =~ m/^(\d+)\.(\d+)\.(\d+)\.(\d+).*/; +my ( $pp_oct, $ps_oct, $pt_oct, $pf_oct) = ( $1, $2, $3, $4 ); +$sec_ptr =~ m/^(\d+)\.(\d+)\.(\d+)\.(\d+).*/; +my ( $sp_oct, $ss_oct, $st_oct, $sf_oct) = ( $1, $2, $3, $4 ); + +if ( $role eq "master" ) +{ +	open DFILE, ">" . $dhcp_revzones_file or die $!; +	open NFILE, ">" . $bind_pri_revzones_file or die $!; +} +elsif ( $role eq "slave" ) +{ +	open SFILE, ">" . $bind_sec_revzones_file or die $!; +} +else +{ +	die ("WTF, role is neither 'master' or 'slave'"); +} + +while (1) +{ + +	my $block =  $p_oct . "." . $s_oct . "." . $t_oct . ".0/24"; +	my $current = new Net::IP( $block ) or die ("new Net::IP failed for " . $block); + +	my $rev_zone = $t_oct . "." .  $s_oct . "." . $p_oct . ".in-addr.arpa"; + +	if ( $role eq "master" ) +	{ +		# Generating IPv4-related reverse-stuff for +		# both bind9 and dhcp on master. + +		print DFILE "zone " . $rev_zone . " { primary " . $ddns_to . "; key DHCP_UPDATER; }\n"; + +		print NFILE "zone \"". $rev_zone ."\"	{\n"; +		print NFILE "    type master;\n"; +		print NFILE "    allow-update { key DHCP_UPDATER; };\n"; +		print NFILE "    notify yes;\n"; +		print NFILE "    allow-transfer { $sec_ptr; $ext_xfer; $noc_nett; $noc_nett_v6; };\n"; +		print NFILE "    file \"reverse/". $rev_zone .".zone\";\n"; +		print NFILE "};\n\n"; + +		my $zfilename = $bind_base . "reverse/" . $rev_zone . ".zone"; +		open ZFILE, ">", $zfilename; + +		print ZFILE "; " . $zfilename . "\n"; +		print ZFILE <<"EOF"; +; Base reverse zones are updated from dhcpd -- DO NOT TOUCH! +\$TTL 3600 +@	IN	SOA	ns1.$tgname.gathering.org.	abuse.gathering.org. ( +                        $serial   ; serial +                        3600 ; refresh +                        1800 ; retry +                        608400 ; expire +                        3600 ) ; minimum and default TTL + +		IN	NS	ns1.$tgname.gathering.org. +		IN	NS	ns2.$tgname.gathering.org. + +\$ORIGIN $rev_zone. +EOF +		if ( ($pt_oct == $t_oct) && ($ps_oct == $s_oct) ) +		{ +			print ZFILE $pf_oct . "		IN	PTR	ns1.$tgname.gathering.org.\n"; +		} +		if ( ($st_oct == $t_oct) && ($ss_oct == $s_oct) ) +		{ +			print ZFILE $sf_oct . "		IN	PTR	ns2.$tgname.gathering.org.\n"; +		} +	} +	else +	{ +		# AKA "if not master", as in "is slave". +		# A lot less work: update the named.slave-reverse4.conf file.. +		print SFILE "zone \"". $rev_zone ."\"	{\n"; +		print SFILE "    type slave;\n"; +		print SFILE "    notify no;\n"; +		print SFILE "    file \"slave/". $rev_zone .".cache\";\n"; +		print SFILE "    masters { bootstrap; };\n"; +		print SFILE "    allow-transfer { $ext_xfer; $noc_nett; $noc_nett_v6; };\n"; +		print SFILE "};\n\n"; +	} + +	if ( $current->last_int() == $base_ipv4->last_int() ) +	{ +		print STDERR "Reached last IP network. Finished\n"; +		last; +	} +	$t_oct++; +} +# Close all files, even those that have never been opened ;) +close DFILE; +close NFILE; +close SFILE; diff --git a/tools/make-switch-placements.pl b/tools/make-switch-placements.pl new file mode 100755 index 0000000..58538e2 --- /dev/null +++ b/tools/make-switch-placements.pl @@ -0,0 +1,88 @@ +#! /usr/bin/perl +use strict; +use warnings; + +my $switchtype = "dlink3100"; + +print "begin;\n"; +print "delete from placements where switch in (select switch from switches where switchtype = '$switchtype');\n"; + +my %ip; +my $i = 1; +while (<STDIN>) { +	chomp; +	my @info = split(/ /); + +	if (scalar @info < 5) { +		die "Unknown line: $_"; +	} +	my ($x, $y, $xx, $yy); + +	my $name = $info[0]; +	if ($name =~ /^e\d+-\d+$/) { +		$name =~ /e(\d+)-(\d+)/; +		my ($e, $s) = ($1, $2); + +		$x = int(220 + (($e-1)/2) * 21.5); +		$y = undef; + +		$x += 10 if ($e >= 11); +		$x += 10 if ($e >= 27); +		$x += 10 if ($e >= 43); +		$x += 10 if ($e >= 59); + +		if ($s > 2) { +			$y = 310 - 84 * ($s-2); +		} else { +			$y = 507 - 84 * ($s); +		} + +		$xx = $x + 14; +		$yy = $y + 84; + +		# Justeringer +		$y += 42 if $name eq "e1-4"; +		$y += 28 if $name eq "e3-4"; +		$y += 14 if $name eq "e5-4"; + +		$yy -= 14 if $name eq "e77-1"; +		$yy -= 28 if $name eq "e79-1"; +		$yy -= 42 if $name eq "e81-1"; +		$yy -= 56 if $name eq "e83-1"; +	} elsif ($name =~ /^creative(\d+)$/) { +		my $s = $1; +		if ($s < 3) { +			if ($s == 1) { +				$x = 1190; +				$y = 278; +			} else { +				$x = 1180; +				$y = 230; +			} +			$xx = $x+35; +			$yy = $y+19; +			$yy += 6; +		} else { +			$x = 1056; +			$y = 296 - 22 * ($s-3); +			if ($s <= 4) { +				$xx = $x+100; +			} elsif ($s <= 7) { +				$xx = $x+70; +			} elsif ($s <= 8) { +				$xx = $x+55; +			} else { +				$xx = $x+35; +			} +			$yy = $y+19; +			$yy -= 5 if $s == 3; +		} +	} else { +		die "Unknown switch: $name"; +	} + +	print "insert into placements select switch, box '(($x,$y),($xx,$yy))' from switches where sysname = '$name';\n"; +	$i++; +} + +print "end;\n"; diff --git a/tools/make-switches.pl b/tools/make-switches.pl new file mode 100755 index 0000000..a2f5d22 --- /dev/null +++ b/tools/make-switches.pl @@ -0,0 +1,33 @@ +#! /usr/bin/perl +use strict; +use warnings; + +my $switchtype = "dlink3100"; + +print "begin;\n"; +print "delete from temppoll;\n"; +print "delete from dhcp;\n"; +print "delete from switches where switchtype = '$switchtype';\n"; +#print "SELECT pg_catalog.setval('switches_switch_seq', 1, false);\n"; +print "SELECT pg_catalog.setval('polls_poll_seq', 1, false);\n"; + +my %ip; +my $i = 1; +while (<STDIN>) { +	chomp; +	my @info = split(/ /); + +	if (scalar @info < 5) { +		die "Unknown line: $_"; +	} + +	my $name = $info[0]; +	my $range = $info[3]; +	my $ip = $info[4]; + +	print "insert into switches (ip, sysname, switchtype) values ('$ip', '$name', '$switchtype');\n"; +	print "insert into dhcp select switch, '$range' from switches where sysname = '$name';\n"; +} +close HOSTS; + +print "end;\n"; diff --git a/tools/update-baseservice.sh b/tools/update-baseservice.sh new file mode 100755 index 0000000..5908941 --- /dev/null +++ b/tools/update-baseservice.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +set -e + +BASE=""; +if [ -n $1 ] +then +	BASE=$1 +	echo "Using base path ${BASE}" +fi + +source include/tgmanage.cfg.sh +if [ -z ${PRIMARY} ] +then +	echo "Not configured!"; +	exit 1; +fi; + +cat netlist.txt | ssh -l root ${PRIMARY} "~/tgmanage/tools/make-missing-conf.pl master ${BASE}" +ssh -l root ${PRIMARY} "~/tgmanage/tools/make-dhcpd-include.pl ${BASE}" +ssh -l root ${PRIMARY} "~/tgmanage/tools/make-bind-include.pl master ${BASE}" + +set +e +ssh -l root ${PRIMARY} "chown bind.bind /etc/bind/dynamic/*.zone"; +set -e + +cat netlist.txt | ssh -l root ${SECONDARY} "~/tgmanage/tools/make-missing-conf.pl slave ${BASE}" +ssh -l root ${SECONDARY} "~/tgmanage/tools/make-bind-include.pl slave ${BASE}" + diff --git a/tools/update-tools.sh b/tools/update-tools.sh new file mode 100755 index 0000000..99f712a --- /dev/null +++ b/tools/update-tools.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +set -e + +source include/tgmanage.cfg.sh +if [ -z ${PRIMARY} ] +then +	echo "Not configured!"; +	exit 1; +fi; + +ssh -l root ${PRIMARY} "mkdir -p ~/tgmanage" +ssh -l root ${SECONDARY} "mkdir -p ~/tgmanage" + +scp -r netlist.txt root@${PRIMARY}:tgmanage/ +scp -r tools root@${PRIMARY}:tgmanage/ +scp -r tools root@${SECONDARY}:tgmanage/ +scp -r include root@${PRIMARY}:tgmanage/ +scp -r include root@${SECONDARY}:tgmanage/ +scp -r clients root@${PRIMARY}:tgmanage/ +scp -r clients root@${SECONDARY}:tgmanage/  | 
