newimageid_ez.php3 42.3 KB
Newer Older
1
<?php
Leigh B. Stoller's avatar
Leigh B. Stoller committed
2
#
3
# Copyright (c) 2000-2012 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
#
# Only known and logged in users.
#
$this_user = CheckLoginOrDie();
$uid       = $this_user->uid();
$dbid      = $this_user->dbid();
$isadmin   = ISADMIN();

45
46
47
# This will not return if its a sajax request.
include("showlogfile_sup.php3");

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

61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#
# If starting from a specific node we can derive the type and possibly
# the baseimage from it. 
#
if (isset($node)) {
    $nodetype   = $node->type();
    
    #
    # 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.
    #
    $baseimage = Image::Lookup($node->def_boot_osid());
    #
    # Try for at least an osinfo if no image.
    #
    if (! $baseimage) {
	$baseosinfo = OSinfo::Lookup($node->def_boot_osid());
    }
}

82
#
83
84
85
# Options for using this page with different types of nodes.
# nodetype controls the view and trumps nodeclass.
# nodeclass determines what node types are visible from the DB.
86
#
87
88
89
90
91
92
93
94
95
96
97
98
99
if (isset($nodetype) && $nodetype == "pcvm") {
    $title = "PCVM Form";
    $nodeclass = "pcvm";
    # Default to imagezip ndz files
    $filename_extension = "ndz";
    $view = array('hide_partition' => 1,
		  'hide_upload' => 1,
		  'hide_mbr' => 1,
		  'hide_concurrent' => 1,
		  'hide_footnotes' => 1,
		  'hide_wholedisk' => 1);
}
elseif (isset($nodetype) && $nodetype == "mote") {
100
    $view = array('hide_partition' => 1, 'hide_os' => 1, 'hide_version' => 1,
101
102
103
104
		  'hide_snapshot' => 1,
		  'hide_concurrent' => 1,
		  'hide_wholedisk' => 1,
		  'hide_features' => 1,
105
106
107
		  'hide_opmode' => 1, 'hide_footnotes' => 1);
    $nodeclass = "mote";
    $title = "Mote Form";
108
109
    $help_message = 
          "See the
110
          <a href=\"$WIKIDOCURL/emotes#PROGRAMMING\">
111
112
          mote documentation</a> for more info on creating/using custom
          mote images.";
113
114
    # Default to 'srec' files for use with uisp
    $filename_extension = "srec";
115
} else {
116
    # Defaults to PC view.
117
    $view = array('hide_upload' => 1);
118
119
    if (!isset($nodeclass)) 
	$nodeclass = "pc";
120
121
122
123
    else {
	if (! preg_match("/^[-\w]*$/", $nodeclass)) {
	    PAGEARGERROR("Invalid characters in $nodeclass");
	}
124
	$nodeclass = addslashes($nodeclass);
125
126
127
128
129
130
    }
    if (isset($nodetype)) {
	if (! preg_match("/^[-\w]*$/", $nodetype)) {
	    PAGEARGERROR("Invalid characters in $nodetype");
	}
    }
131
    $title = "EZ Form";
132
133
    $help_message = 
          "See the
134
          <a href=$WIKIDOCURL/Tutorial#CustomOS>
135
          tutorial</a> for more info on creating/using custom Images.";
136
137
    # Default to imagezip ndz files
    $filename_extension = "ndz";
138
}
139
140
141
142
143
144
#
# If we are lucky enough to get a baseimage, do not show footnotes.
#
if (isset($baseimage)) {
    $view['hide_footnotes'] = 1;
}
145

146
147
148
#
# Standard Testbed Header
#
149
PAGEHEADER("Create a new Image Descriptor ($title)");
150
151
152
153

#
# See what projects the uid can do this in.
#
154
$projlist = $this_user->ProjectAccessList($TB_PROJECT_MAKEIMAGEID);
155
156
157
158
159
160
161

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

#
162
163
# Need a list of node types. We join this over the nodes table so that
# we get a list of just the nodes that currently in the testbed, not
164
# just in the node_types table. Limit by class if given.
165
#
166
$types_querystring = "select distinct n.type from nodes as n ".
167
168
169
    "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 ".
170
    "      a.attrvalue!='0' and n.role='testnode'";
171

172
if ($nodeclass) {
173
174
175
176
177
178
179
    if ($nodeclass == "pcvm") {
	$types_querystring = "select distinct type from node_types ".
	    "where type='pcvm'";
    }
    else {
	$types_querystring .= " and nt.class='$nodeclass' ";
    }
180
181
182
}

$types_result = DBQueryFatal($types_querystring);
183
184

#
185
186
# Spit the form out using the array of data.
#
187
188
function SPITFORM($formfields, $errors)
{
189
190
    global $projlist, $isadmin, $types_result, $osid_oslist, $osid_opmodes,
	$osid_featurelist, $nodetype, $filename_extension, $help_message;
191
    global $nodeclass, $node;
192
    global $TBDB_OSID_OSNAMELEN, $TBDB_NODEIDLEN;
193
    global $TBDB_OSID_VERSLEN, $TBBASE, $TBPROJ_DIR, $TBGROUP_DIR;
194
    global $view;
195
    
196
197
198
    #
    # 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
199
    # of nodes. It's an associative array, with contents like:'hide_partition'.
200
201
202
    # In general, when an option is hidden, it is replaced with a hidden
    # field from $formfields
    #
203
204
205
    if ($help_message) {
        echo "<center><b>$help_message</b></center>\n";
    }
206
207
208
209
210
211
212

    if ($isadmin) {
	echo "<center>
               Administrators get to use the
               <a href='newimageid.php3'>long form</a>.
              </center>\n";
    }
213
214
    
    if ($errors) {
Chad Barb's avatar
   
Chad Barb committed
215
216
	echo "<table class=nogrid
                     align=center border=0 cellpadding=6 cellspacing=0>
217
              <tr>
Chad Barb's avatar
   
Chad Barb committed
218
                 <th align=center colspan=2>
219
                   <font size=+1 color=red>
Chad Barb's avatar
   
Chad Barb committed
220
                      &nbsp;Oops, please fix the following errors!&nbsp;
221
222
223
224
225
                   </font>
                 </td>
              </tr>\n";

	while (list ($name, $message) = each ($errors)) {
226
227
            # XSS prevention.
	    $message = CleanString($message);
228
	    echo "<tr>
Chad Barb's avatar
   
Chad Barb committed
229
230
231
232
                     <td align=right>
                       <font color=red>$name:&nbsp;</font></td>
                     <td align=left>
                       <font color=red>$message</font></td>
233
234
235
236
                  </tr>\n";
	}
	echo "</table><br>\n";
    }
237
238
239
240
    # XSS prevention.
    while (list ($key, $val) = each ($formfields)) {
	$formfields[$key] = CleanString($val);
    }
241
242
243
244

    echo "<SCRIPT LANGUAGE=JavaScript>
              function SetPrefix(theform) 
              {
245
246
247
248
                  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;
249
                  var shared = theform['formfields[shared]'].checked;
250
251
252
253
254
255
256
          \n";
    if ($isadmin)
	echo     "var global = theform['formfields[global]'].checked;";
    else
	echo     "var global = 0;";

    echo         "if (pid == '') {
257
                      theform['formfields[path]'].value = '$TBPROJ_DIR';
258
259
260
                  }
                  else if (theform['formfields[imagename]'].value == '') {
		      theform['formfields[imagename]'].defaultValue = '';
261
262
263
264
265
266
267

                      if (global) {
    	                  theform['formfields[path]'].value =
                                  '/usr/testbed/images/';
                      }
		      else if (gid == '' || gid == pid || shared) {
    	                  theform['formfields[path]'].value =
268
                                  '$TBPROJ_DIR/' + pid + '/images/';
269
270
271
                      }
                      else {
    	                  theform['formfields[path]'].value =
272
                                  '$TBGROUP_DIR/' + pid + '/' + gid + '/images/';
273
                      }
274
275
                  }
                  else if (theform['formfields[imagename]'].value != '') {
276
                      var filename = theform['formfields[imagename]'].value +
277
                                     '.$filename_extension';
278
279
280
281
282
283
284

                      if (global) {
    	                  theform['formfields[path]'].value =
                                  '/usr/testbed/images/' + filename;
                      }
		      else if (gid == '' || gid == pid || shared) {
    	                  theform['formfields[path]'].value =
285
                                  '$TBPROJ_DIR/' + pid + '/images/' + filename;
286
287
288
                      }
                      else {
    	                  theform['formfields[path]'].value =
289
                                  '$TBGROUP_DIR/' + pid + '/' + gid + '/images/' +
290
291
                                  filename;
                      }
292
293
294
295
296
297
298
299
300
301
302
                  }
              }
          </SCRIPT>\n";

    echo "<br>
          <table align=center border=1> 
          <tr>
             <td align=center colspan=2>
                 <em>(Fields marked with * are required)</em>
             </td>
          </tr>
303
304
305
306
307
308
309
310
311
          <form action='newimageid_ez.php3' enctype=\"multipart/form-data\"
              method=post name=idform>\n";

    #
    # Carry along the nodetype variable - have to do it here, so that's inside
    # the form
    #
    if (isset($nodetype)) {
	echo "<input type=hidden name=nodetype value='$nodetype'>";
312

313
    }
314
    elseif (isset($nodeclass)) {
315
	echo "<input type=hidden name=nodeclass value='$nodeclass'>";
316
    }
317
318
319
320
    if (isset($node)) {
	$id = $node->node_id();
	echo "<input type=hidden name=node_id value='$id'>";
    }
321
322
323
324
325
326
327
328
329
330
331
332
333

    #
    # 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 = "";

334
	if ($formfields["pid"] == $project)
335
336
337
338
339
340
341
342
	    $selected = "selected";
	
	echo "        <option $selected value='$project'>$project </option>\n";
    }
    echo "       </select>";
    echo "    </td>
          </tr>\n";

343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
    #
    # 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 = "";

360
361
362
363
		if (isset($formfields["gid"]) &&
		    isset($formfields["pid"]) &&
		    strcmp($formfields["pid"], $project) == 0 &&
		    strcmp($formfields["gid"], $group) == 0)
364
365
366
367
368
369
370
371
372
373
374
		    $selected = "selected";
		
		echo "<option $selected value=\"$group\">
                           $project/$group</option>\n";
	    }
	}
    }
    echo "     </select>
             </td>
          </tr>\n";

375
    #
376
    # Image Name
377
378
379
380
381
382
383
    #
    echo "<tr>
              <td>*Descriptor Name (no blanks):</td>
              <td class=left>
                  <input type=text
                         onChange='SetPrefix(idform);'
                         name=\"formfields[imagename]\"
384
                         value=\"" . $formfields["imagename"] . "\"
385
386
	                 size=$TBDB_OSID_OSNAMELEN
                         maxlength=$TBDB_OSID_OSNAMELEN>
387
388
389
390
391
392
393
394
395
396
397
398
              </td>
          </tr>\n";

    #
    # Description
    #
    echo "<tr>
              <td>*Description:<br>
                  (a short pithy sentence)</td>
              <td class=left>
                  <input type=text
                         name=\"formfields[description]\"
399
                         value=\"" . $formfields["description"] . "\"
400
401
402
403
404
405
406
	                 size=50>
              </td>
          </tr>\n";

    #
    # Load Partition
    #
407
    if (isset($view["hide_partition"])) {
408
409
410
411
412
413
414
	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";
415

416
417
	for ($i = 1; $i <= 4; $i++) {
	    $selected = "";
418

419
	    if (strcmp($formfields["loadpart"], "$i") == 0)
420
		$selected = "selected";
Russ Fish's avatar
Russ Fish committed
421

422
423
424
425
426
	    echo "        <option $selected value=$i>$i </option>\n";
	}
	echo "       </select>";
	echo "    </td>
	      </tr>\n";
427
428
429
430
431
    }

    #
    # Select an OS
    # 
432
    if (isset($view["hide_os"])) {
433
	spithidden($formfields, 'OS');
434
435
436
437
    } else {
	echo "<tr>
		 <td>*Operating System:<br>
		    (OS that is on the partition)</td>
438
		 <td><select name=\"formfields[OS]\">
439
		       <option value=none>Please Select </option>\n";
440

441
442
	while (list ($os, $userokay) = each($osid_oslist)) {
	    $selected = "";
443

444
445
	    if (!$userokay && !$isadmin)
		continue;
446

447
448
	    if (isset($formfields["OS"]) &&
		strcmp($formfields["OS"], $os) == 0)
449
		$selected = "selected";
450

451
	    echo "<option $selected value=$os>$os &nbsp; </option>\n";
452
453
454
455
	}
	echo "       </select>
		 </td>
	      </tr>\n";
456
457
458
459
460
    }

    #
    # Version String
    #
461
    if (isset($view["hide_version"])) {
462
	spithidden($formfields, 'version');
463
464
465
466
467
468
    } else {
	echo "<tr>
		  <td>*OS Version:<br>
		      (eg: 4.3, 7.2, etc.)</td>
		  <td class=left>
		      <input type=text
469
470
			     name=\"formfields[version]\"
			     value=\"" . $formfields["version"] . "\"
471
472
473
474
475
			     size=$TBDB_OSID_VERSLEN
			     maxlength=$TBDB_OSID_VERSLEN>
		  </td>
	      </tr>\n";
    }
476
477
478
479
480
481

    #
    # Path to image.
    #
    echo "<tr>
              <td>Filename (full path) of Image:<br>
482
                  (must reside in $TBPROJ_DIR)</td>
483
484
485
              <td class=left>
                  <input type=text
                         name=\"formfields[path]\"
486
                         value=\"" . $formfields["path"] . "\"
487
488
489
490
	                 size=50>
              </td>
          </tr>\n";

Chad Barb's avatar
   
Chad Barb committed
491
    #
Chad Barb's avatar
   
Chad Barb committed
492
    # Node to Snapshot image from.
Chad Barb's avatar
   
Chad Barb committed
493
    #
494
    if (isset($view["hide_snapshot"])) {
495
496
497
498
499
500
	spithidden($formfields, 'node');
    } else {
	echo "<tr>
		  <td>Node to Obtain Snapshot from[<b>2</b>]:</td>
		  <td class=left>
		      <input type=text
501
502
			     name=\"formfields[node_id]\"
			     value=\"" . $formfields["node_id"] . "\"
503
504
505
506
			     size=$TBDB_NODEIDLEN maxlength=$TBDB_NODEIDLEN>
		  </td>
	      </tr>\n";
    }
Chad Barb's avatar
   
Chad Barb committed
507

508
509
510
    #
    # OS Features.
    # 
511
    if (isset($view["hide_features"])) {
512
513
514
515
516
517
518
519
        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>";
520

521
522
523
524
525
526
	reset($osid_featurelist);
	while (list ($feature, $userokay) = each($osid_featurelist)) {
	    $checked = "";
	    
	    if (!$userokay && !$isadmin)
		continue;
527

528
529
530
	    if (isset($formfields["os_feature_$feature"]) &&
		! strcmp($formfields["os_feature_$feature"], "checked"))
		$checked = "checked";
531

532
533
534
535
536
537
	    echo "<input $checked type=checkbox value=checked
			 name=\"formfields[os_feature_$feature]\">
		       $feature &nbsp\n";
	}
	echo "    </td>
	      </tr>\n";
538
539
    }

540
541
542
    #
    # Operational Mode
    # 
543
    if (isset($view["hide_opmode"])) {
544
545
546
547
548
549
	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";
550

551
552
	while (list ($mode, $userokay) = each($osid_opmodes)) {
	    $selected = "";
553

554
555
	    if (!$userokay && !$isadmin)
		continue;
556

557
558
	    if (isset($formfields["op_mode"]) &&
		strcmp($formfields["op_mode"], $mode) == 0)
559
		$selected = "selected";
560

561
	    echo "<option $selected value=$mode>$mode &nbsp; </option>\n";
562
563
564
565
	}
	echo "       </select>
		 </td>
	      </tr>\n";
566
567
    }

568
569
570
    #
    # Node Types.
    #
571
    if (!isset($view["hide_footnotes"])) {
572
	$footnote = "[<b>5</b>]";
573
574
    } else {
	$footnote = "";
575
    }
576
    echo "<tr>
577
              <td>Node Types${footnote}:</td>
578
579
580
581
              <td>\n";

    mysql_data_seek($types_result, 0);
    while ($row = mysql_fetch_array($types_result)) {
582
        $type    = $row["type"];
583
584
        $checked = "";

585
586
587
588
        if ((isset($formfields["mtype_$type"]) &&
	     $formfields["mtype_$type"] == "Yep") ||
	    (isset($formfields["mtype_all"]) &&
	     $formfields["mtype_all"] == "Yep")) {
589
	    $checked = "checked";
590
	}
591
592
593
594
595
596
597
598
599
    
        echo "<input $checked type=checkbox
                     value=Yep name=\"formfields[mtype_$type]\">
                     $type &nbsp
              </input>\n";
    }
    echo "    </td>
          </tr>\n";

600
601
602
    #
    # Whole Disk Image
    #
603
    if (isset($view["hide_wholedisk"])) {
604
605
606
607
608
609
610
611
612
	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";

613
614
	if (isset($formfields["wholedisk"]) &&
	    strcmp($formfields["wholedisk"], "Yep") == 0)
615
616
617
618
619
620
	    echo "           checked";
	    
	echo "                       > Yes
		  </td>
	      </tr>\n";
    }
621
622
623
624

    #
    # Maxiumum concurrent loads
    #
625
    if (isset($view["hide_concurrent"])) {
626
627
628
629
630
631
632
	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]\"
633
			     value=\"" . $formfields["max_concurrent"] . "\"
634
635
636
			     size=4 maxlength=4>
		  </td>
	      </tr>\n";
637

638
    }
639

640
641
642
643
    if (isset($view["hide_mbr"])) {
	spithidden($formfields, 'mbr_version');
    }
    else {
644
645
646
647
648
649
650
651
652
653
654
	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";
    }

655
656
657
    #
    # Shared?
    #
658
    if (isset($view["hide_snapshot"])) {
659
660
661
662
663
664
665
666
667
668
669
	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";

670
671
	if (isset($formfields["shared"]) &&
	    strcmp($formfields["shared"], "Yep") == 0)
672
673
674
675
676
677
678
679
680
681
	    echo "           checked";
	    
	echo "                       > Yes
		  </td>
	      </tr>\n";
    }

    #
    # Upload an image file
    #
682
683
684
685
    if (isset($view["hide_upload"])) {
	;
    }
    else {
686
687
688
689
690
691
692
693
694
	echo "<tr>
		  <td>Upload a file:</td>
		  <td class=left>
		      <input type=file
			     name=\"upload_file\"
			     value=''
			     size=35></tr>";

    }
695

696
697
    if ($isadmin) {
        #
698
        # Global?
699
700
        #
	echo "<tr>
701
  	          <td>Global?:<br>
702
703
704
                      (available to all projects)</td>
                  <td class=left>
                      <input type=checkbox
705
706
                             onClick='SetPrefix(idform);'
                             name=\"formfields[global]\"
707
708
                             value=Yep";

709
710
	if (isset($formfields["global"]) &&
	    strcmp($formfields["global"], "Yep") == 0)
711
712
713
714
715
716
	    echo "           checked";
	
	echo "                       > Yes
                  </td>
              </tr>\n";
    }
717
718
719
    #
    # Reboot waittime. 
    # 
720
721
722
723
724
    if (!isset($view["hide_footnotes"])) {
	$footnote = "[<b>8</b>]";
    } else {
	$footnote = "";
    }
725
    echo "<tr>
726
	      <td>Reboot Waittime (seconds)${footnote}:</td>
727
728
729
730
731
732
733
	      <td class=left>
		  <input type=text
		         name=\"formfields[reboot_waittime]\"
			 value=\"" . $formfields["reboot_waittime"] . "\"
			 size=4 maxlength=4>
   	      </td>
	  </tr>\n";
734

735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
    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";
    }

750
751
752
753
754
755
756
757
758
    echo "<tr>
              <td align=center colspan=2>
                  <b><input type=submit name=submit value=Submit></b>
              </td>
          </tr>\n";

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

759
760
761
762
763
764
    if (isset($view["hide_footnotes"])) {
	echo "<center><blockquote>
	      <b>In general, you should leave the default settings alone!</b>
              </blockquote></center>\n";
    }
    else {
765
	echo "<blockquote>
766
767
768
769
770
	      <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
771
772
                             (RHL*) or Fedora images (FC*) then it is
                             partition 2.
773
774
			</li>
			<li> if you customized one of our standard BSD
775
			     images (FBSD*) then it is partition 1.
776
			</li>
Russ Fish's avatar
Russ Fish committed
777
			<li> if you customized one of our standard Windows XP
778
779
780
			     images then it is partition 1, and make sure
                             you check the <em>Whole Disk Image</em> box.
			</li>
781
782
783
784
785
786
787
788
789
790
791
792
793
794
			<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>
795
796
797
		      <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
798
			   ipod is not supported on Windows XP.
799
		      </li>
800
		      <li> If it is based on one of our standard Linux, Fedora,
Russ Fish's avatar
Russ Fish committed
801
			   FreeBSD, or Windows XP images (or otherwise
802
			   sends its own ISUP notification), mark isup.
Leigh B. Stoller's avatar
Leigh B. Stoller committed
803
                      </li>
804
		      <li> If it is based on one of our standard Linux, Fedora,
Leigh B. Stoller's avatar
Leigh B. Stoller committed
805
			   FreeBSD, or Windows XP images, mark linktest.
806
807
808
809
810
811
812
		      </li>
		    </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
813
814
815
			   Linux, Fedora, FreeBSD, or Windows XP images)
                           use the same op_mode as that image.
                           Select it from the
816
817
818
819
820
821
822
823
824
			   <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).
825
826
827
828
829
830
831
832
833
834
835
836
		      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!
837
838
839
840
841
842
843
844
		 </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.
845
846
847
848
849
                 </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>
850
	      </ol>
851
	      </blockquote>\n";
852
853
854
855
856
857
858
859
860
861
862
863
    }
}

#
# 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";
    }
864
865
866
867
868
}

#
# On first load, display a virgin form and exit.
#
869
if (!isset($submit)) {
870
    $defaults = array();
871
872
873
874
875
    $defaults["pid"]		 = "";
    $defaults["gid"]		 = "";
    $defaults["imagename"]	 = "";
    $defaults["description"]	 = "";
    $defaults["path"]		 = "$TBPROJ_DIR/";
876
    $defaults["node_id"]	 = (isset($node) ? $node->node_id() : "");
877
878
879
    $defaults["max_concurrent"]	 = "";
    $defaults["shared"]		 = "No";
    $defaults["global"]		 = "No";
880
881
882
    $defaults["OS"]	 	 = "";
    $defaults["version"]	 = "";
    $defaults["wholedisk"]	 = "No";
883
    $defaults["reboot_waittime"] = "";
884
    $defaults["mbr_version"]     = "";
885

886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
    #
    # Use the base image to seed the form.
    #
    if (isset($baseimage)) {
	$baseosinfo = OSinfo::Lookup($baseimage->imageid());
	if (! $baseosinfo) {
	    TBERROR("Could not lookup osinfo object for image " .
		    $baseimage->imageid(), 1);
	}
	$defaults["loadpart"]    = $baseimage->loadpart();
	if ($baseimage->loadpart() == 0 && $baseimage->loadlength() == 4) {
	    $defaults["loadpart"]    = "1";
	    $defaults["wholedisk"]   = "Yep";
	}
	$defaults["mbr_version"]     = $baseimage->mbr_version();
	#
	# Same types as the parent.
	#
	foreach ($baseimage->Types() as $type) {
	    $defaults["mtype_${type}"] = "Yep";
	}
    }
    elseif (isset($nodetype) && $nodetype == "pcvm") {
	$defaults["loadpart"]    = "1";
	$defaults["wholedisk"]   = "Yep";
        # mtype_all is a "fake" variable which makes all
	# mtypes checked in the virgin form.
	$defaults["mtype_all"] = "Yep";
914
915
916

	# Bogus. This tells the client that the ndz file is a package.
	$defaults["mbr_version"] = "2";
917
918
    }
    elseif (isset($nodetype) && $nodetype == "mote") {
919
	# Defaults for mote-type nodes
920
	$defaults["loadpart"]    = "1";
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
    } else {
	# 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
944
945
946
947
948
949
950
	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();
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
	}
    }
    elseif (isset($nodetype) && $nodetype == "pcvm") {
	$defaults["op_mode"]     = TBDB_PCVM_OPMODE;
	$defaults["reboot_waittime"]     = "240";
	$defaults["os_feature_ping"]	 = "checked";
	$defaults["os_feature_ssh"]	 = "checked";
	$defaults["os_feature_isup"]	 = "checked";
	$defaults["os_feature_linktest"] = "checked";
        #
	# XXX At the moment we have only one parent that can run openvz
        # container images, so rather then give the user a choice, just
        # hardwire it. Needs more thought, cause we also have the os_submap
        # table and not sure how to deal with that either.
	#
	$def_parentosinfo =
	    OSinfo::LookupByName("emulab-ops". "FEDORA15-OPENVZ-STD");
	if (! $def_parentosinfo) {
	    TBERROR("Could not lookup osinfo object for ".
		    "FEDORA15-OPENVZ-STD" , 1);
	}
	$defaults["def_parentosid"]   = $def_parentosinfo->osid();
    }
    elseif (isset($nodetype) && $nodetype == "mote") {
	# Defaults for mote-type nodes
976
	$defaults["op_mode"]     = TBDB_ALWAYSUP_OPMODE;
977
978
	$defaults["OS"]          = "TinyOS";
	$defaults["version"]     = "1.1.0";
979
    } else {
Russ Fish's avatar
Russ Fish committed
980
	# Defaults for PC-type nodes
981
	$defaults["op_mode"]  = TBDB_DEFAULT_OSID_OPMODE;
982
983
984
985
	$defaults["os_feature_ping"]	 = "checked";
	$defaults["os_feature_ssh"]	 = "checked";
	$defaults["os_feature_ipod"]	 = "checked";
	$defaults["os_feature_isup"]	 = "checked";
986
	$defaults["os_feature_linktest"] = "checked";
987
    }
Chad Barb's avatar
   
Chad Barb committed
988

989
990
991
    #
    # 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
992
    # to be in the naive portion of our users, give them some help.
993
994
995
    # 
    if (count($projlist) == 1) {
	list($project, $grouplist) = each($projlist);
996

997
	if (count($grouplist) <= 2) {
998
	    $defaults["pid"] = $project;
999
1000
1001
1002
1003
	    if (count($grouplist) == 1 || strcmp($project, $grouplist[0]))
		$group = $grouplist[0];
	    else {
		$group = $grouplist[1];
	    }
1004
	    $defaults["gid"] = $group;
1005
1006
	    
	    if (!strcmp($project, $group))
1007
		$defaults["path"]     = "$TBPROJ_DIR/$project/images/";
1008
	    else
1009
		$defaults["path"]     = "$TBGROUP_DIR/$project/$group/images/";
1010
1011
1012
	}
	reset($projlist);
    }
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
    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();
	}
    }
1023
1024

    #
1025
    # Allow formfields that are already set to override defaults.
1026
1027
1028
1029
1030
1031
1032
    #
    if (isset($formfields)) {
	while (list ($field, $value) = each ($formfields)) {
	    $defaults[$field] = $formfields[$field];
	}
    }

1033
1034
1035
1036
1037
1038
1039
1040
    SPITFORM($defaults, 0);
    PAGEFOOTER();
    return;
}

#
# Otherwise, must validate and redisplay if errors
#
1041
$errors  = array();
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073

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

1074
1075
$project = null;
$group   = null;
1076
1077
1078

#
# Project:
1079
1080
1081
#
if (!isset($formfields["pid"]) ||
    strcmp($formfields["pid"], "") == 0) {
1082
1083
    $errors["Project"] = "Not Selected";
}
1084
1085
elseif (!TBvalid_pid($formfields["pid"])) {
    $errors["Project"] = "Invalid project name";
1086
}
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
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";
1097
    }
1098
1099
1100
    elseif ($project &&
	    ! ($group = $project->LookupSubgroupByName($formfields["gid"]))) {
	$errors["Group"] = "Invalid group name";
1101
1102
    }
}
1103
1104
elseif ($project) {
    $group = $project->DefaultGroup();
1105
1106
}

1107
1108
1109
1110
1111
1112
# 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";
}
 
1113
#
1114
# Build up argument array to pass along.
1115
#
1116
1117
$args = array();

1118
1119
1120
1121
1122
1123
1124
# 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();
}

1125
1126
if (isset($formfields["pid"]) && $formfields["pid"] != "") {
    $args["pid"] = $pid = $formfields["pid"];
1127
1128
}

1129
1130
if (isset($formfields["gid"]) && $formfields["gid"] != "") {
    $args["gid"] = $gid = $formfields["gid"];
1131
}
1132
1133
1134

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

1137
1138
if (isset($formfields["description"]) && $formfields["description"] != "") {
    $args["description"] = $formfields["description"];
1139
}
1140
1141

if (isset($formfields["loadpart"]) &&
Russ Fish's avatar
Russ Fish committed
1142
    $formfields["loadpart"] != "X" && $formfields["loadpart"] != "") {
1143
    $args["loadpart"] = $formfields["loadpart"];
1144
}
1145
1146
1147
1148

if (isset($formfields["OS"]) &&
    $formfields["OS"] != "none" && $formfields["OS"] != "") {
    $args["OS"] = $formfields["OS"];
1149
}
1150
1151
1152

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

1155
1156
if (isset($formfields["path"]) && $formfields["path"] != "") {
    $args["path"] = $formfields["path"];
1157
}
1158
1159
1160

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

1163
1164
if (isset($formfields["op_mode"]) && $formfields["op_mode"] != "") {
    $args["op_mode"] = $formfields["op_mode"];
1165
1166
}

1167
1168
1169
# Filter booleans from checkboxes to 0 or 1.
if (isset($formfields["wholedisk"])) {
   $args["wholedisk"] = strcmp($formfields["wholedisk"], "Yep") ? 0 : 1;
1170
}
1171
1172
if (isset($formfields["shared"])) {
   $args["shared"] = strcmp($formfields["shared"], "Yep") ? 0 : 1;
1173
}
1174
1175
if (isset($formfields["global"])) {
   $args["global"] = strcmp($formfields["global"], "Yep") ? 0 : 1;
1176
}
1177
1178
1179
1180

if (isset($formfields["max_concurrent"]) &&
    $formfields["max_concurrent"] != "") {
    $args["max_concurrent"] = $formfields["max_concurrent"];
1181
}
1182

1183
1184
1185
1186
1187
if (isset($formfields["mbr_version"]) &&
    $formfields["mbr_version"] != "") {
    $args["mbr_version"] = $formfields["mbr_version"];
}

1188
1189
1190
if (isset($formfields["reboot_waittime"]) &&
    $formfields["reboot_waittime"] != "") {
    $args["reboot_waittime"] = $formfields["reboot_waittime"];
1191
1192
1193
}

#
1194
# Form comma separated list of osfeatures.
1195
1196
1197
#
$os_features_array = array();

1198
while (list ($feature, $userokay) = each($osid_featurelist)) {
1199
    if (isset($formfields["os_feature_$feature"]) &&
1200
1201
	$formfields["os_feature_$feature"] == "checked") {
	$os_features_array[] = $feature;
1202
1203
    }
}
1204
$args["osfeatures"] = join(",", $os_features_array);
1205

1206
1207
1208
1209
#
# Node.
#
unset($node);
1210
unset($node_id);
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
if (isset($formfields["node_id"]) &&
    strcmp($formfields["node_id"], "")) {

    if (!TBvalid_node_id($formfields["node_id"])) {
	$errors["Node"] = "Invalid node name";
    }
    elseif (! ($node = Node::Lookup($formfields["node_id"]))) {
	$errors["Node"] = "Invalid node name";
    }
    elseif (!$node->AccessCheck($this_user, $TB_NODEACCESS_LOADIMAGE)) {
	$errors["Node"] = "Not enough permission";
    }
    else {
	$node_id = $node->node_id();
    }
}

1228
1229
1230
1231
1232
#
# See what node types this image will work on. Must be at least one!
# Store the valid types in a new array for simplicity.
#
$mtypes_array = array();
1233
mysql_data_seek($types_result, 0);
1234
while ($row = mysql_fetch_array($types_result)) {
1235
    $type = $row["type"];