mkproj.in 7.31 KB
Newer Older
1
#!/usr/bin/perl -wT
Leigh B. Stoller's avatar
Leigh B. Stoller committed
2 3 4

#
# EMULAB-COPYRIGHT
5
# Copyright (c) 2000-2003, 2005 University of Utah and the Flux Group.
Leigh B. Stoller's avatar
Leigh B. Stoller committed
6 7 8
# All rights reserved.
#

9 10 11 12 13 14 15 16 17 18 19
use English;

#
# Make a project directory hierarchy. Must be called as tbroot.
# Creates a directory rooted /proj/pid. The directory is setuid
# to the project leader, and setgid to the project gid. We get
# this info from the database.
#
# usage: mkproj <pid>
#

20 21
sub fatal($);

22 23 24 25 26 27
#
# Configure variables
#
my $TB       = "@prefix@";
my $TBOPS    = "@TBOPSEMAIL@";
my $MKGROUP  = "$TB/sbin/mkgroup";
28
my $SETGROUPS= "$TB/sbin/setgroups";
29
my $MKACCT   = "$TB/sbin/tbacct add";
30 31
my $CVSBIN   = "/usr/bin/cvs";
my $CHOWN    = "/usr/sbin/chown";
32
my $GRANTTYPE= "$TB/sbin/grantnodetype -d";
33 34 35 36
my $WIKISUPPORT   = @WIKISUPPORT@;
my $BUGDBSUPPORT  = @BUGDBSUPPORT@;
my $CVSSUPPORT    = @CVSSUPPORT@;
my $MAILMANSUPPORT= @MAILMANSUPPORT@;
37
my $ADDWIKIPROJ = "$TB/sbin/addwikiproj";
38
my $ADDBUGDBPROJ= "$TB/sbin/addbugdbproj";
39
my $ADDMMLIST   = "$TB/sbin/addmmlist";
40 41

my $PROJROOT = "/proj";
42
my $GRPROOT  = "/groups";
43 44
my $TFTPROOT = "/tftpboot";
my @DIRLIST  = ("exp", "images", "logs", "deltas", "tarfiles", "rpms",
45
		"groups", "tiplogs", "CVS");
46
my $projhead;
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62

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

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

#
# Load the Testbed support stuff. 
#
use lib "@prefix@/lib";
63
use libaudit;
64 65 66 67 68 69 70 71 72 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 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
use libdb;
use libtestbed;

#
# 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");
}

#
# Check args.
#
if ($#ARGV < 0) {
    die("Usage: mkprojdir <pid>\n");
}
my $pid = $ARGV[0];

#
# Untaint the argument.
#
if ($pid =~ /^([-\@\w.]+)$/) {
    $pid = $1;
}
else {
    die("Invalid pid '$pid' contains illegal characters.\n");
}

#
# Figure out who called us. Only with admin status in the DB can run
# this script.
#
if (!TBAdmin($UID)) {
    die("*** $0:\n".
	"    You must be a TB administrator to run this script!\n");
}

#
# We need the project leader name.
#
if (! ($projhead = ProjLeader($pid))) {
    die("*** $0:\n".
	"    Could not get project leader for project $pid!\n");
}

119 120 121 122 123 124 125 126 127 128
#
# This script is always audited. Mail is sent automatically upon exit.
#
if (AuditStart(0)) {
    #
    # Parent exits normally
    #
    exit(0);
}

129 130 131 132
#
# Before we can proceed, we need to create the project (unix) group
# and then create an account for the project leader. We pass this off
# to sub scripts, but because they are also setuid, we need to flip
133
# our UID (perl sillyness).
134
#
135
$EUID = $UID;
136

137 138
system("$MKGROUP $pid $pid") == 0 or
    fatal("$MKGROUP $pid failed!");
139

140 141 142 143
if ($WIKISUPPORT) {
    system("$ADDWIKIPROJ $pid") == 0 or
	fatal("$ADDWIKIPROJ $pid failed!");
}
144 145 146 147
if ($BUGDBSUPPORT) {
    system("$ADDBUGDBPROJ $pid") == 0 or
	fatal("$ADDBUGDBPROJ $pid failed!");
}
148 149 150 151
if ($MAILMANSUPPORT) {
    system("$ADDMMLIST -a ${pid}-users") == 0 or
	fatal("$ADDMMLIST -a ${pid}-users failed!");
}
152

153 154 155
system("$MKACCT $projhead") == 0 or
    fatal("$MKACCT $projhead failed!");

156 157 158
system("$SETGROUPS $projhead") == 0 or
    fatal("$SETGROUPS $projhead failed!");

159
$EUID = 0;
160 161 162 163 164 165 166 167 168 169 170 171 172

#
# This acts as check (and we need the numeric uid) in case mkacct failed!
# 
my (undef,undef,$uid) = getpwnam($projhead)
    or fatal("$projhead not in passwd file");

my (undef,undef,$gid) = getgrnam($pid)
    or fatal("$pid not in group file");

#
# Okay, do it.
#
173 174 175 176
if (! -e "$PROJROOT/$pid") {
    if (! mkdir("$PROJROOT/$pid", 0770)) {
	fatal("Could not make directory $PROJROOT/$pid: $!");
    }
177

178 179 180
    if (! chmod(0770, "$PROJROOT/$pid")) {
	fatal("Could not chmod directory $PROJROOT/$pid: $!");
    }
181

182 183 184
    if (! chown($uid, $gid, "$PROJROOT/$pid")) {
	fatal("Could not chown $PROJROOT/$pid to $uid/$gid: $!");
    }
185 186 187 188 189 190
}

#
# Make project subdirs.
#
foreach my $dir (@DIRLIST) {
191 192 193 194 195 196 197 198 199 200
    if (! -e "$PROJROOT/$pid/$dir") {
	if (! mkdir("$PROJROOT/$pid/$dir", 0770)) {
	    fatal("Could not make directory $PROJROOT/$pid/$dir: $!");
	}
	if (! chmod(0770, "$PROJROOT/$pid/$dir")) {
	    fatal("Could not chmod directory $PROJROOT/$pid/$dir: $!");
	}
	if (! chown($uid, $gid, "$PROJROOT/$pid/$dir")) {
	    fatal("Could not chown $PROJROOT/$pid/$dir to $uid/$gid: $!");
	}
201 202 203 204 205
    }
}

#
# Create a tftp directory for oskit kernels.
206 207 208 209 210 211 212 213 214 215 216
#
if (! -e "$TFTPROOT/proj/$pid") {
    if (! mkdir("$TFTPROOT/proj/$pid", 0770)) {
	fatal("Could not make directory $TFTPROOT/proj/$pid: $!");
    }
    if (! chmod(0777, "$TFTPROOT/proj/$pid")) {
	fatal("Could not chmod directory $TFTPROOT/proj/$pid: $!");
    }
    if (! chown($uid, $gid, "$TFTPROOT/proj/$pid")) {
	fatal("Could not chown $TFTPROOT/proj/$pid to $uid/$gid: $!");
    }
217 218
}

219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235
#
# Do the CVS stuff if its turned on.
#
my $CVSDIR = "$PROJROOT/$pid/CVS";

if ($CVSSUPPORT && -e $CVSDIR) {
    system("$CVSBIN -d $CVSDIR init");
    if ($?) {
	fatal("Could not cvs init $CVSDIR!");
    }
    # Chown the tree.
    system("$CHOWN -R ${uid}:${gid} $CVSDIR");
    if ($?) {
	fatal("Could not chown ${uid}:${gid} $CVSDIR!");
    }
}

236 237
#
# Create groups directory.
238 239 240 241 242
#
if (! -e "$GRPROOT/$pid") {
    if (! mkdir("$GRPROOT/$pid", 0770)) {
	fatal("Could not make directory $GRPROOT/$pid: $!");
    }
243
    if (! chmod(0770, "$GRPROOT/$pid")) {
244 245 246 247 248
	fatal("Could not chmod directory $GRPROOT/$pid: $!");
    }
    if (! chown($uid, $gid, "$GRPROOT/$pid")) {
	fatal("Could not chown $GRPROOT/$pid to $uid/$gid: $!");
    }
249 250 251 252 253 254 255

    # Create a group link for the default group.
    if (! -e "$GRPROOT/$pid/$pid") {    
	if (system("ln -s $PROJROOT/$pid $GRPROOT/$pid/$pid")) {
	    fatal("Could not symlink $PROJROOT/$pid to $GRPROOT/$pid/$pid");
	}
    }
256 257
}

258 259 260
#
# Create experiment working directory.
#
Leigh B. Stoller's avatar
Leigh B. Stoller committed
261
my $workdir = TBDB_EXPT_WORKDIR() . "/$pid";
262

263
if (! -e $workdir) {
264
    if (! mkdir("$workdir", 0775)) {
265 266
	fatal("Could not make directory $workdir: $!");
    }
267
    if (! chmod(0775, "$workdir")) {
268 269 270 271 272
	fatal("Could not chmod directory $workdir: $!");
    }
    if (! chown($uid, $gid, "$workdir")) {
	fatal("Could not chown $workdir to $uid/$gid: $!");
    }
273 274
}

275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306
#
# If approved to use remote nodes, then grant permission to use the
# specific types of virtual nodes on those remote physical nodes.
# Unfortunately, the node_types table does not store a relationship
# between the phys type and the virtual types that are hosted on them.
# Need to add that I guess, but in the meantime we have just 3 remote
# phys types to worry about. 
#
my $query_result =
    DBQueryFatal("select pcremote_ok from projects where pid='$pid'");
if ($query_result->num_rows) {
    my ($pcremote) = $query_result->fetchrow_array();

    if (defined($pcremote)) {
	print "$pcremote\n";
	
	foreach my $type (split(",", $pcremote)) {
	    print "$type\n";
	    
	    if ($type eq "pcplabphys") {
		$type = "pcplab";
	    }
	    elsif ($type eq "pcron") {
		$type = "pcvwa";
	    }
	    elsif ($type eq "pcwa") {
		$type = "pcvwa";
	    }
	    else {
		fatal("Unknown remote type $type!");
	    }
	    print "$type\n";
307 308 309

	    $EUID = $UID;

310 311
	    system("$GRANTTYPE -p $pid $type") == 0 or
		fatal("Could not grant permission to use type $type!");
312 313

	    $EUID = 0;
314 315 316 317
	}
    }
}

318
print "Project Creation Completed!\n";
319 320
exit(0);

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

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