newnode.in 5.61 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12
#!/usr/bin/perl -w

#
# EMULAB-COPYRIGHT
# Copyright (c) 2003 University of Utah and the Flux Group.
# All rights reserved.
#

#
# newnode - a script for moving nodes from the new_ tables into production.
#

13
use lib '@prefix@/lib';
14 15 16 17 18

use libdb;

use strict;

19
my $TB = "@prefix@";
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60

my $switchmac = "$TB/sbin/switchmac";
my $sched_reload = "$TB/sbin/sched_reload";
my $nalloc = "$TB/bin/nalloc";
my $nfree = "$TB/bin/nfree";
my $dhcpd_makeconf = "$TB/sbin/dhcpd_makeconf";

my $dhcpd_conf = "/usr/local/etc/dhpcd.conf";
my $dhcpd_template = "/usr/local/etc/dhcpd.conf.template";
my $dhcpd_rc = "/usr/local/etc/rc.d/2.dhcpd.sh";

if (!TBAdmin()) {
    die "Sorry, only testbed administrators can run this script!\n";
}

if (@ARGV < 1) {
    die "Usage: $0 <node_id> ...\n";
}

my @node_ids = @ARGV;

#
# Now, loop through the nodes given, and add each one
#
my @succeeded_nodes;
NODE: foreach my $node_id (@node_ids) {
    my $query_result;

    #
    # Check to make sure said node does not already exist!
    #
    $query_result = DBQueryFatal("SELECT node_id FROM nodes WHERE " .
	"node_id='$node_id'");
    if ($query_result->num_rows()) {
	warn "Node $node_id failed: a node with that name already exists!\n";
	next NODE;
    }

    #
    # Grab information about the node from the new_nodes table
    #
61 62
    $query_result = DBQueryFatal("SELECT new_node_id, type, IP " .
	"FROM new_nodes WHERE node_id='$node_id'");
63 64 65 66
    if (!$query_result->num_rows()) {
	warn "Node $node_id failed: No pending node with that name exists!\n";
	next NODE;
    }
67
    my ($new_node_id, $type, $IP) = $query_result->fetchrow();
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83

    #
    # Make sure that the new node is of a valid type, and grab a few other
    # things to fill in as initial values
    #
    $query_result = DBQueryFatal("SELECT control_net FROM node_types " .
	"WHERE type='$type'");
    if (!$query_result->num_rows()) {
	warn "Node $node_id failed: Type $type does not exist!\n";
	next NODE;
    }
    my ($control_net) = $query_result->fetchrow();

    #
    # Grab the node's MACs from the new_interfaces table
    #
84 85
    $query_result = DBQueryFatal("SELECT iface, MAC, interface_type, " .
	"switch_id, switch_card, switch_port " .
86
	"FROM new_interfaces WHERE new_node_id='$new_node_id'");
87 88 89 90 91 92
    if (!$query_result->num_rows()) {
	warn "Node $node_id failed: Must have at least one interface!\n";
	next NODE;
    }

    my %interfaces;
93 94
    while (my ($iface, $MAC, $iface_type, $switch_id, $switch_card,
	    $switch_port) = $query_result->fetchrow()) {
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
	#
	# Get some more information about this interface type
	#
	my $iface_query = DBQueryFatal("SELECT max_speed, full_duplex " .
	    "FROM interface_types WHERE type='$iface_type'");
	if (!$iface_query->num_rows()) {
	    warn "Node $node_id failed: Interface $iface is of unknown type " .
	    	"$iface_type";
	    next NODE;
	}

	my ($max_speed, $full_duplex) = $iface_query->fetchrow();

	#
	# Stash it away...
	#
111 112
	$interfaces{$iface} = [$MAC, $iface_type, $max_speed, $full_duplex,
		$switch_id, $switch_card, $switch_port];
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134

    }

    #
    # Make up a priority (just used for sorting)
    #
    $node_id =~ /(\d+)$/;
    my $priority;
    if ($1) {
	$priority = $1;
    } else {
	$priority = 1;
    }

    #
    # Okay, time to actually add the node!
    #
    
    DBQueryFatal("INSERT INTO nodes SET node_id='$node_id', type='$type', " .
	"phys_nodeid='$node_id', role='testnode', priority=$priority");

    while (my ($iface, $aref) = each %interfaces) {
135 136
	my ($MAC, $iface_type, $speed, $duplex, $switch_id, $switch_card,
	    $switch_port) = @$aref;
137 138 139 140 141 142 143 144 145 146 147 148 149
	$iface =~ /(\d+)$/;
	my $card = $1;
	my $iface_IP = "";
	my $wire_type = "Node";
	if ($card == $control_net) {
	    $iface_IP = $IP;
	    $wire_type = "Control";
	}
	DBQueryFatal("INSERT INTO interfaces SET node_id='$node_id', " .
	    "card=$card, port=1, mac='$MAC', IP='$iface_IP', " .
	    "interface_type='$iface_type', iface='$iface', " .
	    "current_speed='$speed', duplex=$duplex");

150 151 152 153
	DBQueryFatal("INSERT INTO wires SET type='$wire_type', " .
	    "node_id1='$node_id', card1=$card, port1=1, " .
	    "node_id2='$switch_id', card2='$switch_card', " .
	    "port2='$switch_port'");
154 155 156 157 158 159 160
    }

    #
    # TODO - Do we need to get the nodes into a good state for the event system?
    #

    #
161
    # Schedule a reload for it
162 163 164 165 166 167 168
    #
    system "$nalloc emulab-ops hwdown $node_id";
    system "$sched_reload $node_id";

    #
    # Remove the node from the new_ tables
    #
169
    DBQueryFatal("DELETE FROM new_nodes WHERE new_node_id=$new_node_id");
170
    DBQueryFatal("DELETE FROM new_interfaces WHERE new_node_id=$new_node_id");
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212

    print "$node_id succesfully added!";

    push @succeeded_nodes, $node_id;
}

#
# No point in restarting dhcpd, etc. if there are no nodes that succeeded
#
if (!@succeeded_nodes) {
    die "No nodes succeeded, exiting early\n";
}

#
# Re-generate dhcpd.conf
#
if (! -f $dhcpd_template) {
    warn "Warning: $dhcpd_template does not exist\n";
    warn "You'll need to re-run dhcpd_makeconf manually, then free the new\n";
    warn "nodes from emulab-ops/hwdown\n";
} else {
    print "Re-generating dhcpd.conf\n";
    open(CONF,"$dhcpd_makeconf $dhcpd_template|") or die "Unable to fork: $!\n";
    my @conf = <CONF>;
    close CONF or die "Error reading from dhcpd_makeconf: $!\n";

    open(CONF,">$dhcpd_conf") or die "Unable to open $dhcpd_conf for writing\n";
    print CONF @conf;
    close CONF;

    print "Restarting dhcpd\n";
    system "$dhcpd_rc stop";
    system "$dhcpd_rc start";

    #
    # Now, free all the nodes we just made from hwdown, so that they can reload
    #
    system "$nfree emulab-ops hwdown " . join(" ",@succeeded_nodes);

}

#
213 214 215 216
# TODO -
#    add nodes to named?
#    disable interfaces
#    console setup
217
#