newnodecheckin.php 8.15 KB
Newer Older
1
<?php
2 3
#
# EMULAB-COPYRIGHT
4
# Copyright (c) 2003, 2005, 2007 University of Utah and the Flux Group.
5 6 7
# All rights reserved.
#
require("defs.php3");
8
require("newnode-defs.php3");
9
include("xmlrpc.php3");
10 11 12 13 14

#
# Note - this script is not meant to be called by humans! It returns no useful
# information whatsoever, and expects the client to fill in all fields
# properly.
15
# Since this script does not cause any action to actually happen, so its save
16 17 18 19
# to leave 'in the open' - the worst someone can do is annoy the testbed admins
# with it!
#

20 21 22 23 24 25 26 27 28 29 30
$reqargs = RequiredPageArguments("cpuspeed",    PAGEARG_STRING,
				 "diskdev",     PAGEARG_STRING,
				 "disksize",    PAGEARG_STRING,
				 "role",        PAGEARG_STRING,
				 "messages",    PAGEARG_STRING);

$optargs = OptionalPageArguments("node_id",     PAGEARG_STRING,
				 "identifier",  PAGEARG_STRING,
				 "use_temp_IP", PAGEARG_STRING,
				 "type",        PAGEARG_STRING);

31 32 33 34 35 36
#
# Grab the IP address that this node has right now, so that we can contact it
# later if we need to, say, reboot it.
#
$tmpIP = getenv("REMOTE_ADDR");

37 38 39
#
# Find all interfaces
#
40
$interfaces = array();
41
foreach ($HTTP_GET_VARS as $key => $value) {
42
    if (preg_match("/iface(name|mac|driver)(\d+)/",$key,$matches)) {
43 44 45 46
        $vartype = $matches[1];
    	$ifacenum = $matches[2];
    	if ($vartype == "name") {
	    if (preg_match("/^([a-z]+)(\d+)$/i",$value,$matches)) {
47 48 49
		if (!isset($interfaces[$ifacenum]["type"])) {
		    $interfaces[$ifacenum]["type"] = $matches[1];
		}
50
	        $interfaces[$ifacenum]["card"] = $ifacenum;
51 52 53 54
	    } else {
		echo "Bad interface name $value!";
		continue;
	    }
55 56
	} else if ($vartype == "driver") {
	    $interfaces[$ifacenum]["type"] = $value;
57 58 59 60 61 62
	} else {
	    $interfaces[$ifacenum]["mac"] = $value;
	}
    }
}

63 64 65 66
#
# Use one of the interfaces to see if this node seems to have already checked
# in once
#
67 68 69 70
if (count($interfaces)) {
    $testmac = $interfaces[0]["mac"];

    #
71 72
    # First, make sure it is not a 'real boy' - we should let the operators 
    # know about this, because there may be some problem.
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
    #
    $query_result = DBQueryFatal("select n.node_id from " .
	"nodes as n left join interfaces as i " .
	"on n.node_id=i.node_id " .
	"where i.mac='$testmac'");
    if  (mysql_num_rows($query_result)) {
        $row = mysql_fetch_array($query_result);
	$node_id = $row["node_id"];
        echo "Node is already a real node, named $node_id\n";
	TBMAIL($TBMAIL_OPS,"Node Checkin Error","A node attempted to check " .
	    "in as a new node, but it is already\n in the database as " .
	    "$node_id!");
	exit;
    }


    #
    # Next, try the new nodes
    #
    $query_result = DBQueryFatal("select n.new_node_id, n.node_id from " .
	"new_nodes as n left join new_interfaces as i " .
	"on n.new_node_id=i.new_node_id " .
	"where i.mac='$testmac'");

    if  (mysql_num_rows($query_result)) {
        $row = mysql_fetch_array($query_result);
	$id = $row["new_node_id"];
	$node_id = $row["node_id"];
101 102
        echo "Node has already checked in\n";
	echo "Node ID is $id\n";
103 104

	#
105
	# Keep the temp. IP address around in case its gotten a new one
106 107 108 109 110 111 112
	#
	DBQueryFatal("update new_nodes set temporary_IP='$tmpIP' " .
	    "where new_node_id=$id");

	exit;
    }
}
113

114 115

#
116 117
# Attempt to come up with a node_id and an IP address for it - unless one was
# provided by the client.
118
#
119
if (!isset($node_id)) {
120 121 122 123 124 125 126 127
    $name_info = find_free_id("pc");
    $node_prefix = $name_info[0];
    $node_num = $name_info[1];
    $hostname = $node_prefix . $node_num;
} else {
    $hostname = $node_id;
}

128
if (isset($use_temp_IP)) {
129 130 131 132
    $IP = $tmpIP;
} else {
    $IP = guess_IP($node_prefix,$node_num);
}
133 134

#
135
# Handle the node type
136
#
Leigh B. Stoller's avatar
Leigh B. Stoller committed
137
if (isset($type) && $type != "") {
138
    #
139
    # If they gave us a type, lets see if that type exists or not
140
    #
141 142 143 144
    if (!preg_match("/^[-\w]*$/", $type)) {
	echo "Illegal characters in type: '$type'\n";
	exit;
    }
145 146 147 148 149 150 151 152 153 154 155 156 157 158
    if (TBValidNodeType($type)) {
	#
	# Great, it already exists, nothin' else to do
	#
    } else {
	#
	# Okay, it doesn't exist. We'll create it.
	#
	make_node_type($type,$cpuspeed,$disksize);
    }
} else {
    #
    # Make an educated guess as to what type it belongs to
    #
159 160 161 162 163 164
    $type = guess_node_type($cpuspeed,$disksize);
}

#
# Default the role to 'testnode' if the node didn't supply a role
#
165
$role = (isset($role) ? addslashes($role) : "testnode");
166 167 168 169

#
# Stash this information in the database
#
Leigh B. Stoller's avatar
Leigh B. Stoller committed
170
if (isset($identifier) && $identifier != "") {
171
    $identifier = "'" . addslashes($identifier) . "'";
172 173 174
} else {
    $identifier = "NULL";
}
175 176 177
$messages = (isset($messages) ? addslashes($messages) : "");
$hostname = (isset($hostname) ? addslashes($hostname) : "");

178
DBQueryFatal("insert into new_nodes set node_id='$hostname', type='$type', " .
179
	"IP='$IP', temporary_IP='$tmpIP', dmesg='$messages', created=now(), " .
180
	"identifier=$identifier, role='$role'");
181 182 183 184 185

$query_result = DBQueryFatal("select last_insert_id()");
$row = mysql_fetch_array($query_result);
$new_node_id = $row[0];

186 187
echo "Node ID is $new_node_id\n";

188
foreach ($interfaces as $interface) {
189
	$card = $interface["card"];
190 191
	$mac = $interface["mac"];
	$type = $interface["type"];
192 193 194
	DBQueryFatal("insert into new_interfaces set " .
	    "new_node_id=$new_node_id, card=$card, mac='$mac', " .
	    "interface_type='$type'");
195 196 197 198 199 200 201
}

#
# Send mail to testbed-ops about the new node
#
TBMAIL($TBMAIL_OPS,"New Node","A new node, $hostname, has checked in");

202
function check_node_exists($node_id) {
203 204
    $node_id = addslashes($node_id);
    
205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222
    #
    # Just check to see if this node already exists in one of the
    # two tables - return 1 if it does, 0 if not
    #
    $query_result = DBQueryFatal("select node_id from nodes " .
	    "where node_id='$node_id'");
    if (mysql_num_rows($query_result)) {
	return 1;
    }
    $query_result = DBQueryFatal("select node_id from new_nodes " .
	    "where node_id='$node_id'");
    if (mysql_num_rows($query_result)) {
	return 1;
    }

    return 0;
}

223
function find_free_id($prefix) {
224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253
    global $ELABINELAB, $TBADMINGROUP, $interfaces;

    #
    # When inside an inner emulab, we have to ask the outer emulab for
    # our nodeid; we cannot just pick one out of a hat, at least not yet.
    #
    if ($ELABINELAB) {
	$arghash = array();
	$arghash["mac"] = $interfaces[0]["mac"];

	$results = XMLRPC("nobody", $TBADMINGROUP,
			  "elabinelab.newnode_info", $arghash);

	if (!$results || ! isset($results{'nodeid'})) {
	    echo "Could not get nodeid from XMLRPC server; quitting.\n";
	    exit;
	}
	elseif (preg_match("/^(.*[^\d])(\d+)$/",
			   $results{'nodeid'}, $matches)) {
	    $base   = $matches[1];
	    $number = $matches[2];
	    return array($base, intval($number));
	}
	else {
	    $nodeid = $results{'nodeid'};
	    
	    echo "Improper nodeid ($nodeid) from XMLRPC server; quitting.\n";
	    exit;
	}
    }
254 255

    #
256 257
    # First, check to see if there's a recent entry in new_nodes we can name
    # this node after
258
    #
259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286
    $query_result = DBQueryFatal("select node_id from new_nodes " .
        "order by created desc limit 1");
    if (mysql_num_rows($query_result)) {
        $row = mysql_fetch_array($query_result);
	$old_node_id = $row[0];
	#
	# Try to figure out if this is in some format we can increment
	#
	if (preg_match("/^(.*[^\d])(\d+)$/",$old_node_id,$matches)) {
	    echo "Matches pcXXX format";
	    # pcXXX format
	    $base = $matches[1];
	    $number = $matches[2];
	    $potential_name = $base . ($number + 1);
	    if (!check_node_exists($potential_name)) {
		return array($base,($number +1));
	    }
	} elseif (preg_match("/^(.*)-([a-zA-Z])$/",$old_node_id,$matches)) {
	    # Something like WAIL's (type-rack-A) format
	    $base = $matches[1];
	    $lastchar = $matches[2];
	    $newchar = chr(ord($lastchar) + 1);
	    $potential_name = $base . '-' . $newchar;
	    if (!check_node_exists($potential_name)) {
		return array($base . '-', $newchar);
	    }
	}
    }
287 288

    #
289
    # Okay, that didn't work.
290 291 292 293
    # Just go through the nodes and new_nodes tables looking for one that
    # hasn't been used yet - put in a silly little guard to prevent an
    # infinite loop in case of bugs.
    #
294 295
    $node_number = 0;
    while ($node_number < 10000) {
296 297
	$node_number++;
    	$potential_name = $prefix . $node_number;
298 299
	if (!check_node_exists($potential_name)) {
	    break;
300 301 302
	}
    }

303
    return array($prefix, $node_number);
304 305 306 307

}

?>