Modified: vcl/trunk/web/.ht-inc/conf-default.php URL: http://svn.apache.org/viewvc/vcl/trunk/web/.ht-inc/conf-default.php?rev=1624325&r1=1624324&r2=1624325&view=diff ============================================================================== --- vcl/trunk/web/.ht-inc/conf-default.php (original) +++ vcl/trunk/web/.ht-inc/conf-default.php Thu Sep 11 16:01:48 2014 @@ -96,6 +96,10 @@ define("ALLOWADDSHIBUSERS", 0); // this // a userid, there is no way to verify that it was entered incorrectly so the user // will be added to the database with the typoed userid +define("MAXINITIALIMAGINGTIME", 720); // for imaging reservations, users will have at least this long as the max selectable duration + +define("MAXSUBIMAGES", 5000); // maximum allowed number for subimages in a config + $ENABLE_ITECSAUTH = 0; // use ITECS accounts (also called "Non-NCSU" accounts) # xmlrpcBlockAPIUsers is an array of ids from user table for users that are
Added: vcl/trunk/web/.ht-inc/config.php URL: http://svn.apache.org/viewvc/vcl/trunk/web/.ht-inc/config.php?rev=1624325&view=auto ============================================================================== --- vcl/trunk/web/.ht-inc/config.php (added) +++ vcl/trunk/web/.ht-inc/config.php Thu Sep 11 16:01:48 2014 @@ -0,0 +1,1640 @@ +<?php +/* + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +class Config extends Resource { + function __construct() { + parent::__construct(); + $this->restype = 'config'; + $this->restypename = 'Config'; + $this->namefield = 'name'; + $this->defaultGetDataArgs = array('rscid' => 0, + 'includedeleted' => 0); + $this->basecdata['obj'] = $this; + } + + //////////////////////////////////////////////////////////////////////////////// + /// + /// \fn + /// + /// \brief Config + /// + //////////////////////////////////////////////////////////////////////////////// + function getData($args) { + return $this->_getData($args['rscid'], $args['includedeleted']); + } + + //////////////////////////////////////////////////////////////////////////////// + /// + /// \fn + /// + /// \brief Config + /// + //////////////////////////////////////////////////////////////////////////////// + function _getData($id=0, $includedeleted=0) { + # config variables + $query = "SELECT cv.id, " + . "cv.name, " + . "cv.configid, " + . "cv.defaultvalue, " + . "cv.required, " + . "cv.ask, " + . "cv.identifier, " + . "cv.datatypeid, " + . "0 AS deleted, " + . "d.name AS datatype " + . "FROM configvariable cv, " + . "datatype d " + . "WHERE cv.datatypeid = d.id "; + if($id != 0) + $query .= "AND cv.configid = $id "; + $query .= "ORDER BY cv.configid, cv.name"; + $variables = array(); + $qh = doQuery($query); + while($row = mysql_fetch_assoc($qh)) + $variables[$row['configid']][$row['id']] = $row; + + # config subimages + $query = "SELECT s.id, " + . "s.configid, " + . "s.imageid, " + . "i.prettyname AS name, " + . "s.mininstance AS min, " + . "s.maxinstance AS max, " + . "s.description, " + . "0 AS deleted " + . "FROM configsubimage s, " + . "image i " + . "WHERE s.imageid = i.id AND " + . "i.deleted = 0 "; + if($id != 0) + $query .= "AND configid = $id "; + $query .= "ORDER BY s.configid, i.prettyname"; + $qh = doQuery($query); + while($row = mysql_fetch_assoc($qh)) + $variables[$row['configid']][$row['id']] = $row; + + # configs + $query = "SELECT c.id, " + . "c.name, " + . "c.description AS description, " + . "c.configtypeid, " + . "ct.prettyname AS configtype, " + . "ct.configstageid AS configstageid, " + . "cs.name AS stage, " + . "c.data, " + . "c.ownerid, " + . "CONCAT(u.unityid, '@', a.name) AS owner, " + . "c.optional, " + . "c.deleted, " + . "r.id AS resourceid " + . "FROM config c, " + . "resource r, " + . "resourcetype t, " + . "user u, " + . "affiliation a, " + . "configtype ct " + . "LEFT JOIN configstage cs ON (ct.configstageid = cs.id) " + . "WHERE c.configtypeid = ct.id AND " + . "c.ownerid = u.id AND " + . "u.affiliationid = a.id AND " + . "c.id = r.subid AND " + . "r.resourcetypeid = t.id AND " + . "t.name = 'config'"; + if($id != 0) + $query .= " AND c.id = $id"; + if(! $includedeleted) + $query .= " AND c.deleted = 0"; + $qh = doQuery($query); + $configs = array(); + while($row = mysql_fetch_assoc($qh)) { + if(array_key_exists($row['id'], $variables)) + $row['variables'] = $variables[$row['id']]; + else + $row['variables'] = array(); + $configs[$row['id']] = $row; + } + return $configs; + } + + + //////////////////////////////////////////////////////////////////////////////// + /// + /// \fn + /// + /// \brief Config + /// + //////////////////////////////////////////////////////////////////////////////// + function getConfigMapData($configmapid) { + $query = "SELECT cm.configid, " + . "c.name AS configname, " + . "ct.prettyname AS configtype, " + . "cm.subid, " + . "cm.configmaptypeid, " + . "cmt.name AS configmaptype, " + . "cmt.prettyname AS prettyconfigmaptype, " + . "cm.affiliationid, " + . "a.name AS affiliation, " + . "cm.disabled, " + . "cm.configstageid AS stageid, " + . "cs.name AS stage " + . "FROM configmaptype cmt, " + . "config c, " + . "affiliation a, " + . "configstage cs, " + . "configtype ct, " + . "configmap cm " + . "WHERE cm.configmaptypeid = cmt.id AND " + . "cm.affiliationid = a.id AND " + . "cm.configstageid = cs.id AND " + . "cm.id = $configmapid AND " + . "cm.configid = c.id AND " + . "c.configtypeid = ct.id AND " + . "c.deleted = 0"; + $qh = doQuery($query); + if($row = mysql_fetch_assoc($qh)) + return $row; + else + return NULL; + } + + //////////////////////////////////////////////////////////////////////////////// + /// + /// \fn + /// + /// \brief Config + /// + //////////////////////////////////////////////////////////////////////////////// + function extraSelectAdminOptions() { + $h = ''; + $cont = addContinuationsEntry("editConfigMap", $this->basecdata); + $h .= "<INPUT type=radio name=continuation value=\"$cont\" id=\""; + $h .= "configmap\"><label for=\"configmap\">Edit Mapping</label><br>\n"; + return $h; + } + + //////////////////////////////////////////////////////////////////////////////// + /// + /// \fn + /// + /// \brief Config + /// + //////////////////////////////////////////////////////////////////////////////// + function AJeditResource() { + # TODO see if base AJeditResource will work + $configid = processInputVar('rscid', ARG_NUMERIC); + $configs = getUserResources(array("configAdmin"), array('administer'), 0, 1); + if(! array_key_exists($configid, $configs['config'])) { + $ret = array('status' => 'noaccess'); + sendJSON($ret); + return; + } + $tmp = $this->_getData($configid); + $data = $tmp[$configid]; + $data['variables'] = array_splice($data['variables'], 0); + $cdata = $this->basecdata; + $cdata['configid'] = $configid; + $cdata['configdata'] = $data; + $cont = addContinuationsEntry('AJsaveResource', $cdata); + # TODO SECURITY - is there a chance of an XSS attack from value of data + #$data['data'] = htmlspecialchars($data['data']); + $ret = array('title' => "Edit {$this->restypename}", + 'cont' => $cont, + 'resid' => $configid, + 'data' => $data, + 'status' => 'success'); + sendJSON($ret); + } + + + //////////////////////////////////////////////////////////////////////////////// + /// + /// \fn + /// + /// \brief Config + /// + //////////////////////////////////////////////////////////////////////////////// + function AJsaveResource() { + $curdata = getContinuationVar('configdata'); + $add = getContinuationVar('add', 0); + if($add) + $configid = 0; + else + $configid = $curdata['id']; + if(! $vars = $this->processInput($configid)) { + sendJSON(array('status' => 'error', 'msg' => $this->errmsg)); + return; + } + if($add) { + $this->addResource($vars); + return; + } + $sets = array(); + if($curdata['name'] != $vars['name']) { + $name = mysql_real_escape_string($vars['name']); + $sets[] = "name = '$name'"; + } + if($curdata['data'] != $vars['data']) { + $data = mysql_real_escape_string($vars['data']); + $sets[] = "data = '$data'"; + } + if($curdata['ownerid'] != $vars['ownerid']) + $sets[] = "ownerid = {$vars['ownerid']}"; + if($curdata['optional'] != $vars['optional']) + $sets[] = "optional = {$vars['optional']}"; + if(count($sets)) { + $allsets = implode(',', $sets); + $query = "UPDATE config SET $allsets WHERE id = $configid"; + doQuery($query); + } + if($curdata['configtype'] == 'Cluster') { + $cursubs = $curdata['variables']; + $newsubs = $vars['subimages']; + $dels = array(); + foreach($cursubs as $sub) { + $id = $sub['id']; + if($newsubs[$id]['deleted']) + $dels[] = $id; + $sets = array(); + if($newsubs[$id]['min'] != $sub['min']) + $sets[] = "mininstance = {$newsubs[$id]['min']}"; + if($newsubs[$id]['max'] != $sub['max']) + $sets[] = "maxinstance = {$newsubs[$id]['max']}"; + if(! empty($sets)) { + $allsets = implode(',', $sets); + $query = "UPDATE configsubimage " + . "SET $allsets " + . "WHERE id = $id"; + doQuery($query); + } + unset($newsubs[$id]); + } + if(! empty($dels)) { + $alldels = implode(',', $dels); + $query = "DELETE FROM configsubimage " + . "WHERE id IN ($alldels)"; + doQuery($query); + } + $vals = array(); + foreach($newsubs as $sub) { + $item = "($configid, {$sub['imageid']}, {$sub['min']}, {$sub['max']})"; + $vals[] = $item; + } + if(! empty($vals)) { + $allvals = implode(',', $vals); + $query = "INSERT INTO configsubimage " + . "(configid, " + . "imageid, " + . "mininstance, " + . "maxinstance) " + . "VALUES $allvals"; + doQuery($query); + } + } + else { + $newvars = $vars['configvariables']; + $cfgvars = $curdata['variables']; + $deletes = array(); + $datatypes = getConfigDataTypes(); + foreach($cfgvars as $vardata) { + $id = $vardata['id']; + if($newvars[$id]['deleted'] == 1) { + $deletes[] = $id; + unset($newvars[$id]); + continue; + } + $sets = array(); + if($vardata['name'] != $newvars[$id]['name']) { + $name = mysql_real_escape_string($newvars[$id]['name']); + $sets[] = "name = '$name'"; + } + if($vardata['identifier'] != $newvars[$id]['identifier']) { + $identifier = mysql_real_escape_string($newvars[$id]['identifier']); + $sets[] = "identifier = '$identifier'"; + } + if($vardata['datatypeid'] != $newvars[$id]['datatypeid']) { + if(! array_key_exists($newvars[$id]['datatypeid'], $datatypes)) + $newvars[$id]['datatypeid'] = $this->findDataTypeID($newvars[$id]['defaultvalue'], $datatypes); + $sets[] = "datatypeid = '{$newvars[$id]['datatypeid']}'"; + } + if($vardata['defaultvalue'] != $newvars[$id]['defaultvalue']) { + $defaultvalue = mysql_real_escape_string($newvars[$id]['defaultvalue']); + $sets[] = "defaultvalue = '$defaultvalue'"; + } + if($vardata['required'] != $newvars[$id]['required']) { + if($newvars[$id]['required'] == 0 || + $newvars[$id]['required'] == 1) + $sets[] = "required = '{$newvars[$id]['required']}'"; + } + if($vardata['ask'] != $newvars[$id]['ask']) { + if($newvars[$id]['ask'] == 0 || + $newvars[$id]['ask'] == 1) + $sets[] = "ask = '{$newvars[$id]['ask']}'"; + } + if(count($sets)) { + $allsets = implode(',', $sets); + $query = "UPDATE configvariable SET $allsets WHERE id = $id"; + doQuery($query); + } + unset($newvars[$id]); + } + if(count($deletes)) { + $alldels = implode(',', $deletes); + $query = "DELETE FROM configvariable WHERE id IN ($alldels)"; + doQuery($query); + } + if(count($newvars)) + $this->addNewConfigVars($newvars, $configid); + } + $vars['id'] = $configid; + $ret = array('status' => 'success', 'data' => $vars, 'action' => 'update'); + sendJSON($ret); + } + + + //////////////////////////////////////////////////////////////////////////////// + /// + /// \fn + /// + /// \brief Config + /// + //////////////////////////////////////////////////////////////////////////////// + function addNewConfigVars($newvars, $configid) { + $inserts = array(); + $datatypes = getConfigDataTypes(); + foreach($newvars as $var) { + $name = mysql_real_escape_string($var['name']); + $identifier = mysql_real_escape_string($var['identifier']); + $defaultvalue = mysql_real_escape_string($var['defaultvalue']); + if(! array_key_exists($var['datatypeid'], $datatypes)) + $var['datatypeid'] = $this->findDataTypeID($var['defaultvalue'], $datatypes); + $inserts[] = "('$name', " + . "$configid, " + . "'user', " + . "'$defaultvalue', " + . "{$var['required']}, " + . "{$var['ask']}, " + . "'$identifier', " + . "'{$var['datatypeid']}')"; + } + $allvars = implode(',', $inserts); + $query = "INSERT INTO configvariable " + . "(name, configid, `type`, defaultvalue, required, ask, identifier, datatypeid) " + . "VALUES $allvars"; + doQuery($query); + } + + + //////////////////////////////////////////////////////////////////////////////// + /// + /// \fn + /// + /// \brief Config + /// + //////////////////////////////////////////////////////////////////////////////// + function addResource($vars) { + $name = mysql_real_escape_string($vars['name']); + if($vars['type'] == 'Cluster') { + $query = "INSERT INTO config " + . "(name, " + . "ownerid, " + . "configtypeid, " + . "optional) " + . "VALUES " + . "('$name', " + . "{$vars['ownerid']}, " + . "(SELECT id FROM configtype WHERE prettyname = '{$vars['type']}'), " + . "{$vars['optional']})"; + doQuery($query); + $id = dbLastInsertID(); + $vals = array(); + foreach($vars['subimages'] as $sub) { + $item = "($id, {$sub['imageid']}, {$sub['min']}, {$sub['max']})"; + $vals[] = $item; + } + $allvals = implode(',', $vals); + $query = "INSERT INTO configsubimage " + . "(configid, " + . "imageid, " + . "mininstance, " + . "maxinstance) " + . "VALUES $allvals"; + doQuery($query); + } + else { + $data = mysql_real_escape_string($vars['data']); + $query = "INSERT INTO config " + . "(name, " + . "configtypeid, " + . "ownerid, " + . "optional, " + . "data) " + . "VALUES " + . "('$name', " + . "{$vars['typeid']}, " + . "{$vars['ownerid']}, " + . "{$vars['optional']}, " + . "'$data')"; + doQuery($query); + $id = dbLastInsertID(); + if(count($vars['configvariables'])) + $this->addNewConfigVars($vars['configvariables'], $id); + } + $query = "INSERT INTO resource " + . "(resourcetypeid, " + . "subid) " + . "VALUES " + . "((SELECT id FROM resourcetype WHERE name = 'config'), " + . "$id)"; + doQuery($query); + $key = getKey(array(array("{$this->restype}Admin"), array("administer"), 0, 1, 0)); + unset($_SESSION['userresources'][$key]); + $key = getKey(array(array("{$this->restype}Admin"), array("administer"), 0, 0, 0)); + unset($_SESSION['userresources'][$key]); + $ret = array('status' => 'success', 'action' => 'add'); + $ret['item'] = array('id' => $id, + 'name' => $vars['name'], + 'configtypeid' => $vars['typeid'], + 'configtype' => $vars['type'], + 'data' => $vars['data'], + 'ownerid' => $vars['ownerid'], + 'owner' => $vars['owner'], + 'optional' => $vars['optional'], + 'deleted' => 0); + sendJSON($ret); + } + + + //////////////////////////////////////////////////////////////////////////////// + /// + /// \fn + /// + /// \brief Config + /// + //////////////////////////////////////////////////////////////////////////////// + function processInput($configid) { + $return = array(); + $configtypes = getConfigTypes(); + $return['typeid'] = processInputVar('typeid', ARG_NUMERIC); + if(! array_key_exists($return['typeid'], $configtypes)) { + $this->errmsg = "Invalid type submitted"; + return 0; + } + $return['name'] = processInputVar('name', ARG_STRING); + if(! preg_match('/^([-a-zA-Z0-9\. ]){3,80}$/', $return['name'])) { + $this->errmsg = "The name can only contain letters, numbers, spaces, dashes(-)," + . "\\nand periods(.) and can be from 3 to 80 characters long"; + return 0; + } + # check for existance of name + $name = mysql_real_escape_string($return['name']); + $query = "SELECT id FROM config WHERE name = '$name' AND id != $configid"; + $qh = doQuery($query); + if(mysql_num_rows($qh)) { + $this->errmsg = "Another config with this name already exists."; + return 0; + } + # owner + $return['owner'] = processInputVar('owner', ARG_STRING); + if(! validateUserid($return['owner'])) { + $this->errmsg = "Invalid user submitted for owner"; + return 0; + } + $return['ownerid'] = getUserlistID($return['owner']); + if(is_null($return['owner'])) { + $this->errmsg = "Invalid user submitted for owner"; + return 0; + } + # optional + $return['optional'] = processInputVar('optional', ARG_NUMERIC); + if($return['optional'] !== '0' && $return['optional'] !== '1') { + $this->errmsg = "Invalid data submitted"; + return 0; + } + # type + $return['type'] = $configtypes[$return['typeid']]; + # cluster + if($return['type'] == 'Cluster') { + if(get_magic_quotes_gpc()) + $tmp = stripslashes($_POST['subimages']); + else + $tmp = $_POST['subimages']; + $tmp = json_decode($tmp, 1); + if(is_null($tmp)) { + $this->errmsg = "Invalid data submitted"; + return 0; + } + $resources = getUserResources(array("imageAdmin")); + $return['subimages'] = $tmp['items']; + foreach($return['subimages'] as $key => $sub) { + if(! array_key_exists($sub['imageid'], $resources['image'])) { + $this->errmsg = "Invalid subimage submitted"; + return 0; + } + elseif(! is_numeric($sub['min']) || $sub['min'] < 1 || $sub['min'] > MAXSUBIMAGES || + ! is_numeric($sub['max']) || $sub['max'] < 1 || $sub['max'] > MAXSUBIMAGES || + $sub['min'] > $sub['max']) { + $this->errmsg = "Invalid min/max value submitted for {$resources['image'][$sub['imageid']]}"; + return 0; + } + elseif($sub['deleted'] != 0 && $sub['deleted'] != 1) { + if($sub['id'] > 15000000) + unset($return['subimages'][$key]); + else + $return['subimages'][$key]['deleted'] = 0; + } + } + $return['data'] = ''; + } + # vlan + elseif($return['type'] == 'VLAN') { + $tmp = getContinuationVar('configdata'); + $vdata = $tmp['variables'][0]; + $return['data'] = processInputVar('vlanid', ARG_NUMERIC); + if($return['data'] < 1 || $return['data'] > 4095) { + $this->errmsg = "VLAN ID must be between 1 and 4095"; + return 0; + } + $var = array($vdata['id'] => + array('id' => $vdata['id'], + 'name' => 'VLAN', + 'identifier' => $vdata['identifier'], + 'datatypeid' => $vdata['datatypeid'], + 'defaultvalue' => $return['data'], + 'required' => '1', + 'ask' => '0', + 'deleted' => '0')); + $return['configvariables'] = $var; + } + # other + else { + # TODO may need more validation on data + $return['data'] = trim($_POST['data']); + if(get_magic_quotes_gpc()) + $return['data'] = stripslashes($return['data']); + if(! is_string($return['data']) || $return['data'] == '') { + $this->errmsg = "cannot be empty"; + return 0; + } + # TODO validate configvariable input + if(get_magic_quotes_gpc()) + $tmp = stripslashes($_POST['configvariables']); + else + $tmp = $_POST['configvariables']; + $tmp = json_decode($tmp, 1); + $return['configvariables'] = $tmp['items']; + } + return $return; + } + + //////////////////////////////////////////////////////////////////////////////// + /// + /// \fn + /// + /// \brief Config + /// + //////////////////////////////////////////////////////////////////////////////// + function addEditDialogHTML() { + # TODO add places for description fields + global $user; + # dialog for on page editing + $configtypes = getConfigTypes(); + $h = ''; + $h .= "<div dojoType=dijit.Dialog\n"; + $h .= " id=\"addeditdlg\"\n"; + $h .= " title=\"Edit {$this->restypename}\"\n"; + $h .= " duration=250\n"; + $h .= " draggable=true>\n"; + $h .= "<div id=\"addeditdlgcontent\">\n"; + # id + $h .= "<input type=\"hidden\" id=\"editresid\">\n"; + # type + $h .= "<label for=\"type\">Type:</label><span class=\"labeledform\">\n"; + $h .= selectInputHTML('', $configtypes, 'type', 'dojoType="dijit.form.Select" maxHeight="250" onChange="configSetType();"'); + $h .= "</span><br>\n"; + # config name + $h .= "<label for=\"name\">Name:</label><span class=\"labeledform\"><input type=\"text\" dojoType=\"dijit.form.ValidationTextBox\" "; + $h .= "id=\"name\" required=\"true\" invalidMessage=\"Name can only contain letters, numbers, "; + $h .= "spaces, dashes(-), parenthesis, <br>and periods(.) and can be from 3 to 80 characters long\" "; + $h .= "regExp=\"^([-a-zA-Z0-9\. \(\)]){3,80}$\" style=\"width: 300px\"></span><br>\n"; + # owner + $h .= "<label for=\"owner\">Owner:</label><span class=\"labeledform\"><input type=\"text\" dojoType=\"dijit.form.ValidationTextBox\" "; + $h .= "id=\"owner\" required=\"true\" invalidMessage=\"Unknown user\" style=\"width: 300px\" "; + $h .= "validator=\"checkOwner\" onKeyPress=\"setOwnerChecking\" value=\"{$user['unityid']}@{$user['affiliation']}\"></span><br>\n"; + $cont = addContinuationsEntry('AJvalidateUserid'); + $h .= "<input type=\"hidden\" id=\"valuseridcont\" value=\"$cont\">\n"; + # optional + $h .= "<label for=\"optionalchk\">Optional:</label>\n"; + $h .= "<span class=\"labeledform\"><input type=checkbox dojoType=dijit.form.CheckBox id=\"optionalchk\"></span><br>\n"; + # config data + $h .= "<div id=\"configdatadiv\">\n"; + $h .= "<span id=\"datalabel\" style=\"font-weight: bold;\"></span>:<br>\n"; + $h .= "<textarea id=\"data\" style=\"width: 40em; height: 10em;\"></textarea>\n"; + $h .= "</div>\n"; #configdatadiv + + # subimage extra + $h .= "<div id=\"subimageextradiv\" class=\"hidden\"><br>\n"; + # subimage + $h .= "<b>Subimages</b>:<br>\n"; + $resources = getUserResources(array("imageAdmin")); + # TODO possibly populate this after page load + if(USEFILTERINGSELECT && count($resources['image']) < FILTERINGSELECTTHRESHOLD) + $h .= selectInputHTML('', $resources['image'], 'subimageid', 'dojoType="dijit.form.FilteringSelect"'); + else + $h .= selectInputHTML('', $resources['image'], 'subimageid', 'dojoType="dijit.form.Select" maxHeight="250"'); + # add subimage button + $h .= "<button dojoType=\"dijit.form.Button\" id=\"addsubimagebtn\">\n"; + $h .= " Add Subimage\n"; + $h .= " <script type=\"dojo/method\" event=\"onClick\">\n"; + $h .= " addCfgSubimage();\n"; + $h .= " </script>\n"; + $h .= "</button>\n"; + # list of subimages + $h .= "<div id=\"subimagegriddiv\">\n"; + # TODO - figure out how to get an embedded widget in a cell + $h .= "<table dojoType=\"dojox.grid.DataGrid\" jsId=\"subimagegrid\" "; + $h .= "style=\"width: 350px; height: 300px;\" "; + $h .= "selectionMode=\"extended\" "; + $h .= "sortInfo=\"1\">\n"; + $h .= "<thead>\n"; + $h .= "<tr>\n"; + $h .= "<th field=\"name\" width=\"270px\"></th>\n"; + $h .= "<th field=\"min\" width=\"30px\" editable=\"true\"></th>\n"; + $h .= "<th field=\"max\" width=\"30px\" editable=\"true\"></th>\n"; + $h .= "</tr>\n"; + $h .= "</thead>\n"; + $h .= "</table>\n"; + $h .= "</div>\n"; # subimagegriddiv + # remove subimages button + $h .= "<button dojoType=\"dijit.form.Button\" id=\"remsubimagebtn\">\n"; + $h .= " Remove Selected Subimage(s)\n"; + $h .= " <script type=\"dojo/method\" event=\"onClick\">\n"; + $h .= " removeSubimages();\n"; + $h .= " </script>\n"; + $h .= "</button><br><br>\n"; + $h .= "</div>\n"; #subimageextradiv + + # vlan extra + $h .= "<div id=\"vlanextradiv\" class=\"hidden\">\n"; + # vlan id + $h .= "<label for=\"vlanid\">VLAN ID:</label>\n"; + $h .= "<span class=\"labeledform\"><input dojoType=\"dijit.form.NumberSpinner\" value=\"1\" "; + $h .= "smallDelta=1 largeDelta=5 "; + $h .= "constraints=\"{min:1, max:4095}\" id=\"vlanid\" required=\"true\" "; + $h .= "style=\"width: 70px\"/></span><br>\n"; + $h .= "</div>\n"; #vlanextradiv + + # config variables + #$h .= "<div id=\"configvariables\" class=\"hidden\">\n"; + $h .= "<div id=\"configvariables\">\n"; + $h .= "<h3 align=\"center\">Config Variables</h3>\n"; + $h .= "<table summary=\"\"><tr valign=\"top\"><td>\n"; + # list of variables + $h .= "<div id=\"configvariablegriddiv\">\n"; + $h .= "Select a variable:<br>\n"; + $h .= "<table dojoType=\"dojox.grid.DataGrid\" jsId=\"configvariablegrid\" "; + $h .= "style=\"width: 150px; height: 125px;\" query=\"{inout: 1}\" "; + $h .= "selectionMode=\"single\" "; + $h .= "onSelected=\"configVarSelected\" "; + $h .= "onCanSelect=\"configVarAllowSelection\" "; + $h .= "sortInfo=\"1\">\n"; + $h .= " <script type=\"dojo/connect\" event=\"onStyleRow\" args=\"row\">\n"; + $h .= " configVarListStyle(row);\n"; + $h .= " </script>\n"; + $h .= "<thead>\n"; + $h .= "<tr>\n"; + $h .= "<th field=\"name\" width=\"150px\"></th>\n"; + $h .= "</tr>\n"; + $h .= "</thead>\n"; + $h .= "</table>\n"; + $h .= "</div>\n"; + $h .= "<button dojoType=\"dijit.form.Button\" id=\"newcfgvarbtn\">\n"; + $h .= " Add New Variable\n"; + $h .= " <script type=\"dojo/method\" event=\"onClick\">\n"; + $h .= " addNewConfigVar();\n"; + $h .= " </script>\n"; + $h .= "</button>\n"; + $h .= "</td><td>\n"; + # edit variable + $h .= "<div id=\"editcfgvardiv\" class=\"hidden\">\n"; + # id + $h .= "<input type=\"hidden\" id=\"varid\">\n"; + # name + $h .= "<label for=\"varname\">Name:</label><span class=\"labeledform\">\n"; + $h .= "<input type=\"text\" dojoType=\"dijit.form.ValidationTextBox\" "; + $h .= "id=\"varname\" required=\"true\" invalidMessage=\"Name can only contain letters, numbers, "; + $h .= "spaces, dashes(-), parenthesis, <br>and periods(.) and can be from 3 to 80 characters long\" "; + $h .= "regExp=\"^([-a-zA-Z0-9\. \(\)]){3,80}$\" style=\"width: 120px\" "; + $h .= "onKeyPress=\"delayedUpdateConfigVariable\"></span><br>\n"; + # key + $h .= "<label for=\"varidentifier\">Identifier:</label><span class=\"labeledform\">\n"; + $h .= "<input type=\"text\" dojoType=\"dijit.form.ValidationTextBox\" "; + $h .= "id=\"varidentifier\" invalidMessage=\"Key can only contain letters, numbers, "; # TODO determine constraints, if any + $h .= "dashes(-), underscores(_), <br>and percents(%) and can be from 3 to 20 characters long\" "; + $h .= "regExp=\"^([-_A-Za-z0-9%]){3,20}$\" style=\"width: 120px\" "; + $h .= "onKeyPress=\"delayedUpdateConfigVariable\"></span><br>\n"; + # type + $h .= "<label id=\"cfgvartypelbl\" for=\"vartypespan\">Type:</label><span class=\"labeledform\" id=\"vartypespan\">"; + $datatypes = getConfigDataTypes(); + $h .= selectInputHTML('', $datatypes, 'cfgvartype', 'dojoType="dijit.form.Select" maxHeight="250" onChange="setCfgVarType();"'); + $h .= "</span><br>\n"; + # value - bool + $h .= "<span id=\"vartypeboolspan\">\n"; + $h .= "<label for=\"vartypebool\">Value:</label>\n"; + $h .= "<span class=\"labeledform\">"; + $h .= selectInputAutoDijitHTML('', array('true', 'false'), 'vartypebool', 'onChange="delayedUpdateConfigVariable();"'); + $h .= "</span><br>\n"; + $h .= "</span>\n"; # vartypeboolspan + # value - int + $h .= "<span id=\"vartypeintspan\">\n"; + $h .= "<label for=\"vartypeint\">Value:</label>\n"; + $h .= "<span class=\"labeledform\"><input dojoType=\"dijit.form.NumberSpinner\" value=\"1\" "; + $h .= "id=\"vartypeint\" intermediateChanges=\"true\" constraints=\"{places:0}\" "; + $h .= "onChange=\"delayedUpdateConfigVariable\" style=\"width: 70px\"/>"; + $h .= "</span><br>\n"; + $h .= "</span>\n"; # vartypeintspan + # value - float + $h .= "<span id=\"vartypefloatspan\">\n"; + $h .= "<label for=\"vartypefloat\">Value:</label>\n"; + $h .= "<span class=\"labeledform\"><input dojoType=\"dijit.form.NumberSpinner\" value=\"1\" "; + $h .= "id=\"vartypefloat\" intermediateChanges=\"true\" "; + $h .= "onChange=\"delayedUpdateConfigVariable\" style=\"width: 70px\"/>"; + $h .= "</span><br>\n"; + $h .= "</span>\n"; # vartypefloatspan + # value - string + $h .= "<span id=\"vartypestringspan\" class=\"hidden\">\n"; + $h .= "<label for=\"vartypestring\">Value:</label><span class=\"labeledform\">\n"; + $h .= "<input type=\"text\" dojoType=\"dijit.form.ValidationTextBox\" "; + $h .= "id=\"vartypestring\" invalidMessage=\"Value can only contain letters, numbers, "; # TODO determine constraints, if any, also update in requests.php + $h .= "spaces, dashes(-), parenthesis, <br>slashes(/) and periods(.) and can be from 3 to 255 characters long\" "; + $h .= "regExp=\"^([-a-zA-Z0-9\. \(\)/]){3,255}$\" style=\"width: 120px\" "; + $h .= "onKeyPress=\"delayedUpdateConfigVariable\"></span><br>\n"; + $h .= "</span>\n"; # vartypestringspan + # value - text + $h .= "<span id=\"vartypetextspan\" class=\"hidden\">\n"; + $h .= "<label for=\"vartypetext\">Value:</label><span class=\"labeledform\">\n"; + $h .= "<div dojoType=\"dijit.form.Textarea\" "; + $h .= "id=\"vartypetext\" style=\"width: 240px\" "; # TODO determine constraints, if any + $h .= "onKeyPress=\"delayedUpdateConfigVariable\"></div></span><br>\n"; + $h .= "</span>\n"; # vartypetextspan + # required + $h .= "<label for=\"varrequired\">Required:</label>\n"; + $h .= "<span class=\"labeledform\"><input dojoType=\"dijit.form.CheckBox\" "; + $h .= "type=\"checkbox\" id=\"varrequired\" onChange=\"updateConfigVariable\"></span><br>\n"; + # ask + $h .= "<label for=\"varask\">Prompt for Value:</label>\n"; # TODO need better label name + $h .= "<span class=\"labeledform\"><input dojoType=\"dijit.form.CheckBox\" "; + $h .= "type=\"checkbox\" id=\"varask\" onChange=\"updateConfigVariable\"></span><br>\n"; + # delete button + $h .= "<span class=\"labeledform\">\n"; + $h .= "<button dojoType=\"dijit.form.Button\" disabled=\"true\" id=\"deletecfgvarbtn\">\n"; + $h .= " Delete Variable\n"; + $h .= " <script type=\"dojo/method\" event=\"onClick\">\n"; + $h .= " deleteConfigVariable();\n"; + $h .= " </script>\n"; + $h .= "</button></span>\n"; + $h .= "</div>\n"; # editcfgvardiv + # undelete button + $h .= "<div id=\"undeletecfgvardiv\" class=\"hidden labeledform\">\n"; + $h .= "<button dojoType=\"dijit.form.Button\">\n"; + $h .= " Undelete Variable\n"; + $h .= " <script type=\"dojo/method\" event=\"onClick\">\n"; + $h .= " undeleteConfigVariable();\n"; + $h .= " </script>\n"; + $h .= "</button>\n"; + $h .= "</div>\n"; # undeletecfgvardiv + + $h .= "</td></tr></table>\n"; + + $h .= "</div>\n"; # configvariables + + $h .= "</div>\n"; # addeditdlgcontent + + + $h .= "<div id=\"addeditdlgerrmsg\" class=\"nperrormsg\"></div>\n"; + $h .= "<div id=\"editdlgbtns\" align=\"center\">\n"; + $h .= "<button dojoType=\"dijit.form.Button\" id=\"addeditbtn\">\n"; + $h .= " Confirm\n"; + $h .= " <script type=\"dojo/method\" event=\"onClick\">\n"; + $h .= " saveResource();\n"; + $h .= " </script>\n"; + $h .= "</button>\n"; + $h .= "<button dojoType=\"dijit.form.Button\">\n"; + $h .= " Cancel\n"; + $h .= " <script type=\"dojo/method\" event=\"onClick\">\n"; + $h .= " dijit.byId('addeditdlg').hide();\n"; + $h .= " </script>\n"; + $h .= "</button>\n"; + $h .= "</div>\n"; # editdlgbtns + $h .= "</div>\n"; + return $h; + } + + //////////////////////////////////////////////////////////////////////////////// + /// + /// \fn + /// + /// \brief Config + /// + //////////////////////////////////////////////////////////////////////////////// + function editConfigMap() { + $h = ''; + $h = "<h2>Config Mapping</h2>\n"; + + $cont = addContinuationsEntry('AJeditConfigMapping', $this->basecdata); + $h .= "<input type=\"hidden\" id=\"editcfgmapcont\" value=\"$cont\">\n"; + $cdata = $this->basecdata; + $cdata['add'] = 1; + $cont = addContinuationsEntry('AJsaveConfigMapping', $cdata); + $h .= "<input type=\"hidden\" id=\"addcfgmapcont\" value=\"$cont\">\n"; + $h .= "<input type=\"hidden\" id=\"savecfgmapcont\">\n"; + $cont = addContinuationsEntry('AJdeleteConfigMapping', $this->basecdata); + $h .= "<input type=\"hidden\" id=\"deletecfgmapcont\" value=\"$cont\">\n"; + + $h .= "<button dojoType=\"dijit.form.Button\">\n"; + $h .= " Add New Config Mapping\n"; + $h .= " <script type=\"dojo/method\" event=\"onClick\">\n"; + $h .= " addConfigMapping();\n"; + $h .= " </script>\n"; + $h .= "</button>\n"; + + # filters + $h .= "<div dojoType=\"dijit.TitlePane\" title=\"Filters (click to expand)\" "; + $h .= "open=\"false\">\n"; + $h .= "<strong>Config Name</strong>:\n"; + $h .= "<div dojoType=\"dijit.form.TextBox\" id=\"confignamefilter\" length=\"80\">"; + $h .= " <script type=\"dojo/connect\" event=\"onKeyUp\" args=\"event\">\n"; + $h .= " if(event.keyCode == 13) configmapGridFilter();\n"; + $h .= " </script>\n"; + $h .= "</div>\n"; + $h .= "<button dojoType=\"dijit.form.Button\">\n"; + $h .= " Apply Name Filter\n"; + $h .= " <script type=\"dojo/method\" event=\"onClick\">\n"; + $h .= " configmapGridFilter();\n"; + $h .= " </script>\n"; + $h .= "</button><br>\n"; + $h .= "<strong>Displayed Fields</strong>:<br>\n"; + $h .= "<input type=\"checkbox\" id=\"chkmtype\" checked onClick=\"toggleCmapFieldDisplay(this, 'configmaptype')\">"; + $h .= "<label for=\"chkmtype\">Map Type</label><br>\n"; + $h .= "<input type=\"checkbox\" id=\"chkname\" checked onClick=\"toggleCmapFieldDisplay(this, 'configname')\">"; + $h .= "<label for=\"chkname\">Config Name</label><br>\n"; + $h .= "<input type=\"checkbox\" id=\"chkctype\" checked onClick=\"toggleCmapFieldDisplay(this, 'configtype')\">"; + $h .= "<label for=\"chkctype\">Config Type</label><br>\n"; + $h .= "<input type=\"checkbox\" id=\"chkmto\" checked onClick=\"toggleCmapFieldDisplay(this, 'mapto')\">"; + $h .= "<label for=\"chkmto\">Map To</label><br>\n"; + $h .= "<input type=\"checkbox\" id=\"chkaffil\" onClick=\"toggleCmapFieldDisplay(this, 'affiliation')\">"; + $h .= "<label for=\"chkaffil\">Affiliation</label><br>\n"; + $h .= "<input type=\"checkbox\" id=\"chkdisabled\" onClick=\"toggleCmapFieldDisplay(this, 'disabled')\">"; + $h .= "<label for=\"chkdisabled\">Disabled</label><br>\n"; + $h .= "<input type=\"checkbox\" id=\"chkstage\" onClick=\"toggleCmapFieldDisplay(this, 'configstage')\">"; + $h .= "<label for=\"chkstage\">Stage</label><br>\n"; + /*$h .= "<strong>Owner</strong>:\n"; + $h .= "<select dojoType=\"dijit.form.Select\" id=\"ownerfilter\" "; + $h .= "onChange=\"usergroupGridFilter();\" maxHeight=\"250\"></select><br>\n"; + if($showusergrouptype) { + $h .= "<strong>Type</strong>:\n"; + $h .= "<label for=\"shownormal\">Normal</label>\n"; + $h .= "<input type=\"checkbox\" dojoType=\"dijit.form.CheckBox\" "; + $h .= "id=\"shownormal\" onChange=\"usergroupGridFilter();\" "; + $h .= "checked=\"checked\"> | \n"; + $h .= "<label for=\"showfederated\">Federated</label>\n"; + $h .= "<input type=\"checkbox\" dojoType=\"dijit.form.CheckBox\" "; + $h .= "id=\"showfederated\" onChange=\"usergroupGridFilter();\" "; + $h .= "checked=\"checked\"> | \n"; + $h .= "<label for=\"showcourseroll\">Course Roll</label>\n"; + $h .= "<input type=\"checkbox\" dojoType=\"dijit.form.CheckBox\" "; + $h .= "id=\"showcourseroll\" onChange=\"usergroupGridFilter();\" "; + $h .= "checked=\"checked\"><br>\n"; + } + $h .= "<strong>Editable by</strong>:\n"; + $h .= "<select dojoType=\"dijit.form.Select\" id=\"editgroupfilter\" "; + $h .= "onChange=\"usergroupGridFilter();\" maxHeight=\"250\"></select><br>\n";*/ + $h .= "</div>\n"; + + $cont = addContinuationsEntry('jsonConfigMapStore', $this->basecdata); + $h .= "<div dojoType=\"dojo.data.ItemFileWriteStore\" url=\"" . BASEURL; + $h .= SCRIPT . "?continuation=$cont\" jsid=\"configmapstore\"></div>\n"; + + $h .= "<div id=\"gridcontainer\">\n"; + $h .= "<table dojoType=\"dojox.grid.DataGrid\" jsId=\"configmapgrid\" "; + $h .= "sortInfo=3 store=\"configmapstore\" autoWidth=\"true\" style=\""; + #$h .= "height: 580px;\" query=\"{type: new RegExp('normal|federated|courseroll')}\">\n"; + $h .= "height: 580px;\">\n"; + $h .= "<thead>\n"; + $h .= "<tr>\n"; + if(preg_match('/MSIE/i', $_SERVER['HTTP_USER_AGENT'])) + $w = array('64px', '38px', '70px', '170px', '80px', '120px', '100px', '59px', '85px'); + else + $w = array('5em', '3em', '6em', '14em', '7em', '11em', '9em', '5em', '7.2em'); + $h .= "<th field=\"id\" width=\"{$w[0]}\" formatter=\"fmtConfigMapDeleteBtn\"> </th>\n"; + $h .= "<th field=\"id\" width=\"{$w[1]}\" formatter=\"fmtConfigMapEditBtn\"> </th>\n"; + $h .= "<th field=\"configmaptype\" width=\"{$w[2]}\">Map Type</th>\n"; + $h .= "<th field=\"configname\" width=\"{$w[3]}\">Config Name</th>\n"; + $h .= "<th field=\"configtype\" width=\"{$w[4]}\">Config Type</th>\n"; + $h .= "<th field=\"mapto\" width=\"{$w[5]}\">Map To</th>\n"; + $h .= "<th field=\"affiliation\" width=\"{$w[6]}\" hidden=\"true\">Affiliation</th>\n"; + $h .= "<th field=\"disabled\" width=\"{$w[7]}\" hidden=\"true\">Disabled</th>\n"; + $h .= "<th field=\"configstage\" width=\"{$w[8]}\" hidden=\"true\">Stage</th>\n"; + $h .= "</tr>\n"; + $h .= "</thead>\n"; + $h .= "</table>\n"; + $h .= "</div>\n"; + + # add/edit dialog + $configs = $this->_getData(); + $maptypes = getConfigMapTypes(1); + $h .= "<div dojoType=dijit.Dialog\n"; + $h .= " id=\"addeditcfgmapdlg\"\n"; + $h .= " title=\"Add Config Mapping\"\n"; + $h .= " duration=250\n"; + $h .= " draggable=true>\n"; + $h .= "<div id=\"addeditcfgmapdlgcontent\">\n"; + $h .= "<input type=\"hidden\" id=\"editcfgmapid\" />\n"; + # config + $cont = addContinuationsEntry('jsonResourceStore', $this->basecdata); + $h .= "<div dojoType=\"dojo.data.ItemFileReadStore\" url=\"" . BASEURL; + $h .= SCRIPT . "?continuation=$cont\" jsid=\"mapconfigliststore\"></div>\n"; + $h .= "<label for=\"config\">Config:</label>\n"; # TODO may want to present configs with config types + if(USEFILTERINGSELECT && count($configs) < FILTERINGSELECTTHRESHOLD) + $dtype = 'dijit.form.FilteringSelect'; + else + $dtype = 'dijit.form.Select'; + $h .= "<select id=\"config\" dojoType=\"$dtype\" "; + $h .= "onChange=\"configMapSetConfig();\" store=\"mapconfigliststore\" "; + $h .= "fetchProperties=\"{sort: [{attribute: 'name'}]}\" "; # TODO ignore case + $h .= "query=\"{deleted: '0'}\" queryExpr=\"*\${0}*\">\n"; + $h .= "</select>\n"; + $h .= "<br>\n"; + # type + $h .= "Type: <span id=\"mapconfigtype\"></span><br><br>\n"; + # maps to + $h .= "<strong><big>Maps to:</big></strong><br>\n"; + # map type + $h .= "<script>\n"; + $h .= "var maptypedata = {identifier: 'id', label: 'name', items: [\n"; + $types = array(); + foreach($maptypes as $id => $name) { + $t = " {id: '$id', name: '$name', "; + if($name == 'Image' || $name == 'Subimage') + $t .= "clusterok: '1'}"; + else + $t .= "clusterok: '0'}"; + $types[] = $t; + } + $h .= implode(",\n", $types); + $h .= "\n]}\n"; + $h .= "</script>\n"; + $h .= "<div dojoType=\"dojo.data.ItemFileReadStore\" data=\"maptypedata\" "; + $h .= "jsid=\"maptypestore\"></div>\n"; + $h .= "<br>Map type: "; + $h .= "<select id=\"maptype\" dojoType=\"dijit.form.Select\" store=\"maptypestore\" "; + $h .= "onChange=\"editConfigMapSetMapType();\" query=\"{id: '*'}\"></select>\n"; + + # image + $h .= "<div id=\"imagetypediv\" class=\"hidden\">\n"; + $tmp = getUserResources(array("imageAdmin"), array("administer")); # TODO is this the criteria we want for which images can be selected? + $images = $tmp['image']; + $h .= "<label for=\"image\">Image:</label>\n"; + $h .= selectInputAutoDijitHTML('', $images, 'image'); + $h .= "</div>\n"; # imagetypediv + # os type + $ostypes = getOStypes(); + $h .= "<div id=\"ostypediv\" class=\"hidden\">\n"; + $h .= "<label for=\"ostype\">OS Type:</label>\n"; + $h .= selectInputAutoDijitHTML('', $ostypes, 'ostype'); + $h .= "</div>\n"; # ostypediv + # os + $oses = getOSList(); + $h .= "<div id=\"osdiv\" class=\"hidden\">\n"; + $h .= "<label for=\"os\">OS:</label>\n"; + $h .= selectInputAutoDijitHTML('', $oses, 'os'); + $h .= "</div>\n"; # osdiv + # config + $tmp = getUserResources(array("configAdmin"), array("administer")); # TODO is this the criteria we want for which configs can be selected? + $configs = $this->getUserConfigsNoCluster($tmp['config']); + $h .= "<div id=\"configdiv\" class=\"hidden\">\n"; + $h .= "<label for=\"mapconfig\">Config:</label>\n"; + $h .= selectInputAutoDijitHTML('', $configs, 'mapconfig'); + $h .= "</div>\n"; # configdiv + # configsubimage + $configsubimages = getConfigSubimages($tmp['config']); + $h .= "<div id=\"configsubimagediv\" class=\"hidden\">\n"; + $h .= "<label for=\"configsubimage\">Cluster:</label>\n"; + $h .= selectInputAutoDijitHTML('', $configsubimages, 'configsubimage'); + $h .= "</div>\n"; # configsubimagediv + # managementnode + $managementnodes = getManagementNodes(); + $h .= "<div id=\"managementnodediv\" class=\"hidden\">\n"; + $h .= "<label for=\"managementnode\">Management Node:</label>\n"; + $h .= selectInputAutoDijitHTML('', $managementnodes, 'managementnode'); + $h .= "</div>\n"; # managementnodediv + + $h .= "<br><strong><big>Additional options:</big></strong><br>\n"; + # affiliation + $affils = getAffiliations(); + $h .= "<br><label for=\"affil\">Affiliation:</label>\n"; + $h .= selectInputAutoDijitHTML('', $affils, 'affil'); + # stage + $stages = $this->getConfigMapStages(); + $h .= "<div id=\"stagediv\" class=\"hidden\">\n"; + $h .= "<label for=\"stage\">Stage:</label>\n"; + $h .= selectInputAutoDijitHTML('', $stages, 'stage'); + $h .= "</div>\n"; # stagediv + $h .= "</div>\n"; # addeditcfgmapdlgcontent + + $h .= "<div id=\"addeditcfgmapdlgerrmsg\" class=\"nperrormsg\"></div>\n"; + $h .= "<div id=\"editdlgbtns\" align=\"center\">\n"; + $h .= "<button dojoType=\"dijit.form.Button\" id=\"addeditcfgmapbtn\">\n"; + $h .= " Confirm\n"; + $h .= " <script type=\"dojo/method\" event=\"onClick\">\n"; + $h .= " saveConfigMapping();\n"; + $h .= " </script>\n"; + $h .= "</button>\n"; + $h .= "<button dojoType=\"dijit.form.Button\">\n"; + $h .= " Cancel\n"; + $h .= " <script type=\"dojo/method\" event=\"onClick\">\n"; + $h .= " dijit.byId('addeditcfgmapdlg').hide();\n"; + $h .= " resetConfigMappingFields();\n"; + $h .= " </script>\n"; + $h .= "</button>\n"; + $h .= "</div>\n"; # editdlgbtns + $h .= "</div>\n"; + + # delete dialog + $h .= "<div dojoType=dijit.Dialog\n"; + $h .= " id=\"delcfgmapdlg\"\n"; + $h .= " title=\"Delete Config Mapping\"\n"; + $h .= " duration=250\n"; + $h .= " draggable=true>\n"; + $h .= "<div id=\"delcfgmapdlgcontent\"></div><br>\n"; + $h .= "<input type=\"hidden\" id=\"submitdeletecfgmapcont\">\n"; + $h .= "<div id=\"delcfgmapdlgerrmsg\" class=\"nperrormsg\"></div>\n"; + $h .= "<div id=\"delcfgmapdlgbtns\" align=\"center\">\n"; + $h .= "<button dojoType=\"dijit.form.Button\" id=\"delcfgmapbtn\">\n"; + $h .= " Delete Mapping\n"; + $h .= " <script type=\"dojo/method\" event=\"onClick\">\n"; + $h .= " submitDeleteConfigMapping();\n"; + $h .= " </script>\n"; + $h .= "</button>\n"; + $h .= "<button dojoType=\"dijit.form.Button\">\n"; + $h .= " Cancel\n"; + $h .= " <script type=\"dojo/method\" event=\"onClick\">\n"; + $h .= " dijit.byId('delcfgmapdlg').hide();\n"; + $h .= " dojo.byId('delcfgmapdlgcontent').innerHTML = '';\n"; + $h .= " dojo.byId('delcfgmapdlgerrmsg').innerHTML = '';\n"; + $h .= " </script>\n"; + $h .= "</button>\n"; + $h .= "</div>\n"; # delcfgmapdlgbtns + $h .= "</div>\n"; + + print $h; + } + + //////////////////////////////////////////////////////////////////////////////// + /// + /// \fn + /// + /// \brief Config + /// + //////////////////////////////////////////////////////////////////////////////// + function jsonConfigMapStore() { + global $user; + $query = "SELECT cm.id AS id, " + . "c.id as configid, " + . "c.name as configname, " + . "c.description as description, " + . "c.configtypeid AS configtypeid, " + . "ct.prettyname AS configtype, " + . "cm.configmaptypeid, " + . "cmt.prettyname AS configmaptype, " + . "cm.affiliationid, " + . "a.name AS affiliation, " + . "cm.disabled, " + . "cm.configstageid, " + . "cms.name AS configstage, " + . "i.prettyname AS image, " + . "c2.name AS maptoconfig, " + . "i2.prettyname AS subimage, " + . "c3.name AS subimageconfig, " + . "o.prettyname AS os, " + . "ot.name AS ostype " + . "FROM config c, " + . "configtype ct, " + . "configmaptype cmt, " + . "configstage cms, " + . "configmap cm " + . "LEFT JOIN affiliation a ON (cm.affiliationid = a.id) " + . "LEFT JOIN image i ON (cm.subid = i.id) " + . "LEFT JOIN config c2 ON (cm.subid = c2.id) " + . "LEFT JOIN configsubimage csi ON (cm.subid = csi.id) " + . "LEFT JOIN config c3 ON (csi.configid = c3.id) " + . "LEFT JOIN image i2 ON (csi.imageid = i2.id) " + . "LEFT JOIN OS o ON (cm.subid = o.id) " + . "LEFT JOIN OStype ot ON (cm.subid = ot.id) " + . "WHERE cm.configid = c.id AND " + . "c.configtypeid = ct.id AND " + . "cm.configmaptypeid = cmt.id AND " + . "cm.configstageid = cms.id AND " + . "c.deleted = 0"; + $configmaps = array(); + $qh = doQuery($query); + while($row = mysql_fetch_assoc($qh)) { + switch($row['configmaptype']) { + case "Image": + $row['mapto'] = $row['image']; + break; + case "Config": + $row['mapto'] = $row['maptoconfig']; + break; + case "Subimage": + $row['mapto'] = "{$row['subimageconfig']} - {$row['subimage']}"; + break; + case "OS": + $row['mapto'] = $row['os']; + break; + case "OS Type": + $row['mapto'] = $row['ostype']; + break; + } + unset($row['image']); + unset($row['maptoconfig']); + unset($row['subimage']); + unset($row['subimagesubimage']); + unset($row['os']); + unset($row['ostype']); + $configmaps[] = $row; + } + sendJSON($configmaps, 'id'); + } + + //////////////////////////////////////////////////////////////////////////////// + /// + /// \fn + /// + /// \brief Config + /// + //////////////////////////////////////////////////////////////////////////////// + function AJeditConfigMapping() { + $configmapid = processInputVar('configmapid', ARG_NUMERIC); + # TODO check access - who is allowed to map/unmap? + $data = $this->getConfigMapData($configmapid); + if(is_null($data)) { + $ret = array('status' => 'notfound'); + sendJSON($ret); + return; + } + $cdata = $this->basecdata; + $cdata['configmapid'] = $configmapid; + $cdata['mapdata'] = $data; + $cont = addContinuationsEntry('AJsaveConfigMapping', $cdata); + $ret = array('status' => 'success', 'data' => $data, 'cont' => $cont); + sendJSON($ret); + } + + //////////////////////////////////////////////////////////////////////////////// + /// + /// \fn + /// + /// \brief Config + /// + //////////////////////////////////////////////////////////////////////////////// + function AJsaveConfigMapping() { + $add = getContinuationVar('add', 0); + $maptypes = getConfigMapTypes(1); + if(! $data = $this->processMappingInput($maptypes)) { + sendJSON(array('status' => 'error', 'msg' => $this->errmsg)); + return; + } + if($add) { + $this->addConfigMapping($data, $maptypes); + return; + } + $configmapid = getContinuationVar('configmapid', 0); + $id = $data['configid']; + $configdata = $this->_getData($id); + $curdata = getContinuationVar('mapdata'); + $sets = array(); + if($curdata['configid'] != $data['configid']) + $sets[] = "configid = {$data['configid']}"; + if($curdata['configmaptypeid'] != $data['maptypeid']) + $sets[] = "configmaptypeid = {$data['maptypeid']}"; + if($curdata['subid'] != $data['subid']) + $sets[] = "subid = {$data['subid']}"; + if($curdata['affiliationid'] != $data['affiliationid']) + $sets[] = "affiliationid = {$data['affiliationid']}"; + if(is_null($configdata[$id]['configstageid'])) { + if($curdata['stageid'] != $data['stageid']) + $sets[] = "configstageid = {$data['stageid']}"; + } + else + $sets[] = "configstageid = {$configdata[$id]['configstageid']}"; + if(count($sets)) { + $allsets = implode(',', $sets); + $query = "UPDATE configmap SET $allsets WHERE id = $configmapid"; + doQuery($query); + } + $stages = $this->getConfigMapStages(); + $item = array('id' => $configmapid, + 'configid' => $id, + 'configname' => $configdata[$id]['name'], + 'configtypeid' => $configdata[$id]['configtypeid'], + 'configtype' => $configdata[$id]['configtype'], + 'configmaptypeid' => $data['maptypeid'], + 'configmaptype' => $maptypes[$data['maptypeid']], + 'mapto' => $data['mapto'], + 'affiliationid' => $data['affiliationid'], + 'affiliation' => getAffiliationName($data['affiliationid']), + 'disabled' => $curdata['disabled'], + 'stageid' => $data['stageid'], + 'configstage' => $stages[$data['stageid']]); + $ret = array('status' => 'success', 'data' => $item, 'action' => 'update'); + sendJSON($ret); + } + + //////////////////////////////////////////////////////////////////////////////// + /// + /// \fn + /// + /// \brief Config + /// + //////////////////////////////////////////////////////////////////////////////// + function addConfigMapping($data, $maptypes) { + $configdata = $this->_getData($data['configid']); + if(is_null($configdata[$data['configid']]['configstageid'])) + $stageid = $data['stageid']; + else + $stageid = $configdata[$data['configid']]['configstageid']; + $query = "INSERT INTO configmap " + . "(configid, " + . "configmaptypeid, " + . "subid, " + . "affiliationid, " + . "disabled, " + . "configstageid) " + . "VALUES " + . "({$data['configid']}, " + . "{$data['maptypeid']}, " + . "{$data['subid']}, " + . "{$data['affiliationid']}, " + . "0, " + . "$stageid)"; + doQuery($query); + $configmapid = dbLastInsertID(); + $id = $data['configid']; + $configdata = $this->_getData($id); + $stages = $this->getConfigMapStages(); + $item = array('id' => $configmapid, + 'configid' => $id, + 'configname' => $configdata[$id]['name'], + 'description' => $configdata[$id]['description'], + 'configtypeid' => $configdata[$id]['configtypeid'], + 'configtype' => $configdata[$id]['configtype'], + 'configmaptypeid' => $data['maptypeid'], + 'configmaptype' => $maptypes[$data['maptypeid']], + 'affiliationid' => $data['affiliationid'], + 'mapto' => $data['mapto'], + 'affiliation' => getAffiliationName($data['affiliationid']), + 'disabled' => 0, + 'stageid' => $data['stageid'], + 'configstage' => $stages[$data['stageid']]); + $ret = array('status' => 'success', 'item' => $item, 'action' => 'add'); + sendJSON($ret); + return; + } + + //////////////////////////////////////////////////////////////////////////////// + /// + /// \fn + /// + /// \brief Config + /// + //////////////////////////////////////////////////////////////////////////////// + function AJdeleteConfigMapping() { + $configmapid = processInputVar('configmapid', ARG_NUMERIC); + # TODO check access - who is allowed to map/unmap? + $data = $this->getConfigMapData($configmapid); + if(is_null($data)) { + $ret = array('status' => 'notfound'); + sendJSON($ret); + return; + } + $h = ''; + $h .= "Delete the following config mapping?<br><br>"; + $h .= "<strong>Config</strong>: {$data['configname']}<br><br>"; + $subname = $this->getMapSubName($data['prettyconfigmaptype'], $data['subid']); + $h .= "<strong>{$data['prettyconfigmaptype']}</strong>: $subname<br><br>"; + $h .= "<strong>Additional options</strong>:<br>"; + $h .= "Affiliation: {$data['affiliation']}<br>"; + $h .= "Stage: {$data['stage']}"; + $cdata = $this->basecdata; + $cdata['configmapid'] = $configmapid; + $cont = addContinuationsEntry('AJsubmitDeleteConfigMapping', $cdata, SECINDAY, 1, 0); + $ret = array('status' => 'success', 'html' => $h, 'cont' => $cont); + sendJSON($ret); + } + + //////////////////////////////////////////////////////////////////////////////// + /// + /// \fn + /// + /// \brief Config + /// + //////////////////////////////////////////////////////////////////////////////// + function AJsubmitDeleteConfigMapping() { + $configmapid = getContinuationVar('configmapid'); + $query = "DELETE FROM configmap " + . "WHERE id = $configmapid"; + doQuery($query); + $ret = array('status' => 'success', 'configmapid' => $configmapid); + sendJSON($ret); + } + + //////////////////////////////////////////////////////////////////////////////// + /// + /// \fn + /// + /// \brief Config + /// + //////////////////////////////////////////////////////////////////////////////// + function processMappingInput($maptypes) { + # configid + $return['configid'] = processInputVar('configid', ARG_NUMERIC); + $tmp = getUserResources(array("configAdmin"), array("administer")); # TODO is this the criteria we want for which configs can be selected? + if(! array_key_exists($return['configid'], $tmp['config'])) { + $this->errmsg = "Invalid config submitted"; + return 0; + } + + # maptypeid + $return['maptypeid'] = processInputVar('maptypeid', ARG_NUMERIC); + if(! array_key_exists($return['maptypeid'], $maptypes)) { + $this->errmsg = "Invalid map type submitted"; + return 0; + } + + # subid + $return['subid'] = processInputVar('subid', ARG_NUMERIC); + if($maptypes[$return['maptypeid']] == 'Image') { + $tmp = getUserResources(array("imageAdmin"), array("administer")); # TODO is this the criteria we want for which images can be selected? + if(! array_key_exists($return['subid'], $tmp['image'])) { + $this->errmsg = "Invalid image submitted"; + return 0; + } + $return['mapto'] = $tmp['image'][$return['subid']]; + } + elseif($maptypes[$return['maptypeid']] == 'OS Type') { + $ostypes = getOStypes(); + if(! array_key_exists($return['subid'], $ostypes)) { + $this->errmsg = "Invalid os type submitted"; + return 0; + } + $return['mapto'] = $ostypes[$return['subid']]; + } + elseif($maptypes[$return['maptypeid']] == 'OS') { + $oses = getOSList(); + if(! array_key_exists($return['subid'], $oses)) { + $this->errmsg = "Invalid OS submitted"; + return 0; + } + $return['mapto'] = $oses[$return['subid']]['prettyname']; + } + elseif($maptypes[$return['maptypeid']] == 'Config') { + $tmp = getUserResources(array("configAdmin"), array("administer")); # TODO is this the criteria we want for which configs can be selected? + $configs = $this->getUserConfigsNoCluster($tmp['config']); + if(! array_key_exists($return['subid'], $configs)) { + $this->errmsg = "Invalid config submitted"; + return 0; + } + $return['mapto'] = $configs[$return['subid']]; + } + elseif($maptypes[$return['maptypeid']] == 'Subimage') { + $configsubimages = getConfigSubimages($tmp['config']); + if(! array_key_exists($return['subid'], $configsubimages)) { + $this->errmsg = "Invalid cluster submitted"; + return 0; + } + $return['mapto'] = $configsubimages[$return['subid']]; + } + elseif($maptypes[$return['maptypeid']] == 'Management Node') { + $managementnodes = getManagementNodes(); + if(! array_key_exists($return['subid'], $managementnodes)) { + $this->errmsg = "Invalid managementnode submitted"; + return 0; + } + $return['mapto'] = $managementnodes[$return['subid']]['hostname']; + } + + # check for creating a loop - cannot have a parent that maps to + # submitted config + if($maptypes[$return['maptypeid']] == 'Config' || + $maptypes[$return['maptypeid']] == 'Subimage') { + $rc = $this->mappingLoopCheck($maptypes[$return['maptypeid']], $return['configid'], $return['subid']); + if($rc != '') { + $this->errmsg = "This mapping would create a loop. $rc is a<br>" + . "parent/grandparent and is mapped to the selected config."; + return 0; + } + } + + # affiliationid + $return['affiliationid'] = processInputVar('affiliationid', ARG_NUMERIC); + $affils = getAffiliations(); + if(! array_key_exists($return['affiliationid'], $affils)) { + $this->errmsg = "Invalid affiliation submitted"; + return 0; + } + + # stageid + $return['stageid'] = processInputVar('stageid', ARG_NUMERIC); + $stages = $this->getConfigMapStages(); + if(! array_key_exists($return['stageid'], $stages)) { + $this->errmsg = "Invalid stage submitted"; + return 0; + } + + # duplicate check + # TODO do we also need to check the disabled field? + $configmapid = getContinuationVar('configmapid', 0); + $query = "SELECT id " + . "FROM configmap " + . "WHERE configid = {$return['configid']} AND " + . "configmaptypeid = {$return['maptypeid']} AND " + . "subid = {$return['subid']} AND " + . "affiliationid = {$return['affiliationid']} AND " + . "configstageid = {$return['stageid']} AND " + . "id != $configmapid"; + $qh = doQuery($query); + if(mysql_num_rows($qh)) { + $this->errmsg = "The specified mapping already exists."; + return 0; + } + return $return; + } + + //////////////////////////////////////////////////////////////////////////////// + /// + /// \fn + /// + /// \brief Config + /// + //////////////////////////////////////////////////////////////////////////////// + function findDataTypeID($data, $datatypes) { + $flip = array_flip($datatypes); + if($data == 'true' || $data == 'false') + return $flip['bool']; + elseif(is_int($data)) + return $flip['int']; + elseif(is_float($data)) + return $flip['float']; + elseif(strlen($data) < 60) + return $flip['string']; + else + return $flip['text']; + } + + //////////////////////////////////////////////////////////////////////////////// + /// + /// \fn + /// + /// \brief Config + /// + //////////////////////////////////////////////////////////////////////////////// + function getUserConfigsNoCluster($userconfigs) { + if(empty($userconfigs)) + return array(); + $inlist = implode(',', array_keys($userconfigs)); + $query = "SELECT c.id, " + . "c.name " + . "FROM config c, " + . "configtype ct " + . "WHERE c.configtypeid = ct.id AND " + . "ct.name != 'cluster' AND " + . "c.id in ($inlist)"; + $configs = array(); + $qh = doQuery($query); + while($row = mysql_fetch_assoc($qh)) + $configs[$row['id']] = $row['name']; + return $configs; + } + + //////////////////////////////////////////////////////////////////////////////// + /// + /// \fn + /// + /// \brief Config + /// + //////////////////////////////////////////////////////////////////////////////// + function getConfigMapStages() { + $query = "SELECT id, name FROM configstage ORDER BY name"; + $stages = array(); + $qh = doQuery($query); + while($row = mysql_fetch_assoc($qh)) + $stages[$row['id']] = $row['name']; + return $stages; + } + + //////////////////////////////////////////////////////////////////////////////// + /// + /// \fn + /// + /// \brief Config + /// + //////////////////////////////////////////////////////////////////////////////// + function getMapSubName($maptype, $subid) { + switch($maptype) { + case "Image": + $data = getImages(0, $subid); + return $data[$subid]['prettyname']; + case "OS Type": + $ostypes = getOStypes(); + return $ostypes[$subid]; + case "OS": + $oses = getOSList(); + return $oses[$subid]['prettyname']; + case "Config": + case "Cluster": + $data = $this->_getData($subid); + return $data[$subid]['name']; + case "Management Node": + $managementnodes = getManagementNodes('neither', 0, $subid); + return $managementnodes[$subid]['hostname']; + break; + } + } + + //////////////////////////////////////////////////////////////////////////////// + /// + /// \fn + /// + /// \brief Config + /// + //////////////////////////////////////////////////////////////////////////////// + function mappingLoopCheck($maptype, $configid, $subid, $reccnt=0) { + if($maptype == 'Config') { + $query = "SELECT cm.configid, " + . "ct.prettyname AS maptype, " + . "cm.subid, " + . "c.name AS config " + . "FROM configmap cm, " + . "configmaptype ct, " + . "config c " + . "WHERE cm.configid = $subid AND " + . "cm.configmaptypeid = ct.id AND " + . "ct.prettyname = 'Config' AND " + . "cm.configid = c.id"; + $qh = doQuery($query); + while($row = mysql_fetch_assoc($qh)) { + if($row['subid'] == $configid) + return $row['config']; + if($reccnt < 20) { + $rc = $this->mappingLoopCheck($row['maptype'], $configid, $row['subid'], ++$reccnt); + if($rc != '') + return $rc; + } + } + } + elseif($maptype == 'Subimage') { + $query = "SELECT cs2.configid, " + . "ct.prettyname AS maptype, " + . "cm.subid, " + . "c.name AS config " + . "FROM configmap cm, " + . "configmaptype ct, " + . "configsubimage cs, " + . "configsubimage cs2, " + . "config c " + . "WHERE cs.id = $subid AND " + . "cs.configid = cm.configid AND " + . "cs2.id = cm.subid AND " + . "cm.configmaptypeid = ct.id AND " + . "ct.prettyname = 'Subimage' AND " + . "cm.configid = c.id"; + $qh = doQuery($query); + while($row = mysql_fetch_assoc($qh)) { + if($row['configid'] == $configid) + return $row['config']; + if($reccnt < 20) { + $rc = $this->mappingLoopCheck($row['maptype'], $configid, $row['subid'], ++$reccnt); + if($rc != '') + return $rc; + } + } + } + return ''; + } +} +?> Modified: vcl/trunk/web/.ht-inc/dashboard.php URL: http://svn.apache.org/viewvc/vcl/trunk/web/.ht-inc/dashboard.php?rev=1624325&r1=1624324&r2=1624325&view=diff ============================================================================== --- vcl/trunk/web/.ht-inc/dashboard.php (original) +++ vcl/trunk/web/.ht-inc/dashboard.php Thu Sep 11 16:01:48 2014 @@ -60,7 +60,9 @@ function dashboard() { print "</tr>\n"; print "</table>\n"; - print addWidget('newreservations', 'Loading Reservations', ''); + print addWidget('newreservations', 'Notable Reservations', ''); + if(checkUserHasPerm('View Dashboard (global)')) + print addWidget('failedimaging', 'Failed Imaging Reservations', '(Imaging Reservations in the maintenance state)'); $cont = addContinuationsEntry('AJupdateDashboard', array('val' => 0), 90, 1, 0); print "<input type=\"hidden\" id=\"updatecont\" value=\"$cont\">\n"; } @@ -84,6 +86,7 @@ function AJupdateDashboard() { $data['reschart'] = getActiveResChartData(); $data['blockallocation'] = getBlockAllocationData(); $data['newreservations'] = getNewReservationData(); + $data['failedimaging'] = getFailedImagingData(); sendJSON($data); } @@ -166,6 +169,7 @@ function getStatusData() { $data = array(); $data[] = array('key' => 'Active Reservations', 'val' => 0); $data[] = array('key' => 'Online Computers', 'val' => 0, 'tooltip' => 'Computers in states available, reserved,<br>reloading, inuse, or timeout'); + $data[] = array('key' => 'In Use Computers', 'val' => 0, 'tooltip' => 'Computers in inuse state'); $data[] = array('key' => 'Failed Computers', 'val' => 0); $reloadid = getUserlistID('vclreload@Local'); if($affilid == 0) { @@ -196,10 +200,15 @@ function getStatusData() { if($row = mysql_fetch_row($qh)) $data[1]['val'] = $row[0]; - $query = "SELECT COUNT(id) FROM computer WHERE stateid = 5"; + $query = "SELECT COUNT(id) FROM computer WHERE stateid = 8"; $qh = doQuery($query, 101); if($row = mysql_fetch_row($qh)) $data[2]['val'] = $row[0]; + + $query = "SELECT COUNT(id) FROM computer WHERE stateid = 5"; + $qh = doQuery($query, 101); + if($row = mysql_fetch_row($qh)) + $data[3]['val'] = $row[0]; return $data; } @@ -666,9 +675,9 @@ function getNewReservationData() { . "LEFT JOIN state s1 ON (s1.id = rq.stateid) " . "LEFT JOIN state s2 ON (s2.id = rq.laststateid) " . "LEFT JOIN managementnode m ON (m.id = rs.managementnodeid) " - . "WHERE (rq.stateid IN (13, 19, 6) OR " - . "(rq.stateid = 14 AND rq.laststateid IN (6, 13, 19))) AND " - . "rq.start < NOW() " + . "WHERE (rq.stateid IN (6, 13, 19) AND rq.start < NOW()) OR " + . "(rq.stateid = 14 AND rq.laststateid IN (6, 13, 16, 19) AND " + . "rq.start < DATE_ADD(NOW(), INTERVAL 1 HOUR)) " . "ORDER BY rq.start"; $qh = doQuery($query, 101); $data = array(); @@ -686,6 +695,101 @@ function getNewReservationData() { //////////////////////////////////////////////////////////////////////////////// /// +/// \fn getFailedImagingData() +/// +/// \return array of data with these keys:\n +/// \b computer - hostname of computer (without domain)\n +/// \b image - image being loaded\n +/// \b id - id of request\n +/// \b start - start date\n +/// \b state - current and last state\n +/// \b installtype - install for reservation\n +/// \b managementnode - hostname of mangementnode +/// +/// \brief gets information about loading reservations +/// +//////////////////////////////////////////////////////////////////////////////// +function getFailedImagingData() { + $query = "SELECT c.hostname AS computer, " + . "i.prettyname AS image, " + . "rq.id, " + . "rq.start, " + . "o.installtype, " + . "m.hostname AS managementnode, " + . "ch.hostname AS vmhost, " + . "u.unityid AS owner " + . "FROM request rq " + . "LEFT JOIN reservation rs ON (rs.requestid = rq.id) " + . "LEFT JOIN computer c ON (c.id = rs.computerid) " + . "LEFT JOIN image i ON (i.id = rs.imageid) " + . "LEFT JOIN OS o ON (o.id = i.OSid) " + . "LEFT JOIN managementnode m ON (m.id = rs.managementnodeid) " + . "LEFT JOIN vmhost vh ON (c.vmhostid = vh.id) " + . "LEFT JOIN computer ch ON (vh.computerid = ch.id) " + . "LEFT JOIN user u ON (rq.userid = u.id) " + . "WHERE rq.stateid = 10 AND " + . "rq.laststateid = 16 " + . "ORDER BY rq.start"; + $qh = doQuery($query, 101); + $data = array(); + while($row = mysql_fetch_assoc($qh)) { + $tmp = explode('.', $row['computer']); + $row['computer'] = $tmp[0]; + $tmp = explode('.', $row['vmhost']); + $row['vmhost'] = $tmp[0]; + $tmp = explode(' ', $row['start']); + $row['start'] = "{$tmp[0]}<br>{$tmp[1]}"; + $tmp = explode('.', $row['managementnode']); + $row['managementnode'] = $tmp[0]; + if($row['vmhost'] == '') + $row['vmhost'] = "N/A"; + $row['contid'] = addContinuationsEntry('AJrestartImageCapture', array('requestid' => $row['id']), 120, 1, 0); + $data[] = $row; + } + return $data; +} + +//////////////////////////////////////////////////////////////////////////////// +/// +/// \fn restartImageCapture() +/// +/// \return array of data with these keys:\n +/// \b computer - hostname of computer (without domain)\n +/// \b image - image being loaded\n +/// \b id - id of request\n +/// \b start - start date\n +/// \b state - current and last state\n +/// \b installtype - install for reservation\n +/// \b managementnode - hostname of mangementnode +/// +/// \brief gets information about loading reservations +/// +//////////////////////////////////////////////////////////////////////////////// +function AJrestartImageCapture() { + $requestid = getContinuationVar('requestid'); + if(! checkUserHasPerm('View Dashboard (global)')) { + sendJSON(array('status' => 'noaccess')); + return; + } + $request = getRequestInfo($requestid); + if($request['stateid'] != 10 || $request['laststateid'] != 16 || + count($request['reservations']) > 1) { + sendJSON(array('status' => 'wrongstate')); + return; + } + $compid = $request['reservations'][0]['computerid']; + $query = "UPDATE computer c, " + . "request rq " + . "SET c.stateid = 8, " + . "rq.stateid = 16 " + . "WHERE c.id = $compid AND " + . "rq.id = $requestid"; + doQuery($query); + sendJSON(array('status' => 'success')); +} + +//////////////////////////////////////////////////////////////////////////////// +/// /// \fn getDashboardAffilID() /// /// \return an affiliation id Modified: vcl/trunk/web/.ht-inc/errors.php URL: http://svn.apache.org/viewvc/vcl/trunk/web/.ht-inc/errors.php?rev=1624325&r1=1624324&r2=1624325&view=diff ============================================================================== --- vcl/trunk/web/.ht-inc/errors.php (original) +++ vcl/trunk/web/.ht-inc/errors.php Thu Sep 11 16:01:48 2014 @@ -190,6 +190,7 @@ $ERRORS = array ( "380" => "Failed to fetch last insert id in submitBlockRequest", "385" => "Failed to execute query in submitDeleteMgmtnode", "390" => "Failed to fetch salt while updating locally affiliated user password", + "400" => "semaphore for computer(s) expired before adding entry to reservation table", ); $XMLRPCERRORS = array( @@ -224,9 +225,9 @@ $XMLRPCERRORS = array( function errorHandler($errno, $errstr, $errfile=NULL, $errline=NULL, $errcontext=NULL) { global $user; if(! ONLINEDEBUG || ! checkUserHasPerm('View Debug Information')) { + cleanSemaphore(); dbDisconnect(); printHTMLFooter(); - semUnlock(); exit(); } print "Error encountered<br>\n"; @@ -236,9 +237,10 @@ function errorHandler($errno, $errstr, $ echo " Fatal error in line $errline of file $errfile"; echo ", PHP " . PHP_VERSION . " (" . PHP_OS . ")<br />\n"; echo "Aborting...<br />\n"; - semUnlock(); - exit(1); - break; + cleanSemaphore(); + dbDisconnect(); + exit(1); + break; case E_USER_WARNING: echo "<b>ERROR</b> [$errno] $errstr<br />\n"; break; @@ -261,9 +263,9 @@ function errorHandler($errno, $errstr, $ print "<pre>\n"; print getBacktraceString(); print "</pre>\n"; + cleanSemaphore(); dbDisconnect(); printHTMLFooter(); - semUnlock(); exit(); } Modified: vcl/trunk/web/.ht-inc/groups.php URL: http://svn.apache.org/viewvc/vcl/trunk/web/.ht-inc/groups.php?rev=1624325&r1=1624324&r2=1624325&view=diff ============================================================================== --- vcl/trunk/web/.ht-inc/groups.php (original) +++ vcl/trunk/web/.ht-inc/groups.php Thu Sep 11 16:01:48 2014 @@ -835,10 +835,10 @@ function editOrAddGroup($state) { print "</TABLE>\n"; } - if($data["type"] != "user"){ - print "</DIV>\n"; - return; - } + if($data["type"] != "user") { + print "</DIV>\n"; + return; + } if($editusergroup) { $newuser = processInputVar("newuser", ARG_STRING); print "<H3>Group Membership</H3>\n"; @@ -894,7 +894,7 @@ function editOrAddGroup($state) { } print "</TABLE>\n"; } - print "</DIV>\n"; + print "</DIV>\n"; } //////////////////////////////////////////////////////////////////////////////// @@ -1158,15 +1158,12 @@ function checkForGroupUsage($groupid, $t return 1; $query = "SELECT id " . "FROM blockRequest " - . "WHERE groupid = $groupid " - . "OR admingroupid = $groupid"; + . "WHERE (groupid = $groupid " + . "OR admingroupid = $groupid) " + . "AND status IN ('requested', 'accepted')"; $qh = doQuery($query, 311); if(mysql_num_rows($qh)) return 1; - $query = "SELECT id FROM imagemeta WHERE usergroupid = $groupid"; - $qh = doQuery($query, 312); - if(mysql_num_rows($qh)) - return 1; $query = "SELECT id " . "FROM usergroup " . "WHERE editusergroupid = $groupid " @@ -1329,7 +1326,7 @@ function confirmEditOrAddGroup($state) { print " </TD>\n"; print " </TR>\n"; print "</TABLE>\n"; - print "</DIV>\n"; + print "</DIV>\n"; } //////////////////////////////////////////////////////////////////////////////// @@ -1506,7 +1503,7 @@ function confirmDeleteGroup() { print " </TD>\n"; print " </TR>\n"; print "</TABLE>\n"; - print "</DIV>\n"; + print "</DIV>\n"; } //////////////////////////////////////////////////////////////////////////////// @@ -1519,8 +1516,13 @@ function confirmDeleteGroup() { function submitDeleteGroup() { $groupid = getContinuationVar("groupid"); $type = getContinuationVar("type"); - if($type == "user") + if($type == "user") { + $query = "UPDATE blockRequest " + . "SET groupid = 0 " + . "WHERE groupid = $groupid"; + doQuery($query); $table = "usergroup"; + } else $table = "resourcegroup"; $query = "DELETE FROM $table " @@ -1541,7 +1543,7 @@ function addGroupUser() { global $submitErr, $submitErrMsg; $groupid = getContinuationVar("groupid"); $newuser = processInputVar("newuser", ARG_STRING); - if(! validateUserid($newuser)) { + if(validateUserid($newuser) != 1) { $submitErr |= IDNAMEERR; $submitErrMsg[IDNAMEERR] = "Invalid login ID"; editOrAddGroup(0);
