uid(); $isadmin = ISADMIN(); if (! $isadmin) { USERERROR("You do not have permission to edit node types!", 1); } $optargs = OptionalPageArguments("submit", PAGEARG_STRING, "formfields", PAGEARG_ARRAY, # Send new_type=1 to create new nodetype. "new_type", PAGEARG_STRING, # Optional if new_type, required if not. "node_type", PAGEARG_STRING, # Attribute creation and deletion. "deletes", PAGEARG_ARRAY, "attributes", PAGEARG_ARRAY, "newattribute_type", PAGEARG_STRING, "newattribute_name", PAGEARG_STRING, "newattribute_value", PAGEARG_ANYTHING); if (!isset($node_type)) { $node_type = ""; } if (!isset($attributes)) { $attributes = array(); } if (!isset($deletes)) { $deletes = array(); } $emulab_ops = Project::LookupByPid("emulab-ops"); $freebsd_mfs = OSinfo::LookupByName($emulab_ops,"FREEBSD-MFS"); $fbsd410_rhl90_std = Image::LookupByName($emulab_ops,"FBSD410+RHL90-STD"); $rhl_std = OSinfo::LookupByName($emulab_ops, "RHL-STD"); $fbsd_std = OSinfo::LookupByName($emulab_ops,"FBSD-STD"); $frisbee_mfs = OSinfo::LookupByName($emulab_ops,"FRISBEE-MFS"); if ($freebsd_mfs == null || $fbsd410_rhl90_std == null || $rhl_std == null || $fbsd_std == null || $frisbee_mfs == null) { PAGEERROR("You must add images from Utah into your database" . " before adding a nodetype. See installation documentation for details!",1); } # This belongs elsewhere! $initial_attributes = array( array("attrkey" => "adminmfs_osid", "attrvalue" => $freebsd_mfs->osid(), "attrtype" => "integer"), array("attrkey" => "bios_waittime", "attrvalue" => "60", "attrtype" => "integer"), array("attrkey" => "bootdisk_unit", "attrvalue" => "0", "attrtype" => "integer"), array("attrkey" => "control_interface", "attrvalue" => "ethX", "attrtype" => "string"), array("attrkey" => "control_network", "attrvalue" => "X", "attrtype" => "integer"), array("attrkey" => "default_imageid", "attrvalue" => $fbsd410_rhl90_std->imageid(), "attrtype" => "integer"), array("attrkey" => "default_osid", "attrvalue" => $rhl_std->osid(), "attrtype" => "integer"), array("attrkey" => "delay_capacity", "attrvalue" => "2", "attrtype" => "integer"), array("attrkey" => "delay_osid", "attrvalue" => $fbsd_std->osid(), "attrtype" => "integer"), array("attrkey" => "diskloadmfs_osid", "attrvalue" => $frisbee_mfs->osid(), "attrtype" => "integer"), array("attrkey" => "disksize", "attrvalue" => "0.00", "attrtype" => "float"), array("attrkey" => "disktype", "attrvalue" => "ad", "attrtype" => "string"), array("attrkey" => "frequency", "attrvalue" => "XXX", "attrtype" => "integer"), array("attrkey" => "imageable", "attrvalue" => "1", "attrtype" => "boolean"), array("attrkey" => "jail_osid", "attrvalue" => $fbsd_std->osid(), "attrtype" => "integer"), array("attrkey" => "max_interfaces", "attrvalue" => "X", "attrtype" => "integer"), array("attrkey" => "memory", "attrvalue" => "XXX", "attrtype" => "integer"), array("attrkey" => "power_delay", "attrvalue" => "60", "attrtype" => "integer"), array("attrkey" => "processor", "attrvalue" => "PIII", "attrtype" => "string"), array("attrkey" => "rebootable", "attrvalue" => "1", "attrtype" => "boolean"), array("attrkey" => "simnode_capacity", "attrvalue" => "650", "attrtype" => "integer"), array("attrkey" => "trivlink_maxspeed", "attrvalue" => "400000", "attrtype" => "integer"), array("attrkey" => "virtnode_capacity", "attrvalue" => "20", "attrtype" => "integer"), ); # # Spit the form out using the array of data. # function SPITFORM($node_type, $formfields, $attributes, $deletes, $errors) { global $osid_result, $imageid_result, $mfsosid_result, $new_type; global $newattribute_name, $newattribute_value, $newattribute_type; # # Standard Testbed Header # if (! isset($new_type)) { PAGEHEADER("Edit Node Type"); echo "Node Type ". "$node_type \n". "\n"; echo "

\n"; } else { PAGEHEADER("Create Node Type"); } if ($errors) { echo "\n"; while (list ($name, $message) = each ($errors)) { echo "\n"; } echo "
 Oops, please fix the following errors! 
$name:  $message

\n"; } $formargs = "node_type=$node_type"; if (isset($new_type)) { $formargs .= "&new_type=1"; } echo "\n"; echo "\n"; if (isset($new_type)) { echo "\n"; } else { echo "\n"; } echo "\n"; if (isset($new_type)) { echo "\n"; } else { echo "\n"; } echo "\n"; echo "\n"; echo "\n"; echo "\n"; echo "\n"; echo "\n"; echo "\n"; # # Now do attributes. # echo "\n"; while (list ($key, $val) = each ($attributes)) { if (!isset($deletes[$key])) { # Somehow this doesn't get initialized in the Create Node case. $deletes[$key] = ""; } if ($key == "default_osid" || $key == "jail_osid" || $key == "delay_osid") { WRITEOSIDMENU($key, "attributes[$key]", $osid_result, $val, "deletes[$key]", $deletes[$key]); } elseif ($key == "adminmfs_osid" || $key == "diskloadmfs_osid") { WRITEOSIDMENU($key, "attributes[$key]", $mfsosid_result, $val, "deletes[$key]", $deletes[$key]); } elseif ($key == "default_imageid") { WRITEIMAGEIDMENU($key, "attributes[$key]", $imageid_result, $val, "deletes[$key]", $deletes[$key]); } else { echo "\n"; } } # # Provide area for adding a new attribute. # echo "\n"; echo "\n"; echo "\n"; $typenames = array(); $typenames[] = "boolean"; $typenames[] = "integer"; $typenames[] = "float"; $typenames[] = "string"; echo "\n"; echo "\n"; echo "
Type: $node_type
Class: " . $formfields["class"] . "
isvirtnode:
isjailed:
isdynamic:
isremotenode:
issubnode:
isplabdslice:
issimnode:
Delete? Node Attributes
${key}:
Add New Attribute
Attribute Name:
Attribute Value:
Attribute Type: \n"; foreach ($typenames as $i => $type) { $checked = ""; if ($newattribute_type == $type) $checked = "checked"; echo "$type\n"; } echo "
\n"; } if (isset($new_type)) { # # Starting a new node type - give some reasonable defaults # $defaults = array("class" => "pc", "isvirtnode" => 0, "isremotenode" => 0, "issubnode" => 0, "isplabdslice" => 0, "isjailed" => 0, "isdynamic" => 0, "issimnode" => 0); $default_attributes = array(); $attribute_types = array(); $attribute_deletes = array(); foreach ($initial_attributes as $entry) { $default_attributes[$entry['attrkey']] = $entry['attrvalue']; $attribute_types[$entry['attrkey']] = $entry['attrtype']; $attribute_deletes[$entry['attrkey']] = ""; } } elseif (isset($node_type)) { # # Editing an existing type - suck the current info out of the # database. # if (!preg_match("/^[-\w]+$/", $node_type)) { USERERROR("$node_type contains illegal characters!", 1); } $query_result = DBQueryFatal("select * from node_types where type='$node_type'"); if (($defaults = mysql_fetch_array($query_result)) == 0) { USERERROR("$node_type is not a valid node type!", 1); } # # And the attributes ... needed below. # $default_attributes = array(); $attribute_types = array(); $attribute_deletes = array(); $query_result = DBQueryFatal("select * from node_type_attributes ". "where type='$node_type'"); while ($row = mysql_fetch_array($query_result)) { $default_attributes[$row['attrkey']] = $row['attrvalue']; $attribute_types[$row['attrkey']] = $row['attrtype']; $attribute_deletes[$row['attrkey']] = ""; } } else { PAGEARGERROR("Must provide one of node_type or new_type"); return; } # # We need lists of osids and imageids for selection. # $osid_result = DBQueryFatal("select osid,osname,pid from os_info ". "where (path='' or path is NULL) ". "order by pid,osname"); $mfsosid_result = DBQueryFatal("select osid,osname,pid from os_info ". "where (path is not NULL and path!='') ". "order by pid,osname"); $imageid_result = DBQueryFatal("select imageid,imagename,pid from images ". "order by pid,imagename"); # # On first load, display initial values. # if (! isset($submit)) { SPITFORM($node_type, $defaults, $default_attributes, $attribute_deletes, 0); PAGEFOOTER(); return; } # # We do not allow these to be changed. # if (!isset($new_type)) { $formfields["class"] = $defaults["class"]; } # # Otherwise, must validate and redisplay if errors. # $errors = array(); # Check the attributes. while (list ($key, $val) = each ($attributes)) { # Skip checks if scheduled for deletion if (isset($deletes[$key]) && $deletes[$key] == "checked") continue; if (!isset($attribute_types[$key])) { $errors[$key] = "Unknown Attribute"; continue; } if ($val == "") { $errors[$key] = "No value provided for $key"; continue; } # Probably redundant with the XML keyfields checking... $attrtype = $attribute_types[$key]; if ($attrtype == "") { # Shouldn't happen... $attrtype = $attribute_types[$key] = "integer"; } if (strpos(":boolean:float:integer:string:", ":$attrtype:")===FALSE) { $errors[$key] = "Invalid type information: $attrtype"; continue; } # New attributes require type and value. if (isset($newattribute_name) && $newattribute_name != "" && !(isset($newattribute_type) && $newattribute_type != "")) { $errors[$newattribute_name] = "Missing type"; } if (isset($newattribute_name) && $newattribute_name != "" && !(isset($newattribute_value) && $newattribute_value != "")) { $errors[$newattribute_name] = "Missing value"; } } # # If any errors, respit the form with the current values and the # error messages displayed. Iterate until happy. # if (count($errors)) { SPITFORM($node_type, $formfields, $attributes, $deletes, $errors); PAGEFOOTER(); return; } # # Build up argument array to pass along. # $args = array(); # Class (only for new types.) if (isset($new_type) && isset($formfields['class']) && $formfields['class'] != "") { $args["new_type"] = "1"; $args["class"] = $formfields["class"]; } # isvirtnode if (isset($formfields["isvirtnode"]) && $formfields["isvirtnode"] != "") { $args["isvirtnode"] = $formfields["isvirtnode"]; } # isjailed if (isset($formfields["isjailed"]) && $formfields["isjailed"] != "") { $args["isjailed"] = $formfields["isjailed"]; } # isdynamic if (isset($formfields["isdynamic"]) && $formfields["isdynamic"] != "") { $args["isdynamic"] = $formfields["isdynamic"]; } # isremotenode if (isset($formfields["isremotenode"]) && $formfields["isremotenode"] != "") { $args["isremotenode"] = $formfields["isremotenode"]; } # issubnode if (isset($formfields["issubnode"]) && $formfields["issubnode"] != "") { $args["issubnode"] = $formfields["issubnode"]; } # isplabdslice if (isset($formfields["isplabdslice"]) && $formfields["isplabdslice"] != "") { $args["isplabdslice"] = $formfields["isplabdslice"]; } # issimnode if (isset($formfields["issimnode"]) && $formfields["issimnode"] != "") { $args["issimnode"] = $formfields["issimnode"]; } # Existing attributes. foreach ($attributes as $attr_key => $attr_val) { if (isset($deletes[$attr_key]) && $deletes[$attr_key] == "checked") $args["delete_${attr_key}"] = "1"; $attr_type = $attribute_types[$attr_key]; $args["attr_${attr_type}_${attr_key}"] = $attr_val; } # # Form allows for adding a single new attribute, but someday be more fancy. # if (isset($newattribute_name) && $newattribute_name != "" && isset($newattribute_value) && $newattribute_value != "" && isset($newattribute_type) && $newattribute_type != "") { $args["new_attr"] = $newattribute_name; # The following is matched by wildcards on the other side of XML, # including checking its type and value, just like existing attributes. $args["attr_${newattribute_type}_$newattribute_name"] = $newattribute_value; } if (! ($result = SetNodeType($node_type, $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($node_type, $formfields, $attributes, $deletes, $errors); PAGEFOOTER(); return; } PAGEHEADER(isset($new_type) ? "Create" : "Edit" . " Node Type"); # # Spit out a redirect so that the history does not include a post # in it. The back button skips over the post and to the form. # PAGEREPLACE("editnodetype.php3?node_type=$node_type"); # # Standard Testbed Footer # PAGEFOOTER(); # # Create or edit a nodetype. (No class for that at present.) # function SetNodeType($node_type, $args, &$errors) { global $suexec_output, $suexec_output_array; # # Generate a temporary file and write in the XML goo. # $xmlname = tempnam("/tmp", "editnodetype"); if (! $xmlname) { TBERROR("Could not create temporary filename", 0); $errors[] = "Transient error(1); please try again later."; return null; } if (! ($fp = fopen($xmlname, "w"))) { TBERROR("Could not open temp file $xmlname", 0); $errors[] = "Transient error(2); please try again later."; return null; } # Add these. Maybe caller should do this? $args["node_type"] = $node_type; fwrite($fp, "\n"); foreach ($args as $name => $value) { fwrite($fp, ""); fwrite($fp, " " . htmlspecialchars($value) . ""); fwrite($fp, "\n"); } fwrite($fp, "\n"); fclose($fp); chmod($xmlname, 0666); $retval = SUEXEC("nobody", "nobody", "webeditnodetype $xmlname", SUEXEC_ACTION_IGNORE); if ($retval) { if ($retval < 0) { $errors[] = "Transient error(3, $retval); please try again later."; SUEXECERROR(SUEXEC_ACTION_CONTINUE); } else { # unlink($xmlname); if (count($suexec_output_array)) { for ($i = 0; $i < count($suexec_output_array); $i++) { $line = $suexec_output_array[$i]; if (preg_match("/^([-\w]+):\s*(.*)$/", $line, $matches)) { $errors[$matches[1]] = $matches[2]; } else $errors[] = $line; } } else $errors[] = "Transient error(4, $retval); please try again later."; } return null; } # There are no return value(s) to parse at the end of the output. # Unlink this here, so that the file is left behind in case of error. # We can then create the nodetype by hand from the xmlfile, if desired. unlink($xmlname); return true; } ?>