opsdb_control.in 19 KB
Newer Older
1 2
#!/usr/bin/perl -wT
#
3
# Copyright (c) 2005-2011 University of Utah and the Flux Group.
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
# 
# {{{EMULAB-LICENSE
# 
# This file is part of the Emulab network testbed software.
# 
# This file is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or (at
# your option) any later version.
# 
# This file is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public
# License for more details.
# 
# You should have received a copy of the GNU Affero General Public License
# along with this file.  If not, see <http://www.gnu.org/licenses/>.
# 
# }}}
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 61 62 63 64 65 66 67 68 69 70 71 72
#
use English;
use Getopt::Std;
use Errno qw(EEXIST);
use strict;

#
# Control the privilege tables on the ops DB.
#
sub usage()
{
    print STDOUT "Usage: opsdb_control adduser <uid>\n";
    exit(-1);
}
my $optlist = "d";
my $debug   = 0;

#
# Configure variables
#
my $TB		= "@prefix@";
my $TBOPS       = "@TBOPSEMAIL@";
my $CONTROL     = "@USERNODE@";
my $BOSSNODE	= "@BOSSNODE@";
my $OPSDBSUPPORT= @OPSDBSUPPORT@;

# Locals
my $SSH         = "$TB/bin/sshtb";
my $OPSDBPROXY  = "$TB/sbin/opsdb_control.proxy";
my $SAVEUID	= $UID;

#
# Untaint the path
# 
$ENV{'PATH'} = "/bin:/usr/bin";
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};

#
# Turn off line buffering on output
#
$| = 1;

# Protos
sub AddUser(@);
sub DelUser(@);
sub AddProj(@);
sub AddGroup(@);
sub DelProj(@);
sub DelGroup(@);
sub SetGroups(@);
73
sub SetGroupsAux(@);
74 75
sub AddExpDB(@);
sub DelExpDB(@);
76 77 78
sub AddTempDB(@);
sub LoadTempDB(@);
sub DelTempDB(@);
79
sub DumpExpDB(@);
80
sub CleanExpDB(@);
81
sub GraphDB(@);
82 83 84 85 86 87 88 89 90 91
sub DoOpsStuff($;$);
sub Initialize();
sub fatal($);

#
# Load the Testbed support stuff. 
#
use lib "@prefix@/lib";
use libdb;
use libtestbed;
92
use User;
93 94
use Group;
use Experiment;
95

96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
#
# We don't want to run this script unless its the real version.
#
if ($EUID != 0) {
    die("*** $0:\n".
	"    Must be setuid! Maybe its a development version?\n");
}

#
# This script is setuid, so please do not run it as root. Hard to track
# what has happened.
# 
if ($UID == 0) {
    die("*** $0:\n".
	"    Please do not run this as root! Its already setuid!\n");
}

#
# If no opsdb support, just exit. 
#
if (! $OPSDBSUPPORT) {
    print "OPS DB support is not enabled. Exiting ...\n";
    exit(0);
}

121 122 123
#
# Verify user and get his DB uid.
#
124 125 126
my $this_user = User->ThisUser();
if (! defined($this_user)) {
    fatal("You ($UID) do not exist!");
127
}
128 129
my $user_dbid  = $this_user->dbid();
my $user_uid   = $this_user->uid();
130

131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
#
# Parse command arguments. Once we return from getopts, all that should be
# left are the required arguments.
#
my %options = ();
if (! getopts($optlist, \%options)) {
    usage();
}
if (defined($options{"d"})) {
    $debug = 1;
}
usage()
    if (@ARGV < 1);

my $action = shift(@ARGV);

if ($action eq "adduser") {
    exit(AddUser(@ARGV));
}
elsif ($action eq "deluser") {
    exit(DelUser(@ARGV));
}
elsif ($action eq "addproj") {
    exit(AddProj(@ARGV));
}
elsif ($action eq "addgroup") {
    exit(AddGroup(@ARGV));
}
elsif ($action eq "delproj") {
    exit(DelProj(@ARGV));
}
elsif ($action eq "delgroup") {
    exit(DelGroup(@ARGV));
}
elsif ($action eq "setgroups") {
    exit(SetGroups(@ARGV));
}
elsif ($action eq "addexpdb") {
    exit(AddExpDB(@ARGV));
}
elsif ($action eq "delexpdb") {
    exit(DelExpDB(@ARGV));
}
174 175 176 177 178 179 180 181 182
elsif ($action eq "addtempdb") {
    exit(AddTempDB(@ARGV));
}
elsif ($action eq "deltempdb") {
    exit(DelTempDB(@ARGV));
}
elsif ($action eq "loadtempdb") {
    exit(LoadTempDB(@ARGV));
}
183 184 185
elsif ($action eq "dumpexpdb") {
    exit(DumpExpDB(@ARGV));
}
186 187 188
elsif ($action eq "cleanexpdb") {
    exit(CleanExpDB(@ARGV));
}
189 190 191
elsif ($action eq "graphdb") {
    exit(GraphDB(@ARGV));
}
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221
elsif ($action eq "setup") {
    exit(Initialize());
}
else {
    die("*** $0:\n".
	"    Do not know what to do with '$action'!\n");
}
exit(0);

#
# Add user. The user ID and password are added to the user table on ops,
# but with no privs to do anything.
#
sub AddUser(@)
{
    my ($target_uid) = @_;

    usage()
	if (@_ != 1);

    #
    # Untaint args.
    #
    if ($target_uid =~ /^([-\w]+)$/) {
	$target_uid= $1;
    }
    else {
	die("Bad data in uid: $target_uid");
    }

222 223
    # Map target user to object.
    my $target_user = User->Lookup($target_uid);
224
    fatal("No such user in DB: $target_uid!")
Leigh Stoller's avatar
Leigh Stoller committed
225
	if (!defined($target_uid));
226

227
    my $password = $target_user->mailman_password();
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 254 255 256 257 258 259 260 261 262
    fatal("No password defined for $target_uid!")
	if (!defined($password) || $password eq "");

    print "Adding user '$target_uid' to mysql database on $CONTROL.\n";
    my $retval = DoOpsStuff("adduser $target_uid", $password);
    if ($retval) {
	if ($retval == EEXIST()) {
	    # Not an error.
	    return 0;
	}
	fatal("$OPSDBPROXY failed on $CONTROL!");
    }
    return 0;
}

#
# Delete user.
#
sub DelUser(@)
{
    my ($target_uid) = @_;

    usage()
	if (@_ != 1);

    #
    # Untaint args.
    #
    if ($target_uid =~ /^([-\w]+)$/) {
	$target_uid= $1;
    }
    else {
	die("Bad data in uid: $target_uid");
    }

263 264
    # Map target user to object.
    my $target_user = User->Lookup($target_uid);
265
    fatal("No such user in DB: $target_uid!")
Leigh Stoller's avatar
Leigh Stoller committed
266
	if (!defined($target_uid));
267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291

    print "Removing user '$target_uid' from mysql database on $CONTROL.\n";
    my $retval = DoOpsStuff("deluser $target_uid");
    if ($retval) {
	fatal("$OPSDBPROXY failed on $CONTROL!");
    }
    return 0;
}

#
# Add a project or group to the list of DBs on ops.
#
sub AddProj(@)
{
    my ($pid) = @_;

    usage()
	if (@_ != 1);

    return AddGroup($pid, $pid);
}

sub AddGroup(@)
{
    usage()
292
	if (@_ < 1 || @_ > 3);
293

294 295 296
    my $group = Group->Lookup($_[0], $_[1]);
    if (!defined($group)) {
	fatal("No such group: @_!");
297
    }
298 299
    my $pid    = $group->pid();
    my $gid    = $group->gid();
300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325
    my $dbname = ($pid eq $gid ? $pid : "$pid,$gid");

    print "Adding DB '$dbname' to mysql database on $CONTROL.\n";
    my $retval = DoOpsStuff("adddb $dbname");
    if ($retval) {
	fatal("$OPSDBPROXY failed on $CONTROL!");
    }
    return 0;
}

#
# Delete project or group from the list of DBs on ops.
#
sub DelProj(@)
{
    my ($pid) = @_;

    usage()
	if (@_ != 1);

    return DelGroup($pid, $pid);
}

sub DelGroup(@)
{
    usage()
326
	if (@_ < 1 || @_ > 3);
327

328 329 330
    my $group = Group->Lookup($_[0], $_[1]);
    if (!defined($group)) {
	fatal("No such group: @_!");
331
    }
332 333
    my $pid    = $group->pid();
    my $gid    = $group->gid();
334 335 336 337 338 339 340 341 342 343 344 345 346 347 348
    my $dbname = ($pid eq $gid ? $pid : "$pid,$gid");

    print "Removing DB '$dbname' from mysql database on $CONTROL.\n";
    my $retval = DoOpsStuff("deldb $dbname");
    if ($retval) {
	fatal("$OPSDBPROXY failed on $CONTROL!");
    }
    return 0;
}

#
# Set the groups for a user; the list of DBs they can use on OPS.
#
sub SetGroups(@)
{
349
    my @userlist  = ();
350 351

    usage()
352
	if (@_ < 1);
353

354 355 356 357
    foreach my $uid (@_) {
	my $user = User->Lookup($uid);
	if (! defined($user)) {
	    fatal("No such user $uid!");
358
	}
359 360 361 362
	push(@userlist, $user);
    }
    return SetGroupsAux(@userlist);
}
363

364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387
sub SetGroupsAux(@)
{
    my @userlist  = @_;
    my @uids      = ();
    my $input     = "";

    foreach my $user (@userlist) {
	my @groups  = ();
	my @glist   = ();
	my $uid     = $user->uid();
	my $uid_idx = $user->uid_idx();

	next
	    if ($user->status() ne $User::USERSTATUS_ACTIVE);

	# Debug printf below.
	push(@uids, $uid);

	$user->GroupMembershipList(\@groups) == 0 or
	    fatal("Could not get group list for $user");

	foreach my $group (@groups) {
	    my $pid = $group->pid();
	    my $gid = $group->gid();
388

389 390 391 392 393 394 395 396 397 398 399
	    if ($pid eq $gid) {
		push(@glist, "$pid");
	    }
	    else {
		push(@glist, "$pid,$gid");
	    }

	    #
	    # Now get the per-experiment DBs inside this group.
	    #
	    my $experiment_result =
400
		$group->TableLookUp("experiments", "dpdbname", "dpdb!=0");
401 402 403 404 405

	    while (my ($dbname) = $experiment_result->fetchrow_array()) {
		if (defined($dbname) && $dbname ne "") {
		    push(@glist, $dbname);
		}
406
	    }
407 408 409 410 411
	    
	    #
	    # Now get additional temporary DBs.
	    #
	    my $databases_result =
412
		$group->TableLookUp("datapository_databases", "dbname");
413 414 415 416 417 418 419

	    while (my ($dbname) = $databases_result->fetchrow_array()) {
		if (defined($dbname) && $dbname ne "") {
		    push(@glist, $dbname);
		}
	    }
	    
420
	}
421
	$input .= "$uid @glist\n";
422 423
    }
    
424 425 426
    print "Setting DB access list for user(s) '@uids' on $CONTROL.\n"
	if ($debug);
    my $retval = DoOpsStuff("setdbs", $input);
427 428 429 430 431 432 433 434
    if ($retval) {
	fatal("$OPSDBPROXY failed on $CONTROL!");
    }
    return 0;
}

#
# Add and delete a DB for a specific experiment. We use the pid,gid of
435 436
# the experiment to set the access list.
# 
437 438
sub AddExpDB(@)
{
439
    my @uids = ();
440 441

    usage()
442
	if (@_ < 1 || @_ > 3);
443

444 445 446
    my $experiment = Experiment->Lookup($_[0], $_[1]);
    if (!defined($experiment)) {
	fatal("No such experiment: @_!");
447
    }
448 449 450
    my $pid    = $experiment->pid();
    my $eid    = $experiment->eid();
    my $gid    = $experiment->gid();
451
    my $dbname = "${pid}+${eid}";
452
    my $exptidx= $experiment->idx();
453

454
    if (defined($experiment->dpdbname())) {
455
	# Allow override.
456
	$dbname = $experiment->dpdbname();
457
    }
458 459
    my $dpdbpassword = $experiment->dpdbpassword();
	
460 461 462 463
    if (!defined($dpdbpassword)) {
	$dpdbpassword = TBGenSecretKey();
	$dpdbpassword = substr($dpdbpassword, 0, 10);
    }
464 465 466 467

    #
    # XXX See if there are any traced links. 
    #
468 469 470
    my $query_result =
	$experiment->TableLookUp("virt_lans", "vname", "trace_db!=0");
					     
471
    my $traceflag = ($query_result->numrows ? "-s" : "");
472 473

    print "Adding DB '$dbname' to mysql database on $CONTROL.\n";
474
    my $retval = DoOpsStuff("adddb $dbname $traceflag");
475 476 477 478
    if ($retval) {
	fatal("$OPSDBPROXY failed on $CONTROL!");
    }

479 480 481 482 483 484 485
    $experiment->Update({"dpdbpassword" => "$dpdbpassword",
			 "dpdbname"     => "$dbname"}) == 0 or
	fatal("Could not update dpdbname,dpdbpassword for $experiment");

    $experiment->TableUpdate("experiment_stats",
			     {"dpdbname" => "$dbname"}) == 0 or
	fatal("Could not update experiment_stats for $experiment");
486

487 488 489 490
    #
    # Add a user that is named by this DB, with the password from above.
    # Basically, a per-experiment DB user for the DB.
    #
491 492 493 494
    my $dbuser = "E${exptidx}";
    
    print "Adding user '$dbuser' to mysql database on $CONTROL.\n";
    $retval = DoOpsStuff("adduser $dbuser", $dpdbpassword);
495 496 497
    if ($retval && $retval != EEXIST()) {
	fatal("$OPSDBPROXY failed on $CONTROL!");
    }
498
    $retval = DoOpsStuff("setdbs", "$dbuser $dbname");
499 500 501 502
    if ($retval) {
	fatal("$OPSDBPROXY failed on $CONTROL!");
    }

503 504 505
    #
    # Now we need to update the access list for everyone in the group.
    #
506 507 508 509 510 511 512 513
    my $group = $experiment->GetGroup();
    my @userlist;

    $group->MemberList(\@userlist) == 0 or
	fatal("Could not get user list for $group");

    SetGroupsAux(@userlist) == 0
	or fatal("Could not setgroups for $experiment!");
514 515 516

    return 0;
}
517

518 519 520
sub DelExpDB(@)
{
    usage()
521
	if (@_ < 1 || @_ > 3);
522

523 524 525
    my $experiment = Experiment->Lookup($_[0], $_[1]);
    if (!defined($experiment)) {
	return 0;
526
    }
527 528
    my $dbname = $experiment->dpdbname();
    my $exptidx= $experiment->idx();
529 530 531 532

    return -1
	if (!defined($dbname));

533
    #
534
    # Always do a DB removal if the experiment has a dbname set.
535
    #
536 537 538 539
    my $dbuser = "E${exptidx}";
    
    print "Deleting user '$dbuser' from mysql database on $CONTROL.\n";
    my $retval = DoOpsStuff("deluser $dbuser");
540 541 542 543
    if ($retval) {
	fatal("$OPSDBPROXY failed on $CONTROL!");
    }

544
    print "Removing DB '$dbname' from mysql database on $CONTROL.\n";
545
    $retval = DoOpsStuff("deldb $dbname");
546 547 548 549 550 551 552 553 554 555
    if ($retval) {
	fatal("$OPSDBPROXY failed on $CONTROL!");
    }
    #
    # No need to do a setgroups here since the proxy on ops removed the
    # DB and any user entries for that DB.
    #
    return 0;
}

556 557 558
sub DumpExpDB(@)
{
    usage()
559
	if (@_ < 2 || @_ > 4);
560

561 562 563
    my $experiment = Experiment->Lookup($_[0], $_[1]);
    if (!defined($experiment)) {
	return 0;
564
    }
565 566 567
    my $dbname   = $experiment->dpdbname();
    my $filename = $_[2];

568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585
    if ($filename =~ /^([-\w\/\.\+,]+)$/) {
	$filename = $1;
    }
    else {
	die("Bad data in filename: $filename");
    }

    return -1
	if (!defined($dbname));

    print "Dumping mysql DB '$dbname' to $filename on $CONTROL.\n";
    my $retval = DoOpsStuff("dumpdb $dbname $filename");
    if ($retval) {
	fatal("$OPSDBPROXY failed on $CONTROL!");
    }
    return 0;
}

586 587 588
sub CleanExpDB(@)
{
    usage()
589
	if (@_ < 2 || @_ > 3);
590

591 592 593
    my $experiment = Experiment->Lookup($_[0], $_[1]);
    if (!defined($experiment)) {
	return 0;
594
    }
595
    my $dbname   = $experiment->dpdbname();
596 597 598 599 600 601 602 603 604 605 606 607

    return -1
	if (!defined($dbname));

    print "Cleaning mysql DB '$dbname' on $CONTROL.\n";
    my $retval = DoOpsStuff("cleandb $dbname");
    if ($retval) {
	fatal("$OPSDBPROXY failed on $CONTROL!");
    }
    return 0;
}

608 609 610 611 612 613
#
# Add a temporary DB to ops.
#
sub AddTempDB(@)
{
    usage()
614
	if (@_ < 2 || @_ > 4);
615

616 617 618
    my $group = Group->Lookup($_[0], $_[1]);
    if (!defined($group)) {
	fatal("No such group: @_!");
619
    }
620 621
    my $dbname = $_[2];

622 623 624 625 626 627 628
    if ($dbname =~ /^([-\w,\+]+)$/) {
	$dbname = $1;
    }
    else {
	die("Bad data in dbname: $dbname");
    }

629 630 631 632 633
    my $pid     = $group->pid();
    my $gid     = $group->gid();
    my $pid_idx = $group->pid_idx();
    my $gid_idx = $group->gid_idx();

634 635 636 637
    #
    # Add DB record for it.
    #
    if (! DBQueryWarn("insert into datapository_databases set ".
638
		      "  pid='$pid', gid='$gid', ".
639
		      "  pid_idx='$pid_idx', gid_idx='$gid_idx', ".
640
		      "  uid='$user_uid', uid_idx='$user_dbid', ".
641 642 643 644
		      "  dbname='$dbname', created=now()")) {
	fatal("Failed to add temporary dbname to database");
    }

645 646 647
    print "Adding temporary DB '$dbname' to mysql database on $CONTROL.\n";
    my $retval = DoOpsStuff("adddb $dbname -t");
    if ($retval) {
648 649
	DBQueryWarn("delete from datapository_databases ".
		    "where dbname='$dbname'");
650 651 652 653 654 655
	fatal("$OPSDBPROXY failed on $CONTROL!");
    }

    #
    # Now we need to update the access list for everyone in the group.
    #
656 657 658 659 660 661 662 663
    my @userlist;

    $group->MemberList(\@userlist) == 0 or
	fatal("Could not get user list for $group");

    SetGroupsAux(@userlist) == 0
	or fatal("Could not setgroups for $group!");

664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723
    return 0;
}

sub LoadTempDB(@)
{
    my ($dbname, $filename) = @_;

    usage()
	if (@_ != 2);

    #
    # Untaint args.
    #
    if ($dbname =~ /^([-\w,\+]+)$/) {
	$dbname = $1;
    }
    else {
	die("Bad data in dbname: $dbname");
    }
    if ($filename =~ /^([-\w\/\.\+,]+)$/) {
	$filename = $1;
    }
    else {
	die("Bad data in filename: $filename");
    }
    
    print "Loading mysql DB '$dbname' from $filename on $CONTROL.\n";
    my $retval = DoOpsStuff("loaddb $dbname $filename");
    if ($retval) {
	fatal("$OPSDBPROXY failed on $CONTROL!");
    }
    return 0;
}

#
# Delete a temporary DB from ops.
#
sub DelTempDB(@)
{
    my ($dbname) = @_;

    usage()
	if (@_ != 1);

    #
    # Untaint args.
    #
    if ($dbname =~ /^([-\w,\+]+)$/) {
	$dbname = $1;
    }
    else {
	die("Bad data in dbname: $dbname");
    }

    print "Deleting temporary DB '$dbname' from mysql database on $CONTROL.\n"
	if ($debug);
    my $retval = DoOpsStuff("deldb $dbname");
    if ($retval) {
	fatal("$OPSDBPROXY failed on $CONTROL!");
    }
724 725 726 727 728 729 730 731 732 733 734
    DBQueryFatal("delete from datapository_databases ".
		 "where dbname='$dbname'");
    return 0;
}

#
# Hack graph support.
#
sub GraphDB(@)
{
    usage()
735 736 737 738 739
	if (@_ < 2);

    my $dbname   = shift(@_);
    my $which    = shift(@_);
    my @optargs  = ();
740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755

    #
    # Untaint args.
    #
    if ($dbname =~ /^([-\w,\+]+)$/) {
	$dbname = $1;
    }
    else {
	die("Bad data in dbname: $dbname");
    }
    if ($which =~ /^([\w]*)$/) {
	$which = $1;
    }
    else {
	die("Bad data in which: $which");
    }
756 757 758 759 760 761

    # Check the rest of the args with a generic test.
    foreach my $arg (@_) {
	# Note different taint check (allow /).
	if ($arg =~ /^([-\w\.\/\:]+)$/) {
	    $arg = $1;
762 763
	}
	else {
764
	    tbdie("Bad data in argument: $arg");
765
	}
766
	push(@optargs, $arg);
767 768 769 770
    }

    print "Graphing DB '$dbname' from mysql database on $CONTROL.\n"
	if ($debug);
771
    my $retval = DoOpsStuff("graphdb $dbname $which @optargs");
772 773 774
    if ($retval) {
	fatal("$OPSDBPROXY failed on $CONTROL!");
    }
775 776 777
    return 0;
}

778 779 780 781 782
# Wrapper for ssh.
sub DoOpsStuff($;$)
{
    my ($remote_command, $input) = @_;
    my $retval = 0;
783
    my $flag   = ($debug ? "-d" : "");
784 785 786 787 788
    my ($command);
    
    # For ssh.
    $UID = $EUID;

789
    $command = "$SSH -host $CONTROL $OPSDBPROXY $flag $remote_command";
790 791 792

    print "Running command '$command'\n"
	if ($debug);
793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813

    # Echo stuff to remote stdin
    if (defined($input) && $input ne "") {
	if (!open(OPS, "| $command")) {
	    print "Could not start '$SSH'\n";
	    $retval = -1;
	}
	else {
	    print OPS $input;
	    if (! close(OPS)) {
		print(($! ? "Error closing pipe: $!\n"
		          : "Exit status $? from pipe\n"));
		$retval = -1;
	    }
	}
    }
    else {
	system($command);
	if ($?) {
	    $retval = $? >> 8;
	}
814 815 816 817 818 819 820 821 822 823 824
    }
    $EUID = $SAVEUID;
    
    return $retval;
}

#
# Initial setup for pre-existing emulabs.
#
sub Initialize()
{
825 826
    my @uids = ();
    
827 828 829 830
    #
    # Initialize a mailman password for all users, just in case not set.
    #
    my $query_result =
831 832
	DBQueryFatal("select uid,uid_idx from users ".
		     "where mailman_password is NULL");
833

834 835
    while (my ($uid,$uid_idx) = $query_result->fetchrow_array()) {
	print "Setting initial mailman password for $uid ($uid_idx)\n"
836 837 838 839 840 841
	    if ($debug);

	my $password = TBGenSecretKey();
	$password = substr($password, 0, 10);

	DBQueryFatal("update users set mailman_password='$password' ".
842
		     "where uid_idx='$uid_idx'");
843 844 845 846 847 848 849 850
    }

    #
    # Now add all active users.
    # 
    my $users_result =
	DBQueryFatal("select distinct g.uid ".
		     "  from group_membership as g ".
851
		     "left join users as u on u.uid_idx=g.uid_idx ".
852 853 854 855 856
		     "where u.status='active' or u.status='frozen' ".
#  		     "  and (g.pid='testbed' or g.pid='emulab-ops' or ".
#		     "       g.pid='tbres' or g.pid='utahstud')" .
		     "order by u.admin");

857 858 859
    # Need to do this when we want to seek around inside the results.
    $users_result = $users_result->WrapForSeek();

860 861 862 863 864 865 866 867 868 869
    while (my ($uid) = $users_result->fetchrow_array()) {
	AddUser(($uid)) == 0
	    or fatal("Could not add user $uid to DB on $CONTROL");
    }

    #
    # Add project and group DBs.
    #
    my $projects_result =
	DBQueryFatal("select g.pid,g.gid from groups as g ".
870
		     "left join projects as p on p.pid_idx=g.pid_idx ".
871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886
		     "where p.approved=1 ".
#		     "and (p.pid='testbed' or p.pid='emulab-ops' or ".
#		     "     p.pid='tbres' or p.pid='utahstud') ".
		     "");

    while (my ($pid,$gid) = $projects_result->fetchrow_array()) {
	AddGroup(($pid, $gid)) == 0
	    or fatal("Could not add database for $pid,$gid to DB on $CONTROL");
    }

    #
    # Now go back to the users list and set the access lists
    #
    $users_result->dataseek(0);
    
    while (my ($uid) = $users_result->fetchrow_array()) {
887
	push(@uids, $uid);
888
    }
889 890 891
    SetGroups(@uids) == 0
	or fatal("Could not set groups for @uids!");
    
892 893 894 895 896 897 898 899 900 901
    return 0;
}

sub fatal($)
{
    my($mesg) = $_[0];

    die("*** $0:\n".
	"    $mesg\n");
}