[Maintain-dev] [JIRA] Commented: (MNT-1361) VLAN to dhcp's shared-network

James O'Dell (JIRA) jira at osuosl.org
Mon Aug 8 15:41:08 PDT 2005


     [ http://bugs.osuosl.org/browse/MNT-1361?page=comments#action_10611 ]
     
James O'Dell commented on MNT-1361:
-----------------------------------



# build-dhcp

#!/usr/bin/perl
#
# Copyright (c) 2001 Oregon State University - Network Engineering
# All rights reserved.
 
# $Id: build-dhcp 3544 2005-01-04 19:03:27Z philips $
# $HeadURL: https://svn.osuosl.org/public/maintain2/tags/release-2.4.2-RC2/bin/build-dhcp $ 

# This will connect to the database and build the complete
#  dhcpd.conf.data file that is included by both the primary
#  and secondary dhcp servers.

use Data::Dumper;

# create the Maintain object
use FindBin qw($Bin);
use lib "$Bin";
use SetupMaintain;
my $maintain = get_maintain(); 

$maintain->{_debug} = 0;

# Let's go ahead and set the zones we need to build into the
# autoreg dhcpd files next version this needs to come out of
# the config file (read_config) 
my @public_zones = ('zone.public');
my @resnet_zones = ('zone.resnet');

# we need this a few times below
my @resnet_workgroups = ('zone.resnet-RCN 240', 'zone.resnet-RCN 244', 'zone.resnet-RCN 248', 'zone.resnet-RCN 252', 'zone.resnet-sn083.0.def',
				'zone.resnet-sn083.0.hpsw.def', 'zone.resnet-sn083.128.def', 'zone.resnet-sn083.128.hpsw.def',
				'zone.resnet-sn083.192.def', 'zone.resnet-sn083.192.hpsw.def', 'zone.resnet-sn083.32.def',
				'zone.resnet-sn083.32.hpsw.def', 'zone.resnet-sn083.64.def', 'zone.resnet-sn083.64.hpsw.def',
				'zone.resnet-static-RCN 244','zone.resnet-static-RCN 248','zone.resnet-static-RCN 252',
				'zone.resnet-static-sn083.192.def','zone.resnet-static-sn083.0.def','zone.resnet-static-sn083.0.hpsw.def',
				'zone.resnet-static-sn083.128.def','zone.resnet-static-sn083.128.hpsw.def','zone.resnet-static-sn083.192.hpsw.def',
				'zone.resnet-static-sn083.32.def','zone.resnet-static-sn083.32.hpsw.def','zone.resnet-static-sn083.64.def',
				'zone.resnet-static-sn083.64.hpsw.def','zone.resnet-static-RCN 240','resnet');

# Define the start and End range for RCN's _normal_ addresses this is a kludge
my %resnet_range = ();
$resnet_range{start} = 2160193536;
$resnet_range{end} = 2160197630;
$resnet_range{sand_start} = 180482048;
$resnet_range{sand_end} = 180486142;

my $resnet_sand_workgroup = 'Sandbox';

$maintain->populate_domains();

# This is the data file we're tryin' to build
open(DATA, "> $maintain->{_path}/build/dhcpd.conf.data");

# let's build the classes for the ranges that are dynamic (even if they don't
#   have hosts associated with them.
my $sql = qq{SELECT ranges.id,zone_range.zone 
		FROM ranges,zone_range 
		WHERE ranges.type='dynamic' 
		AND ranges.id = zone_range.range AND ranges.enabled='1'};
my $dynamic_host_sth = $maintain->{_dbh}->prepare($sql);
$dynamic_host_sth->execute();

$sql = qq{SELECT id FROM host WHERE ip >= ? AND ip <= ?};
my $host_range_sth = $maintain->{_dbh}->prepare($sql);

$sql = qq{SELECT ha FROM host where dynamic_range=? AND zone=?};
my $dynamic_ha_sth = $maintain->{_dbh}->prepare($sql);

# setup $maintain->{_dhcp_options}
#
$maintain->populate_dhcp_options();

# We're going to need these resnet hosts a lot and no sense in
#   doing a million extra selects that we don't need.  Let's just
#   get these hosts and use them as needed.
my @resnet_hosts = ();

foreach my $workgroup_name (@resnet_workgroups) {
	$sql = qq{SELECT id FROM workgroup WHERE name=?};
	$sth = $maintain->{_dbh}->prepare($sql);
	$sth->execute($workgroup_name);
	my ($id) = $sth->fetchrow();

	my $workgroup = $maintain->get_workgroup_by_id($id);

	my $hosts = $maintain->get_workgroup_hosts($workgroup);
	foreach my $host (@{$hosts}) {
		push(@resnet_hosts, $host);
	}
}

# We are going to have more hosts than host options almost all of the
# time, rather than doing a single select on _every_ host (currently 50K plus
# for us, let's do one select and put the options into a hash for later 
# reference. 
my %host_options;

$sql = qq{SELECT * FROM object_option WHERE type='host'};
$sth = $maintain->{_dbh}->prepare($sql);
$sth->execute();

while (@obj = $sth->fetchrow_array) {

	$host_options{$obj[1]}->{$obj[4]} = $obj[5];

} # End while fetching

# Next we're going to need the sandboxed resnet hosts, rather than grab
# them 4 times let's get them all at once.
my @resnet_sand_hosts = ();

$sql = qq{SELECT id FROM workgroup WHERE name=?};
$sth = $maintain->{_dbh}->prepare($sql);
$sth->execute($resnet_sand_workgroup);
my ($id) = $sth->fetchrow();

my $workgroup = $maintain->get_workgroup_by_id($id);
my $hosts = $maintain->get_workgroup_hosts($workgroup);
foreach my $host (@{$hosts}) {
	push(@resnet_sand_hosts, $host);
}



# Build the dynamic host class hierarchy (class & subclass via DHCP)
while ( my ($range_id, $zone_id) = $dynamic_host_sth->fetchrow() ) {
	my $zone  = $maintain->get_zone($zone_id);	
	my $range = $maintain->get_range($range_id);

	print DATA "# $zone->{name} for $range->{start} to $range->{end}\n";
	print DATA "class \"$zone->{name}:$range->{start}:$range->{end}\" {\n";
	print DATA "\tmatch hardware; \n";
	print DATA "}\n";

	# kludge alert ... basically we want to include any data from zone.rcn-staging
	#  in any declaration for zone.public.  This is how we do that.
	if ( ($zone->{name} eq 'zone.resnet') ) {


		# Next make sure that we are within their normal IP space
		# We don't want to populate into 10.??? space that is bad
		#


		print DATA "# Resnet hosts for $zone->{name}\n";

		if ($range->{start_int} >= $resnet_range{start} && $range->{end_int} <= $resnet_range{end} ) {

			my $hosts = $maintain->get_workgroup_hosts($workgroup);
			foreach my $host (@resnet_hosts) {
				print DATA "subclass \"$zone->{name}:$range->{start}:$range->{end}\" 1:$host->{ha};\n";
			}
	
			next;


		} # End if inside resnet range

		# Next we want to check and see if we are inside the 10.??? space for resnet
		# If we are let's dump those hosts!
		if ($range->{start_int} >= $resnet_range{sand_start} && $range->{end_int} <= $resnet_range{sand_end} ) {

			foreach my $host (@resnet_sand_hosts) {
				print DATA "subclass \"$zone->{name}:$range->{start}:$range->{end}\" 1:$host->{ha};\n";
			}

			next;


		} # End if inside 10 range

	} # End if resnet zone

	print DATA "# Hosts for $zone->{name}\n";

        $dynamic_ha_sth->execute($range->{id}, $zone_id);
        
        while ( my ($ha) = $dynamic_ha_sth->fetchrow() ) {
                # if they don't have a ha something is wrong here
                if ( $ha ) {
                	$ha = $maintain->convert_ha($ha);
                	print DATA "subclass \"$zone->{name}:$range->{start}:$range->{end}\" 1:$ha;\n";
                }
        }
	
	print DATA "# end $zone->{name}\n";
}

$sql = qq{SELECT DISTINCT ha FROM host WHERE `enabled` =1 AND `ha` != '' AND `ha` != '000000000000' GROUP BY ha};
my $global_ha_sth = $maintain->{_dbh}->prepare($sql);

#Modified
$sql = qq{SELECT id FROM subnet WHERE status='visible' ORDER BY vlan};
my $sth = $maintain->{_dbh}->prepare($sql);
$sth->execute();

# Build the subnet declarations with their associated options
#
while ( my ($id) = $sth->fetchrow_array() ) {

	$subnet = $maintain->get_subnet_by_id($id);

	# returns a ref to an array of hashrefs
	$ranges = $maintain->get_dynamic_ranges($subnet);

	$options = $maintain->get_workgroup_options($id,'subnet',$dbh);
#New
        $count = $maintain->get_vlan_count_by_vlan($subnet->{vlan});

#print "id:$subnet->{id} name:$subnet->{name} subnet:$subnet->{subnet} netmask:$subnet->{netmask} vlan:$subnet->{vlan}\n";

	if ( $count > 1 ) {
        # if count > 1 then the network has more than one IP subnet on the network segment - overlay network
        	print DATA "shared-network VLAN_$subnet->{vlan} \{\n";

		$maintain->print_dhcp_subnet($subnet->{subnet}, $subnet->{netmask}, $ranges, $options, \*DATA);
	
        	for ( $I=1; $I<$count; $I++ ) {
        	# We can use this approach because the array is a sorted list.. e.g. ORDER BY in the sql query 
               		$id = $sth->fetchrow_array();
	       		$subnet = $maintain->get_subnet_by_id($id);

	       		$ranges = $maintain->get_dynamic_ranges($subnet);

	       		$options = $maintain->get_workgroup_options($id,'subnet',$dbh);

	       		$maintain->print_dhcp_subnet($subnet->{subnet}, $subnet->{netmask}, $ranges, $options, \*DATA);
		}
        	print DATA "\}\n";
	} else {
		$maintain->print_dhcp_subnet($subnet->{subnet}, $subnet->{netmask}, $ranges, $options, \*DATA);
	}
}

$sth->finish();

$sql = qq{SELECT * FROM workgroup};
$sth = $maintain->{_dbh}->prepare($sql);
$sth->execute();

# Build the workgroup declarations with their associated options
#
while ( my $workgroup = $sth->fetchrow_hashref() ) {
	$options = $maintain->get_workgroup_options($workgroup->{id}, 'workgroup', $dbh);

	$maintain->print_dhcp_workgroup($workgroup, 'default', $options, \*DATA, \%host_options);
}

$sth->finish();
close(DATA);

if ( $maintain->{'_config'}->{'build_autoreg'} eq 'true' ) {

	# The following builds a file called dhcpd.conf.autoreg that is deployed to
	#   the autoregistration server.  This server will hand out leases to clients
	#   it doesn't know about; we generate this file and push it to the autoreg
	#   server so it doesn't know about the newly registered clients (and so ignores
	#   any dhcprequests from them.
	#	
	foreach my $zone (@public_zones) {

		
		$sql = qq{SELECT ranges.subnet FROM zone,zone_range,ranges WHERE zone.name='$zone' AND zone_range.zone=zone.id AND zone_range.range=ranges.id AND ranges.type='dynamic'};
		$sth = $maintain->{_dbh}->prepare($sql);
		$sth->execute();
		
		my $subnet = $sth->fetchrow_hashref();

		$sql = qq{SELECT DISTINCT(host.name),domain.name AS dn,host.ha FROM ranges,host,domain WHERE ranges.subnet='$subnet->{subnet}' AND host.dynamic_range=ranges.id AND host.domain=domain.id};
		$sth = $maintain->{_dbh}->prepare($sql);
		$sth->execute();

		open(AUTO, "> $maintain->{_path}/build/dhcpd.conf.autoreg");
		print AUTO "group { # autoreg group\n";

		while (my $host = $sth->fetchrow_hashref()) { 

			my $hwa = $host->{ha};
			$hwa =~ /(\w{2,2})(\w{2,2})(\w{2,2})(\w{2,2})(\w{2,2})(\w{2,2})/;
			$ha = ($1.":".$2.":".$3.":".$4.":".$5.":".$6);
			
			print AUTO "\thost " . $host->{name} . "." . $host->{dn} . " {\n\t\thardware ethernet ". $ha . ";\n\t}\n";

		} # While we are getting hosts (there will be tons of these) 

		$sql = qq{SELECT host.name,domain.name AS dn,host.ha FROM ranges,host,domain WHERE ranges.subnet='$subnet->{subnet}' AND ( host.ip>=ranges.start AND host.ip<=ranges.end ) AND host.domain=domain.id};
		$sth = $maintain->{_dbh}->prepare($sql);
		$sth->execute();

		while (my $host = $sth->fetchrow_hashref()) { 

                        my $hwa = $host->{ha};
                        $hwa =~ /(\w{2,2})(\w{2,2})(\w{2,2})(\w{2,2})(\w{2,2})(\w{2,2})/;
                        $ha = ($1.":".$2.":".$3.":".$4.":".$5.":".$6);

                        print AUTO "\thost " . $host->{name} . "." . $host->{dn} . " {\n\t\thardware ethernet ". $ha . ";\n\t}\n";	
			
		} # Now we get static hosts.....
		
		print AUTO "\n}\n";
	
		close(AUTO);

	} # End foreach public zones
	
	# ResNet and the public network work closely with each other.  We need to
	#   build a dhcpd.conf.data that has all of the ResNet hosts in it so that
	#   anybody plugging into that network gets a temporary address.  The
	#   public network will have both this dhcpd.conf.data file and the one
	#   for ResNet as we'll automatically include ResNet MAC's in the public
	#   network configuration.

	open(AUTO, "> $maintain->{_path}/build/dhcpd.conf.resnet");

        # The ResNet sandbox workgroup needs to be added into the equation at this
        # time. We need every single computer including those that have been 
        # sandboxed
        push(@resnet_workgroups, $resnet_sand_workgroup);

	foreach my $workgroup_name (@resnet_workgroups) {
		my $workgroup = $maintain->get_workgroup_by_name($workgroup_name);

		$options = $maintain->get_workgroup_options($workgroup->{id}, 'workgroup', $dbh);

		$maintain->print_dhcp_workgroup($workgroup, 'generic', $options, \*AUTO);
	}

	close(AUTO);

}

# all done
1;


> VLAN to dhcp's shared-network
> -----------------------------
>
>          Key: MNT-1361
>          URL: http://bugs.osuosl.org/browse/MNT-1361
>      Project: Maintain
>         Type: Improvement
>   Components: Build Scripts
>     Versions: 2.4.0
>     Reporter: James O'Dell
>     Assignee: Danny Robert

>
>
> Shouldn't Maintain realize that if there are 2 or more subnets are on the same VLAN
> that the DHCP server should be configured with a "shared-network" directive?
> for example
> VLAN1
>    -> 10.10.0.0/16
>    -> 192.168.1.0/24
> #dhcpd.conf.data
> shared-network VLAN1 {
>    subnet 10.10.0.0 netmask 255.255.0.0 {
>       ...
>       match hardware;
>    }
>    subnet 192.168.1.0 {
>       ...
>       allow unknown hosts;
>    }
> }
>   
> I noticed the commented out "shared-network" in dhcpd.conf.footer.
> If this the only alternative?

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
   http://bugs.osuosl.org/secure/Administrators.jspa
-
If you want more information on JIRA, or have a bug to report see:
   http://www.atlassian.com/software/jira



More information about the Maintain-dev mailing list