editimageid.php3 17.1 KB
Newer Older
1
<?php
Leigh Stoller's avatar
Leigh Stoller committed
2
#
3
# Copyright (c) 2000-2014, 2016 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 Stoller's avatar
Leigh Stoller committed
23
#
24
include("defs.php3");
25 26 27
include_once("osiddefs.php3");
include_once("imageid_defs.php");
include_once("osinfo_defs.php");
28 29

#
30
# Only known and logged in users.
31
#
32 33 34
$this_user = CheckLoginOrDie();
$uid       = $this_user->uid();
$isadmin   = ISADMIN();
35
$doespcvm  = 0;
36 37

#
38 39 40 41 42 43 44 45
# Verify page arguments.
#
$reqargs = RequiredPageArguments("image",      PAGEARG_IMAGE);
$optargs = OptionalPageArguments("submit",     PAGEARG_STRING,
				 "formfields", PAGEARG_ARRAY);

# Need these below.
$imageid = $image->imageid();
46 47 48
if ($image->ezid()) {
    $osinfo = OSinfo::Lookup($imageid);
}
49

50
#
Leigh Stoller's avatar
Leigh Stoller committed
51
# Verify permission.
52
#
53
if (!$image->AccessCheck($this_user, $TB_IMAGEID_MODIFYINFO)) {
54
    USERERROR("You do not have permission to access ImageID $imageid!", 1);
55 56
}

57 58 59 60 61
#
# Standard Testbed Header
#
PAGEHEADER("Edit Image Descriptor");

62
#
63 64 65
# 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
# just in the node_types table.
66
#
67 68
$types_result =
    DBQueryFatal("select distinct n.type from nodes as n ".
69 70 71
		 "left join node_type_attributes as a on a.type=n.type ".
		 "where a.attrkey='imageable' and ".
		 "      a.attrvalue!='0'");
72 73 74 75 76 77 78 79 80 81
$types_array = array();
while ($row = mysql_fetch_array($types_result)) {
    $types_array[] = $row["type"];
}

#
# Special hack to specify subOSes that can run on vnodes 
# -- see SetupReload in os_setup
#
$types_array[] = "pcvm";
82

83
$osid_result =
84
    DBQueryFatal("select o.osid,v.vers,o.osname,o.pid from os_info as o ".
85 86 87 88
		 "left join os_info_versions as v on ".
		 "     v.osid=o.osid and v.vers=o.version ".
		 "where (v.path='' or v.path is NULL) ".
		 "order by o.pid,o.osname");
89

90
#
91 92
# Spit the form out using the array of data.
#
93
function SPITFORM($image, $formfields, $errors)
94
{
95
    global $uid, $isadmin, $types_array, $defaults, $osid_result, $doespcvm;
96
    global $TBDB_IMAGEID_IMAGENAMELEN, $TBDB_NODEIDLEN;
Russ Fish's avatar
Russ Fish committed
97

98 99 100 101 102 103 104 105 106 107 108 109
    if ($errors) {
	echo "<table class=nogrid
                     align=center border=0 cellpadding=6 cellspacing=0>
              <tr>
                 <th align=center colspan=2>
                   <font size=+1 color=red>
                      &nbsp;Oops, please fix the following errors!&nbsp;
                   </font>
                 </td>
              </tr>\n";

	while (list ($name, $message) = each ($errors)) {
110 111
            # XSS prevention.
	    $message = CleanString($message);
112 113 114 115 116 117 118 119 120
	    echo "<tr>
                     <td align=right>
                       <font color=red>$name:&nbsp;</font></td>
                     <td align=left>
                       <font color=red>$message</font></td>
                  </tr>\n";
	}
	echo "</table><br>\n";
    }
121 122 123 124
    # XSS prevention.
    while (list ($key, $val) = each ($formfields)) {
	$formfields[$key] = CleanString($val);
    }
125

126 127
    # Must encode the imageid since Rob started using plus signs in
    # the names.
128
    $url = CreateURL("editimageid", $image);
129 130
    echo "<br>
          <table align=center border=1> 
131
          <form action='$url' method=post>\n";
132 133

    #
Russ Fish's avatar
Russ Fish committed
134
    # Image Name
135 136 137
    #
    echo "<tr>
              <td>ImageID:</td>
138
              <td class=left>" . $defaults["imagename"] . "</td>
139 140 141 142 143 144 145
          </tr>\n";

    #
    # Project
    #
    echo "<tr>
              <td>Project:</td>
146
              <td class=left>" . $defaults["pid"] . "</td>
147 148 149 150 151 152 153
          </tr>\n";

    #
    # Group
    # 
    echo "<tr>
              <td>Group:</td>
154
              <td class=left>" . $defaults["gid"] . "</td>
155 156 157 158 159 160 161
          </tr>\n";

    #
    # Image Name:
    #
    echo "<tr>
              <td>Descriptor Name:</td>
162
              <td class=left>" . $defaults["imagename"] . "</td>
163 164 165 166 167 168
          </tr>\n";

    #
    # Description
    #
    echo "<tr>
Russ Fish's avatar
Russ Fish committed
169 170
              <td>Description:<br>
                  (a short pithy sentence)</td>
171 172 173
              <td class=left>
                  <input type=text
                         name=\"formfields[description]\"
174
                         value=\"" . $formfields["description"] . "\"
175 176 177 178 179 180 181 182 183
	                 size=50>
              </td>
          </tr>\n";

    #
    # Load Partition
    #
    echo "<tr>
              <td>Load Partition:</td>
184
              <td class=left>" . $defaults["loadpart"] . "</td>
185 186 187 188 189 190 191
          </tr>\n";

    #
    # Load Length
    #
    echo "<tr>
              <td>Load Partition:</td>
192
              <td class=left>" . $defaults["loadlength"] . "</td>
193 194 195 196 197
          </tr>\n";

    echo "<tr>
             <td>Partition 1 OS: </td>
             <td class=\"left\">";
198
    if (isset($defaults["part1_osid"]))
199
	SpitOSIDLink($defaults["part1_osid"], $defaults["part1_vers"]);
200 201 202 203 204 205 206 207
    else
	echo "No OS";
    echo "   </td>
          </tr>\n";
    
    echo "<tr>
             <td>Partition 2 OS: </td>
             <td class=\"left\">";
208
    if (isset($defaults["part2_osid"]))
209
	SpitOSIDLink($defaults["part2_osid"], $defaults["part2_vers"]);
210 211 212 213 214 215 216 217
    else
	echo "No OS";
    echo "   </td>
          </tr>\n";

    echo "<tr>
             <td>Partition 3 OS: </td>
             <td class=\"left\">";
218
    if (isset($defaults["part3_osid"]))
219
	SpitOSIDLink($defaults["part3_osid"], $defaults["part3_vers"]);
220 221 222 223 224 225 226 227
    else
	echo "No OS";
    echo "   </td>
          </tr>\n";

    echo "<tr>
             <td>Partition 4 OS: </td>
             <td class=\"left\">";
228
    if (isset($defaults["part4_osid"]))
229
	SpitOSIDLink($defaults["part4_osid"], $defaults["part4_vers"]);
230 231 232 233 234 235 236 237
    else
	echo "No OS";
    echo "   </td>
          </tr>\n";
    
    echo "<tr>
             <td>Boot OS: </td>
             <td class=\"left\">";
238
    if (isset($defaults["default_osid"]))
239
	SpitOSIDLink($defaults["default_osid"], $defaults["default_vers"]);
240 241 242 243 244 245 246 247 248
    else
	echo "No OS";
    echo "   </td>
          </tr>\n";
    
    #
    # Path to image.
    #
    echo "<tr>
Russ Fish's avatar
Russ Fish committed
249
              <td>Filename (full path) of Image:</td>
250 251 252
              <td class=left>
                  <input type=text
                         name=\"formfields[path]\"
253
                         value=\"" . $formfields["path"] . "\"
254 255 256 257
	                 size=50>
              </td>
          </tr>\n";

258 259 260 261 262 263 264 265 266 267
    echo "<tr>
              <td>Architecture:</td>
              <td class=left>
                 <input type=text
                        name=\"formfields[architecture]\"
                        value=\"" . $formfields["architecture"] . "\"
                        size=30>
              </td>
         </tr>\n";

268 269 270 271 272 273
    #
    # Node Types.
    #
    echo "<tr>
              <td>Node Types:</td>
              <td>\n";
274 275 276 277 278 279 280 281 282 283
    #
    # Is using the architecture, types are not editable. Instead, we allow
    # editing of the architecture.
    #
    if ($image->architecture()) {
        echo implode(",", $image->TypeList());
    }
    else {
        foreach ($types_array as $type) {
            $checked = "";
284

285 286 287
            if (isset($formfields["mtype_$type"]) &&
                $formfields["mtype_$type"] == "Yep") {
                $checked = "checked";
288

289 290 291 292
                if ("mtype_$type" == "mtype_pcvm") {
                    $doespcvm = 1;
                }
            }
293
    
294
            echo "<input $checked type=checkbox
295 296 297
                     value=Yep name=\"formfields[mtype_$type]\">
                     $type &nbsp
              </input>\n";
298
        }
299 300 301 302 303 304 305 306
    }
    echo "    </td>
          </tr>\n";

    #
    # Shared?
    #
    echo "<tr>
Russ Fish's avatar
Russ Fish committed
307 308
  	      <td>Shared?:<br>
                  (available to all subgroups)</td>
309
              <td class=left>". ($defaults["shared"] ? "Yes" : "No") . "</td>
310 311 312 313 314 315
          </tr>\n";

    #
    # Global?
    #
    echo "<tr>
Russ Fish's avatar
Russ Fish committed
316 317
  	      <td>Global?:<br>
                      (available to all projects)</td>
318
              <td class=left>". ($defaults["global"] ? "Yes" : "No") . "</td>
319 320
          </tr>\n";

321 322 323 324 325 326 327 328 329 330
    if ($isadmin) {
	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";
331 332 333 334 335 336

	if ($doespcvm) {
	    WRITEOSIDMENU("Default Parent OS",
			  "formfields[def_parentosid]",
			  $osid_result, $formfields["def_parentosid"]);
	}
337 338 339 340 341 342 343 344 345 346 347 348 349
        #
	# Notes
	#
	echo "<tr>
                  <td>Admin Notes:</td>
                  <td class=left>
                      <textarea name=\"formfields[notes]\"
                                rows=4 cols=60>" .
		                   str_replace("\r", "",
						$formfields["notes"]) .
	              "</textarea>
                  </td>
              </tr>\n";
350 351
    }

352 353 354 355 356 357 358 359
    echo "<tr>
              <td align=center colspan=2>
                 <b><input type=submit name=submit value=Submit></b>
              </td>
          </tr>\n";

    echo "</form>
          </table>\n";
360
}
361 362

# Need this below.
363
$defaults = $image->DBData();
364 365 366 367
   
#
# On first load, display a virgin form and exit.
#
Russ Fish's avatar
Russ Fish committed
368
if (!isset($submit)) {
369 370
    # Generate the current types array for the form.
    foreach ($image->Types() as $type) {
371 372
	$defaults["mtype_${type}"] = "Yep";
    }
Leigh Stoller's avatar
Leigh Stoller committed
373
    $defaults["def_parentosid"] = "";
374 375 376
    if ($image->ezid() && $osinfo->def_parentosid()) {
	$defaults["def_parentosid"] = $osinfo->def_parentosid();
    }
377

378
    SPITFORM($image, $defaults, 0);
379 380
    PAGEFOOTER();
    return;
381 382
}

383 384 385 386 387 388
#
# Otherwise, must validate and redisplay if errors
#
$errors     = array();
$updates    = array();

389 390 391 392 393 394 395 396
#
# If any errors, respit the form with the current values and the
# error messages displayed. Iterate until happy.
# 
if (count($errors)) {
    SPITFORM($image, $formfields, $errors);
    PAGEFOOTER();
    return;
397 398
}

399
#
400 401 402
# Build up argument array to pass along.
#
$args = array();
403

404
# Notice that {part*,default}_osid are not editable inputs on this form.
405

406 407 408 409 410 411 412 413 414 415 416
# Skip passing ones that are not changing from the default (DB state.)
if (isset($formfields["description"]) && $formfields["description"] != "" &&
    ($formfields["description"] != $image->description())) {
    $args["description"] = $formfields["description"];
}

if (isset($formfields["path"]) && $formfields["path"] != "" &&
    ($formfields["path"] != $image->path())) {
    $args["path"] = $formfields["path"];
}

417 418 419 420
if (isset($formfields["mbr_version"]) && $formfields["mbr_version"] != "" &&
    $formfields["mbr_version"] != $image->mbr_version()) {
    $args["mbr_version"] = $formfields["mbr_version"];
}
421 422 423 424 425 426 427 428

if (isset($formfields["notes"])) {
    if (!TBvalid_fulltext($formfields["notes"])) {
	$errors["Notes"] = TBFieldErrorString();
    }
    else {
	$args["notes"] = $formfields["notes"];
    }
429
}
430

431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457
#
# See what node types this image will work on. Must be at least one!
# Store the valid types in a new array for simplicity.
#
if ($image->architecture()) {
    if (! (isset($formfields["architecture"]) &&
           $formfields["architecture"] != "")) {
	$errors["Architecture"] = "Must set the Architecture";
    }
    else {
        foreach (preg_split("/,/", $formfields["architecture"]) as $arch) {
            if (!array_key_exists($arch, $image_architectures)) {
                $errors["Architecture"] = "Not a valid Architecture";
            }
            else {
                #
                # If no node types of this arch, reject it.
                #
                $query_result = DBQueryFatal("select type from node_types ".
                                             "where architecture='$arch'");
                if (!mysql_num_rows($query_result)) {
                    $errors["Architecture"] =
                        "No node types of this architecture.";
                }
            }
        }
	$args["architecture"] = $formfields["architecture"];
458
    }
459
}
460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476
else {
    $mtypes_array = array();
    foreach ($types_array as $type) {
        #
        # Look for a post variable with name.
        # 
        if (isset($formfields["mtype_$type"]) &&
            $formfields["mtype_$type"] == "Yep") {
            $mtypes_array[] = $type;
            if ("mtype_$type" == "mtype_pcvm") {
                $doespcvm = 1;
            }
        }
    }
    if (! count($mtypes_array)) {
        $errors["Node Types"] = "Must select at least one type";
    }
477

478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503
    # The mtype_* checkboxes are dynamically generated.
    foreach ($mtypes_array as $type) {
        # Filter booleans from checkbox values, send if different.
        $checked = isset($formfields["mtype_$type"]) &&
                 strcmp($formfields["mtype_$type"], "Yep") == 0;
        if ($checked != array_search("mtype_$type", $mtypes_array)) {
            $args["mtype_$type"] = $checked ? "1" : "0";
        }
    }
    #
    # Mereusers are not allowed to create more than one osid/imageid mapping
    # for each machinetype. They cannot actually do that through the EZ form
    # since the osid/imageid has to be unique, but it can happen by mixed
    # use of the long form and the short form, or with multiple uses of the
    # long form.

    # Can't check this unless we have at least one mtype!
    if (!count($mtypes_array) || count($errors)) {
        SPITFORM($image, $formfields, $errors);
        PAGEFOOTER();
        return;
    }
    $typeclause = "type=" . "'$mtypes_array[0]'";
    for ($i = 1; $i < count($mtypes_array); $i++) {
        $typeclause = "$typeclause or type=" . "'$mtypes_array[$i]'";
    }
504

505 506 507 508 509
    unset($osidclause);
    $osid_array = array();
    for ($i = 1; $i <= 4; $i++) {
        # Local variable dynamically created.    
        $foo      = "part${i}_osid";
510

511 512 513 514 515
        if (isset($defaults[$foo])) {
            if (isset($osidclause))
                $osidclause = "$osidclause or osid='" . $defaults[$foo] . "' ";
            else 
                $osidclause = "osid='" . $defaults[$foo] . "' ";
516

517 518
            $osid_array[] = $defaults[$foo];
        }
519
    }
520 521 522 523 524 525 526 527 528 529 530 531 532 533
    if (isset($osidclause)) {
        DBQueryFatal("lock tables images write, os_info write, ".
                     "    osidtoimageid write");
        $query_result =
            DBQueryFatal("select osidtoimageid.*,images.pid,images.imagename ".
                         " from osidtoimageid ".
                         "left join images on ".
                         " images.imageid=osidtoimageid.imageid ".
                         "where ($osidclause) and ($typeclause) and ".
                         "      images.imageid!='$imageid'");
        DBQueryFatal("unlock tables");

        if (mysql_num_rows($query_result)) {
	    echo "<center>
534 535 536 537 538 539 540 541 542
              There are other image descriptors that specify the 
	      same OS descriptors for the same node types.<br>
              There must be a
	      unique mapping of OS descriptor to Image descriptor for
              each node type! Perhaps you need to delete one of the
              images below, or create a new OS descriptor to use in
              this new Image descriptor.
              </center><br>\n";

543
            echo "<table border=1 cellpadding=2 cellspacing=2 align='center'>\n";
544

545
            echo "<tr>
546 547 548 549 550
                  <td align=center>OSID</td>
                  <td align=center>Type</td>
                  <td align=center>ImageID</td>
             </tr>\n";

551 552 553 554 555 556
            while ($row = mysql_fetch_array($query_result)) {
                $imageid   = $row['imageid'];
                $url       = CreateURL("showimageid", URLARG_IMAGEID, $imageid);
                $osid      = $row["osid"];
                $type      = $row["type"];
                $imagename = $row["imagename"];
557
	    
558
                echo "<tr>
559 560
                      <td>$osid</td>
	              <td>$type</td>
561
                      <td><A href='$url'>$imagename</A></td>
562
	          </tr>\n";
563 564 565 566 567 568
           }
            echo "</table><br><br>\n";
            
            USERERROR("Please check the other Image descriptors and make the ".
                      "necessary changes!", 1);
        }
569
    }
570
}
571 572 573 574 575 576
# Can't check this unless we have at least one mtype!
if (count($errors)) {
    SPITFORM($image, $formfields, $errors);
    PAGEFOOTER();
    return;
}
577

578 579 580 581 582 583 584 585
# Send to the backend for more checking, and eventually, to update the DB.
if (! ($result = Image::EditImageid($image,
				 $args, $errors))) {
    # Always respit the form so that the form fields are not lost.
    # I just hate it when that happens so lets not be guilty of it ourselves.
    SPITFORM($image, $formfields, $errors);
    PAGEFOOTER();
    return;
586 587
}

588 589 590 591 592 593 594 595 596 597 598
#
# Special case. 
#
if ($isadmin && $doespcvm && $image->ezid() &&
    isset($formfields["def_parentosid"]) &&
    $formfields["def_parentosid"] != "" &&
    TBvalid_osid($formfields["def_parentosid"]) &&
    OSinfo::Lookup($formfields["def_parentosid"])) {
    $osinfo->SetParent($formfields["def_parentosid"]);
}

599
PAGEREPLACE(CreateURL("showimageid", $image));
600

601
#
602
# Dump record in case the redirect fails.
603
# 
604 605
$image->Refresh();
$image->Show();
606 607 608 609 610 611

#
# Standard Testbed Footer
# 
PAGEFOOTER();
?>