newimageid_ez.php3 43.8 KB
Newer Older
1
<?php
Leigh B. Stoller's avatar
Leigh B. Stoller committed
2
#
3
# Copyright (c) 2000-2015, 2019 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/>.
# 
# }}}
Leigh B. Stoller's avatar
Leigh B. Stoller committed
23
#
24
include("defs.php3");
25 26
include_once("imageid_defs.php");
include_once("osinfo_defs.php");
27
include_once("node_defs.php");
28
include_once("osiddefs.php3");
29

30 31
#
# XXX
32 33
# In this form, we make the images:imagename and the os_info:osname the same!
# Currently, TBDB_OSID_OSNAMELEN is shorter than TBDB_IMAGEID_IMAGENAMELEN
34
# and that causes problems since we use the same id for both tables. For
35
# now, test for the shorter of the two.
36
# 
37 38 39 40 41 42 43 44 45 46 47 48
#
# Only known and logged in users.
#
$this_user = CheckLoginOrDie();
$uid       = $this_user->uid();
$dbid      = $this_user->dbid();
$isadmin   = ISADMIN();

#
# Verify page arguments.
#
$optargs = OptionalPageArguments("submit",       PAGEARG_STRING,
49
				 "imagetype",    PAGEARG_STRING,
50 51
				 "canceled",     PAGEARG_BOOLEAN,
				 "confirmed",    PAGEARG_BOOLEAN,
52
				 "ec2",		 PAGEARG_BOOLEAN,
53 54 55
				 "node",	 PAGEARG_NODE,
				 "baseimage",    PAGEARG_IMAGE,
				 "baseosinfo",   PAGEARG_OSINFO,
56 57
				 "formfields",   PAGEARG_ARRAY,
                                 "classic",      PAGEARG_BOOLEAN);
58

59 60 61 62 63
# Flag to import an EC2 image.
if (!isset($ec2)) {
    $ec2 = 0;
}

64 65 66 67 68 69 70 71 72 73
#
# If starting from a specific node we can derive the type and possibly
# the baseimage from it. 
#
if (isset($node)) {
    #
    # If we can find the running osid, then we can setup the page instead
    # of having the user figure it out. Note that only makes sense for
    # EZ images.
    #
74
    $baseimage = $node->def_boot_image();
75 76 77 78
    #
    # Try for at least an osinfo if no image.
    #
    if (! $baseimage) {
79
	$baseosinfo = $node->def_boot_osinfo();
80
    }
81
    else {
82
	$baseosinfo = $baseimage->OSinfo();
83
    }
84 85
}
elseif (isset($baseimage)) {
86
    $baseosinfo = $baseimage->OSinfo();
87
}
88
elseif ($ec2) {
89 90 91 92 93 94 95 96
    $imagetype = "xen";
}
if (isset($baseosinfo) && $baseosinfo->def_parentosid()) {
    $def_parentosinfo = OSinfo::Lookup($baseosinfo->def_parentosid());
    if (! $def_parentosinfo) {
	TBERROR("Could not lookup osinfo object for parent " .
		$baseosinfo->def_parentosid(), 1);
    }
97
}
98

99 100 101 102
#
# In general, there is no reason for a mere user to do anything but
# clone or snapshot an existing image. 
#
103
if (!$classic && !$ec2) {
104 105 106 107 108 109 110 111 112 113 114
    $imageid = $baseimage->imageid();
    $version = $baseimage->version();
    
    $url = "apt/clone-image.php?imageid=$imageid&version=$version";
    if (isset($node)) {
        $url .= "&node=" . $node->node_id();
    }
    header("Location: $url");
    return;
}

115
#
116 117
# Try to determine what kind of image so we can tailor the form
# a little bit for openvz and xen.
118
#
119 120 121
if (!isset($imagetype) && isset($def_parentosinfo)) {
    if ($def_parentosinfo->FeatureSupported("xen-host")) {
	$imagetype = "xen";
122
    }
123
    else {
124
	$imagetype = "openvz";
125
    }
126 127 128 129 130 131 132 133 134 135 136
}
$title  = "EZ Form";

#
# Options for using this page with different types of nodes.
#
if (!isset($imagetype)) {
    #
    # Generic PC image.
    #
    $view  = array('hide_upload' => 1);
137 138
    $help_message = 
          "See the
139
          <a href=$WIKIDOCURL/Tutorial#CustomOS>
140
          tutorial</a> for more info on creating/using custom Images.";
141 142
    # Default to imagezip ndz files
    $filename_extension = "ndz";
143
}
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
else {
    $view = array('hide_partition' => 1,
		  'hide_upload' => 1);
    
    if ($imagetype == "openvz") {
	$title = "OpenVZ Form";

	$view['hide_mbr']        = 1;
	$view['hide_concurrent'] = 1;
	$view['hide_footnotes']  = 1;
	$view['hide_wholedisk']  = 1;
    }
    # Default to imagezip ndz files
    $filename_extension = "ndz";
}

160 161 162 163 164 165
#
# If we are lucky enough to get a baseimage, do not show footnotes.
#
if (isset($baseimage)) {
    $view['hide_footnotes'] = 1;
}
166

167 168 169
#
# Standard Testbed Header
#
170
PAGEHEADER("Create a new Image Descriptor ($title)");
171 172 173 174

#
# See what projects the uid can do this in.
#
175
$projlist = $this_user->ProjectAccessList($TB_PROJECT_MAKEIMAGEID);
176 177 178 179 180 181 182

if (! count($projlist)) {
    USERERROR("You do not appear to be a member of any Projects in which ".
	      "you have permission to create new Image descriptors.", 1);
}

#
183
# Need a list of node types. We join this over the nodes table so that
184
# we get a list of just the nodes that are currently in the testbed, not
185
# just in the node_types table. Limit by class if given.
186
#
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
$types_list = array();

if (isset($imagetype) && $imagetype == "openvz") {
    $types_list['pcvm'] = 1;
}
else {
    $types_result =
	DBQueryFatal("select distinct n.type from nodes as n ".
		     "left join node_types as nt on n.type=nt.type ".
		     "left join node_type_attributes as a on a.type=n.type ".
		     "where a.attrkey='imageable' and nt.class='pc' and ".
		     "      a.attrvalue!='0' and n.role='testnode'");

    while ($row = mysql_fetch_array($types_result)) {
        $types_list[$row["type"]] = 1;
202
    }
203 204
    if (isset($imagetype) && $imagetype == "xen") {
	$types_list['pcvm'] = 1;
205
    }
206 207
}

208
#
209 210
# Spit the form out using the array of data.
#
211 212
function SPITFORM($formfields, $errors)
{
213 214 215
    global $projlist, $isadmin, $types_list, $osid_oslist, $osid_opmodes,
	$osid_featurelist, $filename_extension, $help_message, $askxen;
    global $node;
216
    global $TBDB_OSID_OSNAMELEN, $TBDB_NODEIDLEN;
217
    global $TBDB_OSID_VERSLEN, $TBBASE, $TBPROJ_DIR, $TBGROUP_DIR;
218
    global $WIKIDOCURL;
219
    global $view, $ec2, $baseimage;
220
    
221 222 223
    #
    # Explanation of the $view argument: used to turn on and off display of
    # various parts of the form, so that it can be used for different types
224
    # of nodes. It's an associative array, with contents like:'hide_partition'.
225 226 227
    # In general, when an option is hidden, it is replaced with a hidden
    # field from $formfields
    #
228 229 230
    if ($help_message) {
        echo "<center><b>$help_message</b></center>\n";
    }
231 232 233 234 235 236 237

    if ($isadmin) {
	echo "<center>
               Administrators get to use the
               <a href='newimageid.php3'>long form</a>.
              </center>\n";
    }
238 239
    
    if ($errors) {
Chad Barb's avatar
 
Chad Barb committed
240 241
	echo "<table class=nogrid
                     align=center border=0 cellpadding=6 cellspacing=0>
242
              <tr>
Chad Barb's avatar
 
Chad Barb committed
243
                 <th align=center colspan=2>
244
                   <font size=+1 color=red>
Chad Barb's avatar
 
Chad Barb committed
245
                      &nbsp;Oops, please fix the following errors!&nbsp;
246 247 248 249 250
                   </font>
                 </td>
              </tr>\n";

	while (list ($name, $message) = each ($errors)) {
251 252
            # XSS prevention.
	    $message = CleanString($message);
253
	    echo "<tr>
Chad Barb's avatar
 
Chad Barb committed
254 255 256 257
                     <td align=right>
                       <font color=red>$name:&nbsp;</font></td>
                     <td align=left>
                       <font color=red>$message</font></td>
258 259 260 261
                  </tr>\n";
	}
	echo "</table><br>\n";
    }
262 263 264 265
    # XSS prevention.
    while (list ($key, $val) = each ($formfields)) {
	$formfields[$key] = CleanString($val);
    }
266 267 268 269

    echo "<SCRIPT LANGUAGE=JavaScript>
              function SetPrefix(theform) 
              {
270 271 272 273
                  var pidx   = theform['formfields[pid]'].selectedIndex;
                  var pid    = theform['formfields[pid]'].options[pidx].value;
                  var gidx   = theform['formfields[gid]'].selectedIndex;
                  var gid    = theform['formfields[gid]'].options[gidx].value;
274
                  var shared = theform['formfields[shared]'].checked;
275 276 277 278 279 280 281
          \n";
    if ($isadmin)
	echo     "var global = theform['formfields[global]'].checked;";
    else
	echo     "var global = 0;";

    echo         "if (pid == '') {
282
                      theform['formfields[path]'].value = '$TBPROJ_DIR';
283 284 285
                  }
                  else if (theform['formfields[imagename]'].value == '') {
		      theform['formfields[imagename]'].defaultValue = '';
286 287 288 289 290 291 292

                      if (global) {
    	                  theform['formfields[path]'].value =
                                  '/usr/testbed/images/';
                      }
		      else if (gid == '' || gid == pid || shared) {
    	                  theform['formfields[path]'].value =
293
                                  '$TBPROJ_DIR/' + pid + '/images/';
294 295 296
                      }
                      else {
    	                  theform['formfields[path]'].value =
297
                                  '$TBGROUP_DIR/' + pid + '/' + gid + '/images/';
298
                      }
299 300
                  }
                  else if (theform['formfields[imagename]'].value != '') {
Leigh B Stoller's avatar
Leigh B Stoller committed
301 302
                      var filename =
                           theform['formfields[imagename]'].value + '/';
303 304 305 306 307 308 309

                      if (global) {
    	                  theform['formfields[path]'].value =
                                  '/usr/testbed/images/' + filename;
                      }
		      else if (gid == '' || gid == pid || shared) {
    	                  theform['formfields[path]'].value =
310
                                  '$TBPROJ_DIR/' + pid + '/images/' + filename;
311 312 313
                      }
                      else {
    	                  theform['formfields[path]'].value =
314
                                  '$TBGROUP_DIR/' + pid + '/' + gid + '/images/' +
315 316
                                  filename;
                      }
317 318 319 320 321 322 323 324 325 326 327
                  }
              }
          </SCRIPT>\n";

    echo "<br>
          <table align=center border=1> 
          <tr>
             <td align=center colspan=2>
                 <em>(Fields marked with * are required)</em>
             </td>
          </tr>
328
          <form action='newimageid_ez.php3' enctype='multipart/form-data'
329 330
              method=post name=idform>\n";

331
    # Carry along stuff ...
332 333 334 335
    if (isset($node)) {
	$id = $node->node_id();
	echo "<input type=hidden name=node_id value='$id'>";
    }
336 337 338
    if ($ec2) {
	echo "<input type=hidden name=ec2 value=true>";
    }
339 340 341
    if ($classic) {
	echo "<input type=hidden name=classic value=true>";
    }
342 343 344 345 346 347
    if (isset($baseimage)) {
        $id = $baseimage->imageid();
	$version = $baseimage->version();
	echo "<input type=hidden name=baseimage value='$id'>";
	echo "<input type=hidden name=version value='$version'>";
    }
348 349 350 351 352 353 354 355 356 357 358 359
    #
    # Select Project
    #
    echo "<tr>
              <td>*Select Project:</td>
              <td><select name=\"formfields[pid]\"
                          onChange='SetPrefix(idform);'>
                      <option value=''>Please Select &nbsp</option>\n";
    
    while (list($project) = each($projlist)) {
	$selected = "";

360
	if ($formfields["pid"] == $project)
361 362 363 364 365 366 367 368
	    $selected = "selected";
	
	echo "        <option $selected value='$project'>$project </option>\n";
    }
    echo "       </select>";
    echo "    </td>
          </tr>\n";

369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385
    #
    # Select a group
    # 
    echo "<tr>
              <td >Group:</td>
              <td><select name=\"formfields[gid]\"
                          onChange='SetPrefix(idform);'>
                    <option value=''>Default Group </option>\n";

    reset($projlist);
    while (list($project, $grouplist) = each($projlist)) {
	for ($i = 0; $i < count($grouplist); $i++) {
	    $group    = $grouplist[$i];

	    if (strcmp($project, $group)) {
		$selected = "";

386 387 388 389
		if (isset($formfields["gid"]) &&
		    isset($formfields["pid"]) &&
		    strcmp($formfields["pid"], $project) == 0 &&
		    strcmp($formfields["gid"], $group) == 0)
390 391 392 393 394 395 396 397 398 399 400
		    $selected = "selected";
		
		echo "<option $selected value=\"$group\">
                           $project/$group</option>\n";
	    }
	}
    }
    echo "     </select>
             </td>
          </tr>\n";

401
    #
402
    # Image Name
403 404 405 406 407 408 409
    #
    echo "<tr>
              <td>*Descriptor Name (no blanks):</td>
              <td class=left>
                  <input type=text
                         onChange='SetPrefix(idform);'
                         name=\"formfields[imagename]\"
410
                         value=\"" . $formfields["imagename"] . "\"
411 412
	                 size=$TBDB_OSID_OSNAMELEN
                         maxlength=$TBDB_OSID_OSNAMELEN>
413 414 415 416 417 418 419 420 421 422 423 424
              </td>
          </tr>\n";

    #
    # Description
    #
    echo "<tr>
              <td>*Description:<br>
                  (a short pithy sentence)</td>
              <td class=left>
                  <input type=text
                         name=\"formfields[description]\"
425
                         value=\"" . $formfields["description"] . "\"
426 427 428 429 430 431 432
	                 size=50>
              </td>
          </tr>\n";

    #
    # Load Partition
    #
433
    if (isset($view["hide_partition"])) {
434 435 436 437 438 439 440
	spithidden($formfields, 'loadpart');
    } else {
	echo "<tr>
		  <td>*Which DOS Partition[<b>1</b>]:<br>
		      (DOS partitions are numbered 1-4)</td>
		  <td><select name=\"formfields[loadpart]\">
			      <option value=X>Please Select </option>\n";
441

442 443
	for ($i = 1; $i <= 4; $i++) {
	    $selected = "";
444

445
	    if (strcmp($formfields["loadpart"], "$i") == 0)
446
		$selected = "selected";
Russ Fish's avatar
Russ Fish committed
447

448 449 450 451 452
	    echo "        <option $selected value=$i>$i </option>\n";
	}
	echo "       </select>";
	echo "    </td>
	      </tr>\n";
453 454 455 456 457
    }

    #
    # Select an OS
    # 
458
    if (isset($view["hide_os"])) {
459
	spithidden($formfields, 'OS');
460 461 462 463
    } else {
	echo "<tr>
		 <td>*Operating System:<br>
		    (OS that is on the partition)</td>
464
		 <td><select name=\"formfields[OS]\">
465
		       <option value=none>Please Select </option>\n";
466

467 468
	while (list ($os, $userokay) = each($osid_oslist)) {
	    $selected = "";
469

470 471
	    if (!$userokay && !$isadmin)
		continue;
472

473 474
	    if (isset($formfields["OS"]) &&
		strcmp($formfields["OS"], $os) == 0)
475
		$selected = "selected";
476

477
	    echo "<option $selected value=$os>$os &nbsp; </option>\n";
478 479 480 481
	}
	echo "       </select>
		 </td>
	      </tr>\n";
482 483 484 485 486
    }

    #
    # Version String
    #
487
    if (isset($view["hide_version"])) {
488
	spithidden($formfields, 'version');
489 490 491 492 493 494
    } else {
	echo "<tr>
		  <td>*OS Version:<br>
		      (eg: 4.3, 7.2, etc.)</td>
		  <td class=left>
		      <input type=text
495 496
			     name=\"formfields[version]\"
			     value=\"" . $formfields["version"] . "\"
497 498 499 500 501
			     size=$TBDB_OSID_VERSLEN
			     maxlength=$TBDB_OSID_VERSLEN>
		  </td>
	      </tr>\n";
    }
502 503 504 505

    #
    # Path to image.
    #
506 507
    $style = ($isadmin ? "" : "style='display:none;'");
    echo "<tr $style>
Leigh B Stoller's avatar
Leigh B Stoller committed
508
              <td>Directory for Image:<br>
509
                  (must reside in $TBPROJ_DIR)</td>
510 511 512
              <td class=left>
                  <input type=text
                         name=\"formfields[path]\"
513
                         value=\"" . $formfields["path"] . "\"
514 515 516 517
	                 size=50>
              </td>
          </tr>\n";

Chad Barb's avatar
 
Chad Barb committed
518
    #
Chad Barb's avatar
 
Chad Barb committed
519
    # Node to Snapshot image from.
Chad Barb's avatar
 
Chad Barb committed
520
    #
521 522 523 524 525 526 527 528 529 530 531 532
    if ($ec2) {
	echo "<tr>
		  <td>EC2 User@Node Info:</td>
		  <td class=left>
		      <input type=text
			     name=\"formfields[ec2_info]\"
			     value=\"" . $formfields["ec2_info"] . "\"
			     size=64>
		  </td>
	      </tr>\n";
    }
    elseif (isset($view["hide_snapshot"])) {
533 534 535 536 537 538
	spithidden($formfields, 'node');
    } else {
	echo "<tr>
		  <td>Node to Obtain Snapshot from[<b>2</b>]:</td>
		  <td class=left>
		      <input type=text
539 540
			     name=\"formfields[node_id]\"
			     value=\"" . $formfields["node_id"] . "\"
541 542 543 544
			     size=$TBDB_NODEIDLEN maxlength=$TBDB_NODEIDLEN>
		  </td>
	      </tr>\n";
    }
545
    
Chad Barb's avatar
 
Chad Barb committed
546

547 548 549
    #
    # OS Features.
    # 
550
    if (isset($view["hide_features"])) {
551 552 553 554 555 556 557 558
        reset($osid_featurelist);
        while (list ($feature, $userokay) = each($osid_featurelist)) {
            spithidden($formfields, "os_feature_$feature");
        }
    } else {
	echo "<tr>
		  <td>OS Features[<b>3</b>]:</td>
		  <td>";
559

560 561 562 563 564 565
	reset($osid_featurelist);
	while (list ($feature, $userokay) = each($osid_featurelist)) {
	    $checked = "";
	    
	    if (!$userokay && !$isadmin)
		continue;
566

567 568 569
	    if (isset($formfields["os_feature_$feature"]) &&
		! strcmp($formfields["os_feature_$feature"], "checked"))
		$checked = "checked";
570

571 572 573 574 575 576
	    echo "<input $checked type=checkbox value=checked
			 name=\"formfields[os_feature_$feature]\">
		       $feature &nbsp\n";
	}
	echo "    </td>
	      </tr>\n";
577 578
    }

579 580 581
    #
    # Operational Mode
    # 
582
    if (isset($view["hide_opmode"])) {
583 584 585 586 587 588
	spithidden($formfields, 'op_mode');
    } else {
	echo "<tr>
		 <td>*Operational Mode[<b>4</b>]:</td>
		 <td><select name=\"formfields[op_mode]\">
		       <option value=none>Please Select </option>\n";
589

590 591
	while (list ($mode, $userokay) = each($osid_opmodes)) {
	    $selected = "";
592

593 594
	    if (!$userokay && !$isadmin)
		continue;
595

596 597
	    if (isset($formfields["op_mode"]) &&
		strcmp($formfields["op_mode"], $mode) == 0)
598
		$selected = "selected";
599

600
	    echo "<option $selected value=$mode>$mode &nbsp; </option>\n";
601 602 603 604
	}
	echo "       </select>
		 </td>
	      </tr>\n";
605 606
    }

607 608 609
    #
    # Node Types.
    #
610
    if (!isset($view["hide_footnotes"])) {
611
	$footnote = "[<b>5</b>]";
612 613
    } else {
	$footnote = "";
614
    }
615
    echo "<tr>
616
              <td>Node Types${footnote}:</td>
617 618
              <td>\n";

619
    foreach ($types_list as $type => $value) {
620 621
        $checked = "";

622 623 624 625
        if ((isset($formfields["mtype_$type"]) &&
	     $formfields["mtype_$type"] == "Yep") ||
	    (isset($formfields["mtype_all"]) &&
	     $formfields["mtype_all"] == "Yep")) {
626
	    $checked = "checked";
627
	}
628 629 630 631 632 633 634 635 636
    
        echo "<input $checked type=checkbox
                     value=Yep name=\"formfields[mtype_$type]\">
                     $type &nbsp
              </input>\n";
    }
    echo "    </td>
          </tr>\n";

637 638 639
    #
    # Whole Disk Image
    #
640
    if (isset($view["hide_wholedisk"]) && $view["hide_wholedisk"]) {
641 642 643 644 645 646 647 648 649
	spithidden($formfields, 'wholedisk');
    } else {
	echo "<tr>
		  <td>Whole Disk Image?[<b>6</b>]:</td>
		  <td class=left>
		      <input type=checkbox
			     name=\"formfields[wholedisk]\"
			     value=Yep";

650 651
	if (isset($formfields["wholedisk"]) &&
	    strcmp($formfields["wholedisk"], "Yep") == 0)
652 653 654 655 656 657
	    echo "           checked";
	    
	echo "                       > Yes
		  </td>
	      </tr>\n";
    }
658 659 660 661

    #
    # Maxiumum concurrent loads
    #
662
    if (isset($view["hide_concurrent"])) {
663 664 665 666 667 668 669
	spithidden($formfields, 'max_concurrent');
    } else {
	echo "<tr>
		  <td>Maximum concurrent loads[<b>7</b>]:</td>
		  <td class=left>
		      <input type=text
			     name=\"formfields[max_concurrent]\"
670
			     value=\"" . $formfields["max_concurrent"] . "\"
671 672 673
			     size=4 maxlength=4>
		  </td>
	      </tr>\n";
674

675
    }
676

677 678 679 680
    if (isset($view["hide_mbr"])) {
	spithidden($formfields, 'mbr_version');
    }
    else {
681 682 683 684 685 686 687 688 689 690 691
	echo "<tr>
	          <td>MBR Version:<br>
		  <td class=left>
		      <input type=text
			     name=\"formfields[mbr_version]\"
			     value=\"" . $formfields["mbr_version"] . "\"
			     size= maxlength=2>
		  </td>
	      </tr>\n";
    }

692 693 694
    #
    # Shared?
    #
695
    if (isset($view["hide_snapshot"])) {
696 697 698 699 700 701 702 703 704 705 706
	spithidden($formfields, 'shared');
    } else {
	echo "<tr>
		  <td>Shared?:<br>
		      (available to all subgroups)</td>
		  <td class=left>
		      <input type=checkbox
			     onClick='SetPrefix(idform);'
			     name=\"formfields[shared]\"
			     value=Yep";

707 708
	if (isset($formfields["shared"]) &&
	    strcmp($formfields["shared"], "Yep") == 0)
709 710 711 712 713 714 715 716 717 718
	    echo "           checked";
	    
	echo "                       > Yes
		  </td>
	      </tr>\n";
    }

    #
    # Upload an image file
    #
719 720 721 722
    if (isset($view["hide_upload"])) {
	;
    }
    else {
723 724 725 726 727 728 729 730 731
	echo "<tr>
		  <td>Upload a file:</td>
		  <td class=left>
		      <input type=file
			     name=\"upload_file\"
			     value=''
			     size=35></tr>";

    }
732

733 734
    if ($isadmin) {
        #
735
        # Global?
736 737
        #
	echo "<tr>
738
  	          <td>Global?:<br>
739 740 741
                      (available to all projects)</td>
                  <td class=left>
                      <input type=checkbox
742 743
                             onClick='SetPrefix(idform);'
                             name=\"formfields[global]\"
744 745
                             value=Yep";

746 747
	if (isset($formfields["global"]) &&
	    strcmp($formfields["global"], "Yep") == 0)
748 749 750 751 752 753
	    echo "           checked";
	
	echo "                       > Yes
                  </td>
              </tr>\n";
    }
754 755 756
    #
    # Reboot waittime. 
    # 
757 758 759 760 761
    if (!isset($view["hide_footnotes"])) {
	$footnote = "[<b>8</b>]";
    } else {
	$footnote = "";
    }
762
    echo "<tr>
763
	      <td>Reboot Waittime (seconds)${footnote}:</td>
764 765 766 767 768 769 770
	      <td class=left>
		  <input type=text
		         name=\"formfields[reboot_waittime]\"
			 value=\"" . $formfields["reboot_waittime"] . "\"
			 size=4 maxlength=4>
   	      </td>
	  </tr>\n";
771

772 773 774 775 776 777 778 779 780 781 782 783 784
    if (isset($formfields["def_parentosid"]) &&
	$formfields["def_parentosid"] != "") {
	$osinfo = OSInfo::Lookup($formfields["def_parentosid"]);
	$osname = $osinfo->osname();
	$url    = CreateURL("showosinfo", $osinfo);

	echo "<tr>
	          <td>Parent OS:</td> 
		  <input type=hidden
		         name=\"formfields[def_parentosid]\"
			 value=\"" . $formfields["def_parentosid"] . "\">
  	          <td class=left><a href='$url'>$osname</a></td>
	  </tr>\n";
785

786 787 788 789 790 791 792 793 794 795 796
	if ($ec2) {
	    echo "<tr>
	  	    <td>Package:</td>
		    <td class=left>
		        <input type=checkbox
		  	       name=\"formfields[package]\"
			       value=Yep";

	    if (isset($formfields["package"]) &&
		strcmp($formfields["package"], "Yep") == 0)
		echo "           checked";
797
	    
798
	    echo "         > Yes (XEN only, and only if you know what this means!)
799 800
		  </td>
	      </tr>\n";
801
	}
802 803
    }

804 805 806 807 808 809 810 811 812
    echo "<tr>
              <td align=center colspan=2>
                  <b><input type=submit name=submit value=Submit></b>
              </td>
          </tr>\n";

    echo "</form>
          </table>\n";

813 814 815 816 817 818
    if (isset($view["hide_footnotes"])) {
	echo "<center><blockquote>
	      <b>In general, you should leave the default settings alone!</b>
              </blockquote></center>\n";
    }
    else {
819
	echo "<blockquote>
820 821 822 823 824
	      <ol type=1 start=1>
		 <li> If you don't know what partition you have customized,
		      here are some guidelines:
		     <ul>
			<li> if you customized one of our standard Linux
825 826
                             (RHL*) or Fedora images (FC*) then it is
                             partition 2.
827 828
			</li>
			<li> if you customized one of our standard BSD
829
			     images (FBSD*) then it is partition 1.
830
			</li>
Russ Fish's avatar
Russ Fish committed
831
			<li> if you customized one of our standard Windows XP
832 833 834
			     images then it is partition 1, and make sure
                             you check the <em>Whole Disk Image</em> box.
			</li>
835 836 837 838 839 840 841 842 843 844 845 846 847 848
			<li> otherwise, feel free to ask us!
			</li>
		     </ul>
		 </li>
		 <li> If you already have a node customized, enter that node
		      name (pcXXX) and a snapshot will automatically be made of
		      its disk contents into the specified Image File. 
		      Notification of completion will be sent to you via email. 
		 </li>
		 <li> Guidelines for setting OS features for your OS:
		      (Most images should mark all four of these.)
		    <ul>
		      <li> Mark ping and/or ssh if they are supported. 
		      </li>
849 850 851
		      <li> If you use one of our standard Linux, Fedora or
                           FreeBSD kernels, or started from our kernel
                           configs, mark ipod.
Russ Fish's avatar
Russ Fish committed
852
			   ipod is not supported on Windows XP.
853
		      </li>
854
		      <li> If it is based on one of our standard Linux, Fedora,
Russ Fish's avatar
Russ Fish committed
855
			   FreeBSD, or Windows XP images (or otherwise
856
			   sends its own ISUP notification), mark isup.
Leigh B. Stoller's avatar
Leigh B. Stoller committed
857
                      </li>
858
		      <li> If it is based on one of our standard Linux, Fedora,
Leigh B. Stoller's avatar
Leigh B. Stoller committed
859
			   FreeBSD, or Windows XP images, mark linktest.
860
		      </li>
861 862 863 864 865 866
		      <li> If it is based on an image with
			   <a href=$WIKIDOCURL/EmulabStorage#section-9>
			   blockstore support</a>, then mark the loc-bstore
			   and/or rem-bstore checkboxes (indicating local
			   and remote blockstore support, respectively).
		      </li>
867 868 869 870 871 872
		    </ul>
		 </li>
		 <li> Guidelines for setting Operational Mode for your OS:
		      (Most images should use " . TBDB_DEFAULT_OSID_OPMODE . ")
		    <ul>
		      <li> If it is based on a testbed image (one of our
873 874 875
			   Linux, Fedora, FreeBSD, or Windows XP images)
                           use the same op_mode as that image.
                           Select it from the
876 877 878 879 880 881 882 883 884
			   <a href=\"$TBBASE/showosid_list.php3\"
			   >OS Descriptor List</a> to find out).
		      </li>
		      <li> If not, use MINIMAL. 
		      </li>
		    </ul>
		 </li>
		 <li> Specify the node types that this image will be able
		      to work on (can be loaded on and expected to work).
885 886 887 888 889 890 891 892 893 894 895 896
		      Typically, images of newer OS versions will work on all
		      of the \"pc\" types.  However, older versions of OSes
		      may only work on the older hardware types (pc600, pc850,
		      pc2000).  To make this type selection process easier,
		      when you take a snapshot of an existing node that you
		      have customized (see 2. above), the system will restrict
		      the types to those allowed for the \"base\" image (the
		      one originally loaded, that you have customized).  If
		      you need to override this restriction and add a type
		      that is not allowed in the current image, you will have
		      to contact us.  If you have any questions, free to ask
		      us!
897 898 899 900 901 902 903 904
		 </li>
		 <li> If you need to snapshot the entire disk (including the MBR),
		      check this option. <b>Most users will not need to check this
		      option. Please ask us first to make sure</b>.
		 </li>
		 <li> If your image contains software that is only licensed to run
		      on a limited number of nodes at a time, you can put this
		      number here. Most users will want to leave this option blank.
905 906 907 908 909
                 </li>
		 <li> Leave this field <b>blank</b> unless you know what you
                      are doing, or you have an explicit problem with images
                      taking too long to boot. <b>Please talk to us first!</b>
                 </li>
910
	      </ol>
911
	      </blockquote>\n";
912 913 914 915 916 917 918 919 920 921 922 923
    }
}

#
# If the given field is defined in the given set of fields, spit out a hidden
# form element for it
#
function spithidden($formfields, $field) {
    if (isset($formfields[$field])) {
	echo "<input type=hidden name=formfields[$field] value='" .
	     $formfields[$field] . "'>\n";
    }
924 925 926 927 928
}

#
# On first load, display a virgin form and exit.
#
929
if (!isset($submit)) {
930
    $defaults = array();
931 932 933 934 935
    $defaults["pid"]		 = "";
    $defaults["gid"]		 = "";
    $defaults["imagename"]	 = "";
    $defaults["description"]	 = "";
    $defaults["path"]		 = "$TBPROJ_DIR/";
936
    $defaults["node_id"]	 = (isset($node) ? $node->node_id() : "");
937 938 939
    $defaults["max_concurrent"]	 = "";
    $defaults["shared"]		 = "No";
    $defaults["global"]		 = "No";
940 941 942
    $defaults["OS"]	 	 = "";
    $defaults["version"]	 = "";
    $defaults["wholedisk"]	 = "No";
943
    $defaults["reboot_waittime"] = "";
944
    $defaults["mbr_version"]     = "";
945
    $defaults["noexport"]        = "No";
946

947 948 949 950
    #
    # Use the base image to seed the form.
    #
    if (isset($baseimage)) {
951
	$baseosinfo = $baseimage->OSinfo();
952 953 954 955 956 957
	if (! $baseosinfo) {
	    TBERROR("Could not lookup osinfo object for image " .
		    $baseimage->imageid(), 1);
	}
	$defaults["loadpart"]    = $baseimage->loadpart();
	if ($baseimage->loadpart() == 0 && $baseimage->loadlength() == 4) {
958 959
	    $loadpart = ($baseimage->part1_osid() ? 1 : 2);
	    $defaults["loadpart"]    = $loadpart;
960 961 962
	    $defaults["wholedisk"]   = "Yep";
	}
	$defaults["mbr_version"]     = $baseimage->mbr_version();
963
	$defaults["noexport"]        = ($baseimage->noexport() ? "Yes" : "No");
964 965 966 967 968 969 970
	#
	# Same types as the parent.
	#
	foreach ($baseimage->Types() as $type) {
	    $defaults["mtype_${type}"] = "Yep";
	}
    }
971
    elseif (isset($imagetype) && $imagetype == "openvz") {
972 973
	$defaults["loadpart"]    = "1";
	$defaults["wholedisk"]   = "Yep";
974
	$defaults["mtype_pcvm"]  = "Yep";
975
    }
976
    else {
977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998
	# Defaults for PC-type nodes
	$defaults["loadpart"] = "X";
	# mtype_all is a "fake" variable which makes all
	# mtypes checked in the virgin form.
	$defaults["mtype_all"] = "Yep";
    }
    
    if (isset($baseosinfo)) {
	#
	# Same features as the parent.
	#
	if ($baseosinfo->osfeatures()) {
	    foreach (preg_split("/,/", $baseosinfo->osfeatures()) as $feature) {
		$defaults["os_feature_${feature}"] = "checked";
	    }
	}
	$defaults["reboot_waittime"] = $baseosinfo->reboot_waittime();
	$defaults["OS"]	 	     = $baseosinfo->OS();
	$defaults["version"]	     = $baseosinfo->version();
	$defaults["op_mode"]         = $baseosinfo->op_mode();
	$defaults["description"]     = "Copy of " . $baseosinfo->osname();

Leigh B Stoller's avatar
Leigh B Stoller committed
999 1000 1001 1002 1003 1004 1005
	if ($baseosinfo->def_parentosid()) {
	    $def_parentosinfo = OSinfo::Lookup($baseosinfo->def_parentosid());
	    if (! $def_parentosinfo) {
		TBERROR("Could not lookup osinfo object for parent " .
			$baseosinfo->def_parentosid(), 1);
	    }
	    $defaults["def_parentosid"]   = $def_parentosinfo->osid();
1006 1007
	}
    }
1008 1009
    elseif (isset($imagetype) && $imagetype == "openvz") {
	$defaults["op_mode"]             = TBDB_PCVM_OPMODE;
1010 1011 1012
	$defaults["reboot_waittime"]     = "240";
	$defaults["os_feature_ping"]	 = "checked";
	$defaults["os_feature_ssh"]	 = "checked";
1013 1014
	$defaults["os_feature_isup"]	 = "checked";
	$defaults["os_feature_linktest"] = "checked";
1015
	$defaults["package"]             = "No";
1016

1017 1018 1019 1020 1021 1022 1023
	#
        # XXX Need to fix this.
        # 
	$def_parentosinfo = OSinfo::LookupByName("emulab-ops",
						 "FEDORA15-OPENVZ-STD");
	if (! $def_parentosinfo) {
	    TBERROR("Could not lookup osinfo object for FEDORA15-OPENVZ-STD",1);
1024
	}
1025 1026 1027 1028 1029 1030
	$defaults["def_parentosid"]   = $def_parentosinfo->osid();
    }
    elseif (isset($imagetype) && $imagetype == "xen") {
	#
        # XXX Need to fix this.
        # 
1031
	$def_parentosinfo = OSinfo::LookupByName("emulab-ops", "XEN43-64-STD");
1032
	if (! $def_parentosinfo) {
1033 1034 1035
	    $def_parentosinfo = OSinfo::LookupByName("emulab-ops",
						     "XEN41-64-STD");
	    TBERROR("Could not lookup osinfo object for XEN image", 1);
1036 1037
	}
	$defaults["def_parentosid"]   = $def_parentosinfo->osid();
1038 1039

	if ($ec2) {
1040 1041 1042
	    $defaults["package"]  = "Yep";
	    $defaults["op_mode"]  = TBDB_ALWAYSUP_OPMODE;
	    $defaults["loadpart"] = 2;
1043
	}
1044 1045 1046 1047 1048
	else {
	    $defaults["os_feature_ipod"]	 = "checked";
	    $defaults["os_feature_isup"]	 = "checked";
	    $defaults["os_feature_linktest"]     = "checked";
	}
1049 1050 1051
	$defaults["reboot_waittime"]     = "240";
	$defaults["os_feature_ping"]	 = "checked";
	$defaults["os_feature_ssh"]	 = "checked";
1052
    }
1053
    else {
Russ Fish's avatar
Russ Fish committed
1054
	# Defaults for PC-type nodes
1055
	$defaults["op_mode"]  = TBDB_DEFAULT_OSID_OPMODE;
1056 1057 1058 1059
	$defaults["os_feature_ping"]	 = "checked";
	$defaults["os_feature_ssh"]	 = "checked";
	$defaults["os_feature_ipod"]	 = "checked";
	$defaults["os_feature_isup"]	 = "checked";
1060
	$defaults["os_feature_linktest"] = "checked";
1061
    }
Chad Barb's avatar
 
Chad Barb committed
1062

1063 1064 1065
    #
    # For users that are in one project and one subgroup, it is usually
    # the case that they should use the subgroup, and since they also tend
1066
    # to be in the naive portion of our users, give them some help.
1067 1068 1069
    # 
    if (count($projlist) == 1) {
	list($project, $grouplist) = each($projlist);
1070

1071
	if (count($grouplist) <= 2) {
1072
	    $defaults["pid"] = $project;
1073 1074 1075 1076 1077
	    if (count($grouplist) == 1 || strcmp($project, $grouplist[0]))
		$group = $grouplist[0];
	    else {
		$group = $grouplist[1];
	    }
1078
	    $defaults["gid"] = $group;
1079 1080
	    
	    if (!strcmp($project, $group))
1081
		$defaults["path"]     = "$TBPROJ_DIR/$project/images/";
1082
	    else
1083
		$defaults["path"]     = "$TBGROUP_DIR/$project/$group/images/";
1084 1085 1086
	}
	reset($projlist);
    }
1087 1088 1089 1090 1091 1092 1093 1094 1095 1096
    elseif (isset($node)) {
	#
	# Use the current pid/eid of the experiment the node is in.
	#
	$experiment = $node->Reservation();
	if ($experiment) {
	    $defaults["pid"] = $experiment->pid();
	    $defaults["gid"] = $experiment->gid();
	}
    }
1097 1098

    #
1099
    # Allow formfields that are already set to override defaults.
1100 1101 1102 1103 1104 1105 1106
    #
    if (isset($formfields)) {
	while (list ($field, $value) = each ($formfields)) {
	    $defaults[$field] = $formfields[$field];
	}
    }

1107 1108 1109 1110 1111 1112 1113 1114
    SPITFORM($defaults, 0);
    PAGEFOOTER();
    return;
}

#
# Otherwise, must validate and redisplay if errors
#
1115
$errors  = array();
1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147

# Be friendly about the required form field names.
if (!isset($formfields["imagename"]) ||
    strcmp($formfields["imagename"], "") == 0) {
    $errors["Descriptor Name"] = "Missing Field";
}

if (!isset($formfields["description"]) ||
    strcmp($formfields["description"], "") == 0) {
    $errors["Descriptor Name"] = "Missing Field";
}

if (!isset($formfields["loadpart"]) ||
    strcmp($formfields["loadpart"], "X") == 0) {
    $errors["Starting DOS Partion"] = "Missing Field";
}

if (!isset($formfields["OS"]) ||
    strcmp($formfields["OS"], "X") == 0) {
    $errors["Operating System"] = "Missing Field";
}

if (!isset($formfields["version"]) ||
    strcmp($formfields["version"], "X") == 0) {
    $errors["Operating System"] = "Missing Field";
}

if (!isset($formfields["op_mode"]) ||
    strcmp($formfields["op_mode"], "none") == 0) {
    $errors["Operational Mode"] = "Missing Field";
}

1148 1149
$project = null;
$group   = null;
1150 1151 1152

#
# Project:
1153 1154 1155
#
if (!isset($formfields["pid"]) ||
    strcmp($formfields["pid"], "") == 0) {
1156 1157
    $errors["Project"] = "Not Selected";
}
1158 1159
elseif (!TBvalid_pid($formfields["pid"])) {
    $errors["Project"] = "Invalid project name";
1160
}
1161 1162 1163 1164 1165 1166 1167 1168 1169 1170
elseif (! ($project = Project::Lookup($formfields["pid"]))) {
    $errors["Project"] = "Invalid project name";
}

if (isset($formfields["gid"]) && $formfields["gid"] != "") {
    if ($formfields["pid"] == $formfields["gid"] && $project) {
	$group = $project->DefaultGroup();
    }
    elseif (!TBvalid_gid($formfields["gid"])) {
	$errors["Group"] = "Invalid group name";
1171
    }
1172 1173 1174
    elseif ($project &&
	    ! ($group = $project->LookupSubgroupByName($formfields["gid"]))) {
	$errors["Group"] = "Invalid group name";
1175 1176
    }
}
1177 1178
elseif ($project) {
    $group = $project->DefaultGroup();
1179 1180
}

1181 1182 1183 1184 1185
# Permission check if we managed to get a proper group above.
if ($group &&
    ! $group->AccessCheck($this_user, $TB_PROJECT_MAKEIMAGEID)) {
    $errors["Project"] = "Not enough permission";
}
1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198

#
# EC2 Checks
#
if ($ec2) {
    if (!isset($formfields["ec2_info"]) ||
	strcmp($formfields["ec2_info"], "") == 0) {
	$errors["EC2 Info"] = "Missing Field";
    }
    if (!preg_match("/^[-\w\@\.\+]+$/", $formfields["ec2_info"])) {
	$errors["EC2 Info"] = "Illegal characters";
    }
}
1199
 
1200
#
1201
# Build up argument array to pass along.
1202
#
1203 1204
$args = array();

1205 1206 1207 1208 1209 1210 1211
# Ignore the form for this ...
if (isset($formfields["def_parentosid"]) &&
    $formfields["def_parentosid"] != "") {
    $osinfo = OSinfo::Lookup($formfields["def_parentosid"]);
    $args["def_parentosid"] = $osinfo->pid() . "," . $osinfo->osname();
}

1212 1213
if (isset($formfields["pid"]) && $formfields["pid"] != "") {
    $args["pid"] = $pid = $formfields["pid"];
1214 1215
}

1216 1217
if (isset($formfields["gid"]) && $formfields["gid"] != "") {
    $args["gid"] = $gid = $formfields["gid"];
1218
}
1219 1220 1221

if (isset($formfields["imagename"]) && $formfields["imagename"] != "") {
    $args["imagename"] = $imaganame = $formfields["imagename"];
1222 1223
}

1224 1225
if (isset($formfields["description"]) && $formfields["description"] != "") {
    $args["description"] = $formfields["description"];
1226
}
1227 1228

if (isset($formfields["loadpart"]) &&
Russ Fish's avatar
Russ Fish committed
1229
    $formfields["loadpart"] != "X" && $formfields["loadpart"] != "") {
1230
    $args["loadpart"] = $formfields["loadpart"];
1231
}
1232 1233 1234 1235

if (isset($formfields["OS"]) &&
    $formfields["OS"] != "none" && $formfields["OS"] != "") {
    $args["OS"] = $formfields["OS"];
1236
}
1237 1238 1239

if (isset($formfields["version"]) && $formfields["version"] != "") {
    $args["version"]	= $formfields["version"];
1240
}
1241

1242 1243
if (isset($formfields["path"]) && $formfields["path"] != "") {
    $args["path"] = $formfields["path"];
1244
}
1245 1246 1247

if (isset($formfields["node_id"]) && $formfields["node_id"] != "") {
    $args["node_id"] = $formfields["node_id"];
1248 1249
}

1250 1251
if (isset($formfields["op_mode"]) && $formfields["op_mode"] != "") {
    $args["op_mode"] = $formfields["op_mode"];
1252 1253
}

1254 1255 1256
# Filter booleans from checkboxes to 0 or 1.
if (isset($formfields["wholedisk"])) {
   $args["wholedisk"] = strcmp($formfields["wholedisk"], "Yep") ? 0 : 1;
1257
}
1258