restype = 'computer'; $this->restypename = 'Computer'; $this->namefield = 'hostname'; $this->defaultGetDataArgs = array('sort' => 0, 'includedeleted' => 0, 'rscid' => ''); $this->basecdata['obj'] = $this; } ///////////////////////////////////////////////////////////////////////////// /// /// \fn getData($args) /// /// \param $args - array of arguments that determine what data gets returned; /// must include:\n /// \param $sort - (optional) 1 to sort computers; 0 not to /// \b includedeleted - 0 or 1; include deleted images\n /// \b rscid - only return data for resource with this id; pass 0 for all /// (from image table) /// /// \return array of data as returned from getImages /// /// \brief wrapper for calling getImages /// ///////////////////////////////////////////////////////////////////////////// function getData($args) { return getComputers($args['sort'], $args['includedeleted'], $args['rscid']); } ///////////////////////////////////////////////////////////////////////////// /// /// \fn fieldWidth($field) /// /// \param $field - name of a resource field /// /// \return string for setting width of field (includes width= part) /// /// \brief generates the required width for the field; can return an empty /// string if field should default to auto width /// ///////////////////////////////////////////////////////////////////////////// function fieldWidth($field) { switch($field) { case 'currentimg': case 'nextimg': $w = 17; break; case 'notes': $w = 14; break; case 'IPaddress': case 'privateIPaddress': case 'natpublicIPaddress': case 'natinternalIPaddress': $w = 8; break; case 'eth0macaddress': case 'eth1macaddress': $w = 8.5; break; case 'vmhost': case 'nathost': $w = 8; break; case 'type': $w = 7; break; case 'location': $w = 9; break; case 'predictivemodule': $w = 10; break; case 'provisioning': $w = 11; break; case 'owner': $w = 12; break; default: return ''; } if(preg_match('/MSIE/i', $_SERVER['HTTP_USER_AGENT']) || preg_match('/Trident/i', $_SERVER['HTTP_USER_AGENT'])) $w = round($w * 11.5) . 'px'; else $w = "{$w}em"; return "width=\"$w\""; } ///////////////////////////////////////////////////////////////////////////// /// /// \fn fieldDisplayName($field) /// /// \param $field - name of a resource field /// /// \return display value for $field /// /// \brief generates the display value for $field /// ///////////////////////////////////////////////////////////////////////////// function fieldDisplayName($field) { switch($field) { case 'currentimg': return 'Current Image'; case 'nextimg': return 'Next Image'; case 'ram': return 'RAM'; case 'procnumber': return 'Cores'; case 'procspeed': return 'Processor speed'; case 'network': return 'Network speed'; case 'IPaddress': return 'Public IP Address'; case 'privateIPaddress': return 'Private IP Address'; case 'eth0macaddress': return 'Private MAC Address'; case 'eth1macaddress': return 'Public MAC Address'; case 'vmhost': return 'VM Host'; case 'provisioning': return 'Provisioning Engine'; case 'predictivemodule': return 'Predictive Loading Module'; case 'natenabled': return 'Connect Using NAT'; case 'nathost': return 'NAT Host'; case 'nathostenabled': return 'Use as NAT Host'; case 'natpublicIPaddress': return 'NAT Public IP Address'; case 'natinternalIPaddress': return 'NAT Internal IP Address'; } return ucfirst($field); } ///////////////////////////////////////////////////////////////////////////// /// /// \fn extraSelectAdminOptions() /// /// \return html /// /// \brief generates HTML for option to create/update an image /// ///////////////////////////////////////////////////////////////////////////// function extraSelectAdminOptions() { $h = ''; $h .= "
(Computer Utilities are now incorporated into Edit Computer "; $h .= "Profiles)
\n"; return $h; } ///////////////////////////////////////////////////////////////////////////// /// /// \fn extraResourceFilters() /// /// \return html /// /// \brief generates HTML for computer utilities drop down and filtering by /// computer group /// ///////////////////////////////////////////////////////////////////////////// function extraResourceFilters() { $h = ''; # selected items menu $h .= "
\n"; $h .= "" . _("Actions for selected computers") . "\n"; $h .= "
\n"; # change NAT $h .= "
\n"; $h .= " Change NAT\n"; $h .= "
\n"; $extra = array('onChange' => "toggleNAT('newnatenabled', 'newnathostid');"); $h .= labeledFormItem('newnatenabled', _('Connect Using NAT'), 'check', '', '', '1', '', '', $extra); $nathosts = getNAThosts(0, 1); $disabled = array('disabled' => 'true'); $h .= labeledFormItem('newnathostid', _('NAT Host'), 'select', $nathosts, '', '', '', '', $disabled); $cdata = $this->basecdata; $cont = addContinuationsEntry('AJcompNATchange', $cdata); $h .= "
\n"; $h .= dijitButton('newnathostbtn', 'Confirm NAT Change', 'confirmNATchange();', 0); $h .= "
\n"; $h .= "
\n"; # change predictive loading module $premodules = getPredictiveModules(); $h .= "
\n"; $h .= " Change Predictive Loading Module\n"; $h .= "
\n"; $h .= " Change Predictive Loading Module to:
\n"; $h .= selectInputAutoDijitHTML('', $premodules, 'newpredictivemoduleid'); $cdata = $this->basecdata; $cont = addContinuationsEntry('AJcompPredictiveModuleChange', $cdata); $h .= "
\n"; $h .= dijitButton('', 'Confirm Predictive Loading Module Change', 'confirmPredictiveModuleChange();', 0); $h .= "
\n"; $h .= "
\n"; # change provisioning engine $provisioning = getProvisioning(); $h .= "
\n"; $h .= " Change Provisioning Engine\n"; $h .= "
\n"; $h .= " Change Provisioning Engine to:
\n"; $h .= selectInputAutoDijitHTML('', $provisioning, 'newprovisioningid'); $cdata = $this->basecdata; $cont = addContinuationsEntry('AJcompProvisioningChange', $cdata); $h .= "
\n"; $h .= dijitButton('', 'Confirm Provisioning Engine Change', 'confirmProvisioningChange();', 0); $h .= "
\n"; $h .= "
\n"; # change schedule $resources = getUserResources(array("scheduleAdmin"), array("manageGroup")); if(count($resources['schedule'])) { $h .= "
\n"; $h .= " Change Schedule\n"; $h .= "
\n"; $h .= " Change schedule to:
\n"; $h .= selectInputAutoDijitHTML('', $resources['schedule'], 'newscheduleid'); $cont = addContinuationsEntry('AJcompScheduleChange', $this->basecdata); $h .= "
\n"; $h .= dijitButton('', 'Confirm Schedule Change', 'confirmScheduleChange();', 0); $h .= "
\n"; $h .= "
\n"; } # change state $states = array("2" => "available", "23" => "hpc", "10" => "maintenance", "20" => "convert to vmhostinuse"); $h .= "
\n"; $h .= " Change State\n"; $h .= "
\n"; $h .= " Change state to:
\n"; $h .= selectInputAutoDijitHTML('', $states, 'newstateid'); $cdata = $this->basecdata; $cdata['states'] = $states; $cont = addContinuationsEntry('AJcompStateChange', $cdata); $h .= "
\n"; $h .= dijitButton('', 'Confirm State Change', 'confirmStateChange();', 0); $h .= "
\n"; $h .= "
\n"; # delete $h .= "
\n"; $h .= " Delete Computers\n"; $cont = addContinuationsEntry('AJdeleteComputers', $this->basecdata); $h .= "
\n"; $h .= "
\n"; # generate /etc/hosts data $h .= "
\n"; $h .= " Generate /etc/hosts Data\n"; $cont = addContinuationsEntry('AJhostsData', $this->basecdata); $h .= "
\n"; $h .= "
\n"; # generate private dhcpd data $h .= "
\n"; $h .= " Generate Private dhcpd Data\n"; $h .= "
\n"; $h .= " Enter the Management Node Private IP Address:
\n"; $h .= "

\n"; $h .= " Select which NIC is used for the Private interface:
\n"; $h .= "
\n"; $h .= " "; $h .= "
\n"; $h .= dijitButton('', 'Generate Data', "generateDHCPdata('private');", 0); $cont = addContinuationsEntry('AJgenerateDHCPdata', $this->basecdata); $h .= " \n"; $h .= "
\n"; $h .= "
\n"; # generate public dhcpd data $h .= "
\n"; $h .= " Generate Public dhcpd Data\n"; $h .= "
\n"; $h .= " Select which NIC is used for the Public interface:
\n"; $h .= " "; $h .= "
\n"; $h .= "
\n"; $h .= dijitButton('', 'Generate Data', "generateDHCPdata('public');", 0); $h .= " \n"; # use previous continuation $h .= "
\n"; $h .= "
\n"; # reload $resources = getUserResources(array("imageAdmin", "imageCheckOut")); if(count($resources['image'])) { $h .= "
\n"; $h .= " Reload with an Image\n"; $h .= "
\n"; $h .= " Reload computers with the following image:
\n"; $extra = 'autoComplete="false"'; $h .= selectInputAutoDijitHTML('', $resources['image'], 'reloadimageid', $extra); $cont = addContinuationsEntry('AJreloadComputers', $this->basecdata); $h .= "
\n"; $h .= dijitButton('', 'Confirm Reload Computers', 'confirmReload();', 0); $h .= "
\n"; $h .= "
\n"; } $h .= "
\n"; # close Menu $h .= "
\n"; # close DropDownButton # computer groups $tmp = getUserResources(array($this->restype . 'Admin'), array('manageGroup'), 1); $groups = $tmp[$this->restype]; $cont = addContinuationsEntry('AJfilterCompGroups', $this->basecdata); $h .= "\n"; $h .= "
\n"; $h .= " Selected Computer Groups\n"; $h .= "
\n"; $size = 10; if(count($groups) < 10) $size = count($groups); $h .= selectInputHTML('', $groups, 'filtercompgroups', "onChange=\"delayedCompGroupFilterSelection();\" size=\"$size\"", -1, 0, 1); $h .= "
\n"; # tooltip dialog $h .= "
\n"; # drop down button $h .= "
\n"; $h .= "
\n"; $h .= "
\n"; $h .= "
\n"; $h .= "\n"; $h .= "
\n"; $h .= "\n"; $h .= dijitButton('submitactionbtn', 'Submit', 'submitAction();', 0); $h .= "\n"; $h .= dijitButton('cancelactionbtn', 'Cancel', 'cancelAction();', 0); $h .= "
\n"; # btn div $h .= "\n"; # confirmactiondlg $h .= "
\n"; $h .= dijitButton('', 'Close', 'dijit.byId("noschedulenoadd").hide();', 0); $h .= "
\n"; # btn div $h .= "\n"; # noschedulenoadd # filter table $h .= "
\n"; return $h; } ///////////////////////////////////////////////////////////////////////////// /// /// \fn AJfilterCompGroups /// /// \brief generates regular expressions to match ids of all computers in the /// submitted computer groups /// ///////////////////////////////////////////////////////////////////////////// function AJfilterCompGroups() { $groupids = processInputVar('groupids', ARG_STRING); if(! preg_match('/^[0-9,]+$/', $groupids)) { $ret = array('status' => 'error', 'errormsg' => "Invalid data submitted."); sendJSON($ret); return; } $groupids = explode(',', $groupids); $tmp = getUserResources(array($this->restype . 'Admin'), array('manageGroup'), 1); $groups = $tmp[$this->restype]; $groupnames = array(); foreach($groupids as $id) { if(array_key_exists($id, $groups)) $groupnames[] = $groups[$id]; } $comps = getResourcesFromGroups($groupnames, 'computer', 1); $regids = "^" . implode('$|^', array_keys($comps)) . "$"; $arr = array('status' => 'success', 'regids' => $regids); sendJSON($arr); } ///////////////////////////////////////////////////////////////////////////// /// /// \fn addEditDialogHTML($add) /// /// \param $add - unused for this class /// /// \brief generates HTML for dialog used to edit resource /// ///////////////////////////////////////////////////////////////////////////// function addEditDialogHTML($add) { global $user; # dialog for on page editing $h = ''; $h .= "
restypename}\"\n"; $h .= " duration=250\n"; $h .= " draggable=true>\n"; $h .= "
\n"; $h .= "
\n"; # id $h .= "\n"; $types = array("blade" => "Bare Metal", "lab" => "Lab", "virtualmachine" => "Virtual Machine"); $provisioning = getProvisioning(); $provtypes = getProvisioningTypes(); $states = array('blade' => array(2 => 'available', 10 => 'maintenance', 20 => 'vmhostinuse'), 'lab' => array(2 => 'available', 10 => 'maintenance'), 'virtualmachine' => array(10 => 'maintenance')); $h .= "\n"; # add single or multiple $h .= "
\n"; /*$h .= ""; $h .= "

\n"; $h .= "

\n";*/ $extra = array('onChange' => 'toggleSingleMultiple();'); $modes = array('single' => 'Single Computer', 'multiple' => 'Multiple Computers'); $h .= labeledFormItem('mode', _('Add') . ' ', 'select', $modes, 1, '', '', '', $extra); $h .= "
\n"; $h .= "
\n"; # singlemultiplediv # add multiple note $h .= "
\n"; $h .= "NOTE: 'Start IP' and 'End IP' can only differ in the number "; $h .= "after the last '.'. The
hostnames will be generated from the "; $h .= "'Hostname' field. The hostnames for each
computer can only differ "; $h .= "by the value of a number in the first part of the hostname.
Place "; $h .= "a '%' character in the 'Hostname' field where that number will be. "; $h .= "Then fill in
'Start value' and 'End value' with the first and last "; $h .= "values to be used in the hostname.

"; $h .= "
\n"; # multiplenotediv # div for canceling moving blade to vmhostinuse $h .= "
\n"; $h .= "\n"; $h .= "NOTICE: This computer is scheduled to start being reloaded as a vmhost at
"; $h .= ""; $h .= ". You may cancel this scheduled
reload by clicking the button below."; $h .= "

\n"; $h .= "\n"; $h .= "NOTICE: This computer is currently being reloaded as a vmhost. You may cancel this
"; $h .= "process by clicking on the button below. After canceling the reload, it may take several
"; $h .= "minutes for the cancellation process to complete."; $h .= "

\n"; $h .= "\n"; $h .= "\n"; $h .= "
\n"; # cancelvmhostinusediv $h .= "
\n"; # hostname $errmsg = _("Name can only contain letters, numbers, dashes(-), periods(.), and underscores(_). It can be from 1 to 36 characters long."); $h .= labeledFormItem('name', _('Name') . '*', 'text', '^([a-zA-Z0-9_][-a-zA-Z0-9_\.]{1,35})$', 1, '', $errmsg); # start/end $h .= "
\n"; $extra = array('smallDelta' => 1, 'largeDelta' => 10); $h .= labeledFormItem('startnum', _('Start') . '*', 'spinner', '{min:0,max:255,places:0}', 1); $h .= labeledFormItem('endnum', _('End') . '*', 'spinner', '{min:0,max:255,places:0}', 1); $h .= "
\n"; # startenddiv # owner $extra = array('onKeyPress' => 'setOwnerChecking'); $h .= labeledFormItem('owner', _('Owner') . '*', 'text', '', 1, "{$user['unityid']}@{$user['affiliation']}", _('Unknown user'), 'checkOwner', $extra); $cont = addContinuationsEntry('AJvalidateUserid'); $h .= "\n"; # type $extra = array('onChange' => 'selectType();'); $h .= labeledFormItem('type', _('Type'), 'select', $types, 1, '', '', '', $extra); # single computer fields $h .= "
\n"; # public IP $ipreg = '(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)'; $ipreg1 = "^$ipreg$"; $errmsg = _("Invalid Public IP address specified - must be a valid IPV4 address"); $h .= labeledFormItem('ipaddress', _('Public IP Address') . '*', 'text', $ipreg1, 1, '', $errmsg); # private IP $errmsg = _("Invalid Private IP address specified - must be a valid IPV4 address"); $h .= labeledFormItem('privateipaddress', _('Private IP Address'), 'text', $ipreg1, 0, '', $errmsg); # Public MAC $macreg = '^([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}$'; $errmsg = _("Invalid Public MAC address specified"); $h .= labeledFormItem('publicmac', _('Public MAC Address'), 'text', $macreg, 0, '', $errmsg); # private MAC $errmsg = _("Invalid Private MAC address specified"); $h .= labeledFormItem('privatemac', _('Private MAC Address'), 'text', $macreg, 0, '', $errmsg); $h .= "
\n"; # singleipmacdiv # multi computer fields $h .= "
\n"; # start public IP $errmsg = _("Invalid Start Public IP Address specified - must be a valid IPV4 address"); $h .= labeledFormItem('startpubipaddress', _('Start Public IP Address') . '*', 'text', $ipreg1, 1, '', $errmsg); # end public IP $errmsg = _("Invalid End Public IP Address specified - must be a valid IPV4 address"); $h .= labeledFormItem('endpubipaddress', _('End Public IP Address') . '*', 'text', $ipreg1, 1, '', $errmsg); # start private IP $errmsg = _("Invalid Start Private IP Address specified - must be a valid IPV4 address"); $h .= labeledFormItem('startprivipaddress', _('Start Private IP Address') . '*', 'text', $ipreg1, 1, '', $errmsg); # end private IP $errmsg = _("Invalid End Private IP Address specified - must be a valid IPV4 address"); $h .= labeledFormItem('endprivipaddress', _('End Private IP Address') . '*', 'text', $ipreg1, 1, '', $errmsg); # start MAC $errmsg = _("Invalid Start MAC Address specified"); $h .= labeledFormItem('startmac', _('Start MAC Address'), 'text', $macreg, 0, '', $errmsg); $h .= "
\n"; # multiipsdiv # provisioning engine $extra = array('onChange' => 'selectProvisioning();'); $h .= labeledFormItem('provisioningid', _('Provisioning Engine'), 'selectonly', $provisioning, 1, '', '', '', $extra); # state $extra = array('onChange' => 'selectState();'); $states = array(2 => 'available', 23 => 'hpc', 10 => 'maintenance', 20 => 'vmhostinuse'); $h .= labeledFormItem('stateid', _('State'), 'selectonly', $states, 1, '', '', '', $extra); # maintenance notes $h .= "
\n"; $h .= labeledFormItem('notes', _('Reason for maintenance'), 'textarea'); $h .= "
\n"; # VMhost profile $profiles = getVMProfiles(); uasort($profiles, 'sortKeepIndex'); $h .= "
\n"; $h .= labeledFormItem('vmprofileid', _('VM Host Porfile'), 'select', $profiles); $h .= "
\n"; # platform $platforms = getPlatforms(); $h .= labeledFormItem('platformid', _('Platform'), 'select', $platforms); # schedule $tmp = getUserResources(array("scheduleAdmin"), array("manageGroup")); $schedules = $tmp["schedule"]; $h .= labeledFormItem('scheduleid', _('Schedule'), 'selectonly', $schedules); # current image $h .= "
\n"; $h .= "\n"; $h .= "
\n"; $h .= "
\n"; # ram $extra = array('smallDelta' => 1024, 'largeDelta' => 4096); $h .= labeledFormItem('ram', _('RAM (MB)') . '*', 'spinner', '{min:500,max:16777215,places:0}', 1); # cores $extra = array('smallDelta' => 1, 'largeDelta' => 4); $h .= labeledFormItem('cores', _('No. Cores') . '*', 'spinner', '{min:1,max:255,places:0}', 1); # proc speed $extra = array('smallDelta' => 100, 'largeDelta' => 1000); $h .= labeledFormItem('procspeed', _('Processor Speed (MHz)') . '*', 'spinner', '{min:500,max:10000,places:0}', 1); # network speed $tmpArr = array("10" => "10", "100" => "100", "1000" => "1000", "10000" => "10000", "100000" => "100000"); $h .= labeledFormItem('network', _('Network'), 'select', $tmpArr); # predictive loading module $vals = getPredictiveModules(); $h .= labeledFormItem('predictivemoduleid', _('Predictive Loading Module'), 'select', $vals); # NAT $h .= "
\n"; # use NAT $extra = array('onChange' => "toggleNAT('natenabled', 'nathostid');"); $h .= labeledFormItem('natenabled', _('Connect Using NAT'), 'check', '', '', '1', '', '', $extra); # which NAT host $nathosts = getNAThosts(0, 1); $h .= labeledFormItem('nathostid', _('NAT Host'), 'selectonly', $nathosts); $h .= "
\n"; # NAT # NAT Host $h .= "
\n"; # use as NAT host $extra = array('onChange' => "toggleNAThost();"); $h .= labeledFormItem('nathostenabled', _('Use as NAT Host'), 'check', '', '', '1', '', '', $extra); # public IP $errmsg = _("Invalid NAT Public IP address specified - must be a valid IPV4 address"); $h .= labeledFormItem('natpublicipaddress', _('NAT Public IP Address'), 'text', $ipreg1, 1, '', $errmsg); # internal IP $errmsg = _("Invalid NAT Internal IP address specified - must be a valid IPV4 address"); $h .= labeledFormItem('natinternalipaddress', _('NAT Internal IP Address'), 'text', $ipreg1, 1, '', $errmsg); $h .= "
\n"; # NAT Host # compid $h .= "
\n"; $h .= "\n"; $h .= "
\n"; $h .= "
\n"; # location $errmsg = _("Location can be up to 255 characters long and may contain letters, numbers, spaces, and these characters: - , . _ @ # ( )"); $h .= labeledFormItem('location', _('Location'), 'text', '^([-a-zA-Z0-9_\. ,@#\(\)]{0,255})$', 0, '', $errmsg); $h .= "
\n"; # computerdlgcontent $h .= "
\n"; # addeditdlgcontent $h .= "
\n"; $h .= "
\n"; $h .= dijitButton('addeditbtn', "Confirm", "saveResource();"); $h .= dijitButton('', "Cancel", "dijit.byId('addeditdlg').hide();"); $h .= "
\n"; # editdlgbtns $h .= "
\n"; # dialog $h .= "
\n"; $h .= dijitButton('', "Close", "dijit.byId('groupingnote').hide();"); $h .= "
\n"; # btn div $h .= "\n"; # groupingnote $h .= "
\n"; $h .= "
\n"; $script = " dijit.byId('groupdlg').hide();\n"; $script .= " checkFirstAdd();\n"; $h .= dijitButton('', "Close", $script); $h .= "
\n"; # btn div $h .= "\n"; # groupdlg return $h; } ///////////////////////////////////////////////////////////////////////////// /// /// \fn AJeditResource() /// /// \brief sends data for editing a resource /// ///////////////////////////////////////////////////////////////////////////// function AJeditResource() { $rscid = processInputVar('rscid', ARG_NUMERIC); $resources = getUserResources(array($this->restype . 'Admin'), array('administer'), 0, 1); if(! array_key_exists($rscid, $resources[$this->restype])) { $ret = array('status' => 'noaccess'); sendJSON($ret); return; } $this->jsondata['showcancel'] = 0; $query = "SELECT UNIX_TIMESTAMP(rq.start) AS start " . "FROM request rq, " . "reservation rs, " . "state ls, " . "state cs " . "WHERE rs.requestid = rq.id AND " . "rs.computerid = $rscid AND " . "rq.laststateid = ls.id AND " . "rq.stateid = cs.id AND " . "ls.name = 'tovmhostinuse' AND " . "cs.name NOT IN ('failed', 'maintenance', 'complete', 'deleted') AND " . "rq.end > NOW() " . "ORDER BY rq.start " . "LIMIT 1"; $qh = doQuery($query); if($row = mysql_fetch_assoc($qh)) { $cdata = $this->basecdata; $cdata['compid'] = $rscid; $cont = addContinuationsEntry('AJcanceltovmhostinuse', $cdata, 300, 1, 0); $this->jsondata['tohostcancelcont'] = $cont; $this->jsondata['showcancel'] = 1; $this->jsondata['tohoststart'] = date('g:i A \o\n l, F jS, Y', $row['start']); if($row['start'] > time()) $this->jsondata['tohostfuture'] = 1; else $this->jsondata['tohostfuture'] = 0; } parent::AJeditResource(); } ///////////////////////////////////////////////////////////////////////////// /// /// \fn AJsaveResource() /// /// \brief saves changes to resource /// ///////////////////////////////////////////////////////////////////////////// function AJsaveResource() { global $user; $add = getContinuationVar('add', 0); $data = $this->validateResourceData(); if($data['error']) { $ret = array('status' => 'error', 'msg' => $data['errormsg']); sendJSON($ret); return; } $promptuser = 0; $promptuserfail = 0; $multirefresh = 0; if($add) { if(! $data['rscid'] = $this->addResource($data)) { sendJSON(array('status' => 'adderror', 'errormsg' => 'Error encountered while trying to create new computer(s).
Please contact an admin for assistance.')); return; } } else { $olddata = getContinuationVar('olddata'); $updates = array(); # hostname if($data['name'] != $olddata['hostname']) $updates[] = "hostname = '{$data['name']}'"; # ownerid $ownerid = getUserlistID($data['owner']); if($ownerid != $olddata['ownerid']) $updates[] = "ownerid = $ownerid"; # cores if($data['cores'] != $olddata['procnumber']) $updates[] = "procnumber = '{$data['cores']}'"; # eth0macaddress if($data['eth0macaddress'] != $olddata['eth0macaddress']) { if($data['eth0macaddress'] == '') $updates[] = "eth0macaddress = NULL"; else $updates[] = "eth0macaddress = '{$data['eth0macaddress']}'"; } # eth1macaddress if($data['eth1macaddress'] != $olddata['eth1macaddress']) { if($data['eth1macaddress'] == '') $updates[] = "eth1macaddress = NULL"; else $updates[] = "eth1macaddress = '{$data['eth1macaddress']}'"; } # use NAT if($data['natenabled'] != $olddata['natenabled']) { if($data['natenabled']) { $query = "INSERT INTO nathostcomputermap " . "(computerid, " . "nathostid) " . "VALUES ({$data['rscid']}, " . "{$data['nathostid']})"; doQuery($query); } else { $query = "DELETE FROM nathostcomputermap " . "WHERE computerid = {$data['rscid']}"; doQuery($query); } } elseif($data['natenabled'] && $olddata['nathostid'] != $data['nathostid']) { $query = "UPDATE nathostcomputermap " . "SET nathostid = {$data['nathostid']} " . "WHERE computerid = {$data['rscid']}"; doQuery($query); } # NAT host if($data['nathostenabled'] != $olddata['nathostenabled']) { if($data['nathostenabled']) { $query = "INSERT INTO nathost " . "(resourceid, " . "publicIPaddress, " . "internalIPaddress) " . "VALUES " . "({$olddata['resourceid']}, " . "'{$data['natpublicIPaddress']}', " . "'{$data['natinternalIPaddress']}') " . "ON DUPLICATE KEY UPDATE " . "publicIPaddress = '{$data['natpublicIPaddress']}', " . "internalIPaddress = '{$data['natinternalIPaddress']}'"; doQuery($query); } else { $query = "DELETE FROM nathost " . "WHERE resourceid = {$olddata['resourceid']}"; doQuery($query); } } elseif($data['nathostenabled'] && ($olddata['natpublicIPaddress'] != $data['natpublicIPaddress'] || $olddata['natinternalIPaddress'] != $data['natinternalIPaddress'])) { $query = "UPDATE nathost " . "SET publicIPaddress = '{$data['natpublicIPaddress']}', " . "internalIPaddress = '{$data['natinternalIPaddress']}' " . "WHERE resourceid = {$olddata['resourceid']}"; doQuery($query); } # other fields $fields = array('type', 'IPaddress', 'privateIPaddress', 'provisioningid', 'platformid', 'scheduleid', 'ram', 'procspeed', 'network', 'predictivemoduleid', 'location'); foreach($fields as $field) { if($data[$field] != $olddata[$field]) $updates[] = "`$field` = '{$data[$field]}'"; } # stateid - if moving from vmhostinuse or reloading with a new image, # make sure no reservations for VMs if($olddata['stateid'] == 10 && $data['stateid'] == 20) { $query = "SELECT vm.id " . "FROM computer vm, " . "vmhost v " . "WHERE v.computerid = {$data['rscid']} AND " . "vm.vmhostid = v.id AND " . "vm.notes = 'maintenance with host {$data['rscid']}' AND " . "vm.stateid = 10"; $qh = doQuery($query); $vmids = array(); while($row = mysql_fetch_assoc($qh)) $vmids[] = $row['id']; $allids = implode(',', $vmids); if($data['provisioning'] != 'none') { $profiles = getVMProfiles(); if(! array_key_exists('vmprofileid', $olddata) || $olddata['vmprofileid'] == '' || $profiles[$olddata['vmprofileid']]['imageid'] != $profiles[$data['vmprofileid']]['imageid']) { # VCL provisioned, different image # schedule VM host to be reloaded $profiles = getVMProfiles($data['vmprofileid']); $imageid = $profiles[$data['vmprofileid']]['imageid']; $start = getReloadStartTime(); $rc = $this->scheduleTovmhostinuse($data['rscid'], $imageid, $start, $data['vmprofileid'], $olddata['vmprofileid']); if($rc == 0) { $msg = ''; if(count($updates)) $msg .= "Computer information changes were saved.
\nHowever, a "; else $msg .= "A "; $msg .= "problem was encountered while attempting to reload the "; $msg .= "computer with the selected VM Host Profile. Please try "; $msg .= "again at a later time.\n"; $msg = preg_replace("/(.{1,76}([ \n]|$))/", '\1
', $msg); $promptuserfail = 1; $title = 'VM Host Reload Failed'; } else { if(count($vmids)) $this->scheduleVMsToAvailable($vmids); $multirefresh = 3; } } else { # VCL provisioned, same image $msg = ''; if(count($updates)) $msg .= "Computer information changes saved.

\nHowever, this "; else $msg .= "This "; $msg .= "computer was previously in the vmhostinuse state. "; $msg .= "You can:

\n"; $msg .= "
\n"; $msg .= "

\n"; $promptuser = 1; $cdata = $this->basecdata; $cdata['compid'] = $data['rscid']; $cdata['imageid'] = $profiles[$data['vmprofileid']]['imageid']; $cdata['oldprofileid'] = $olddata['vmprofileid']; $cdata['vmprofileid'] = $data['vmprofileid']; $cdata['newstateid'] = $data['stateid']; $cdata['oldstateid'] = $olddata['stateid']; $cdata['vmids'] = $vmids; $promptcont = addContinuationsEntry('AJsubmitComputerStateLater', $cdata, SECINDAY, 1, 0); $btntxt = 'Submit'; $title = 'State Change Option'; } $data['stateid'] = $olddata['stateid']; # prevent state from being updated directly } else { if(count($vmids)) { $query = "UPDATE computer " . "SET stateid = 2, " . "notes = '' " . "WHERE id in ($allids)"; doQuery($query); $multirefresh = 1; } if(! array_key_exists('vmprofileid', $olddata) || $olddata['vmprofileid'] == '') { $query = "INSERT INTO vmhost " . "(computerid, " . "vmlimit, " . "vmprofileid) " . "VALUES ({$data['rscid']}, " . "5, " . "{$data['vmprofileid']})"; doQuery($query); } elseif($olddata['vmprofileid'] != $data['vmprofileid']) { $query = "UPDATE vmhost " . "SET vmprofileid = {$data['vmprofileid']} " . "WHERE computerid = {$data['rscid']} AND " . "vmprofileid = {$olddata['vmprofileid']}"; doQuery($query); } } } elseif($olddata['stateid'] != 20 && $data['stateid'] == 20) { # check for reservations moveReservationsOffComputer($data['rscid']); cleanSemaphore(); $reloadstart = getCompFinalReservationTime($data['rscid'], 21); $checkstart = getExistingChangeStateStartTime($data['rscid'], 21); if($data['provisioning'] != 'none') { # VCL provisioned $profiles = getVMProfiles($data['vmprofileid']); $imageid = $profiles[$data['vmprofileid']]['imageid']; if($reloadstart) { if($checkstart && $checkstart < $reloadstart) $reloadstart = $checkstart; # reservations, must wait until end time $end = date('n/j/y g:i a', $reloadstart); $msg = ''; if(count($updates)) $msg .= "Computer information changes saved.
\nHowever, this "; else $msg .= "This "; $msg .= "computer is currently allocated until $end and cannot "; $msg .= "be reloaded until then. You can:\n"; $msg .= "\n"; $msg = preg_replace("/(.{1,76}([ \n]|$))/", '\1
', $msg); $msg = preg_replace("|$end|", "$end", $msg, 1); $promptuser = 1; $cdata = $this->basecdata; $cdata['maintenanceonly'] = 0; $cdata['compid'] = $data['rscid']; $cdata['reloadstart'] = $reloadstart; $cdata['imageid'] = $imageid; $cdata['oldprofileid'] = $olddata['vmprofileid']; $cdata['vmprofileid'] = $data['vmprofileid']; $cdata['newstateid'] = $data['stateid']; $cdata['oldstateid'] = $olddata['stateid']; $promptcont = addContinuationsEntry('AJsubmitComputerStateLater', $cdata, SECINDAY, 1, 0); $btntxt = 'Schedule Reload'; $title = 'Delayed State Change'; } else { # no reservations $start = getReloadStartTime(); $checkstart = getExistingChangeStateStartTime($data['rscid'], 21); if($checkstart && $checkstart < $start) $start = $checkstart; $rc = $this->scheduleTovmhostinuse($data['rscid'], $imageid, $start, $data['vmprofileid'], $olddata['vmprofileid']); if($rc == 0) { $msg = ''; if(count($updates)) $msg .= "Computer information changes were saved.
\nHowever, a "; else $msg .= "A "; $msg .= "problem was encountered while attempting to reload the "; $msg .= "computer with the selected VM Host Profile. Please try "; $msg .= "again at a later time.\n"; $msg = preg_replace("/(.{1,76}([ \n]|$))/", '\1
', $msg); $promptuserfail = 1; $title = 'VM Host Reload Failed'; } else $multirefresh = 3; } $data['stateid'] = $olddata['stateid']; # prevent state from being updated directly } else { # manually provisioned if($reloadstart) { # reservations, must wait until end time $end = date('n/j/y g:i a', $reloadstart); $msg = ''; if(count($updates)) $msg .= "Computer information changes saved.
\nHowever, this "; else $msg .= "This "; $msg .= "computer is currently allocated until $end and cannot "; $msg .= "be converted to a VM host until then. You can:\n"; $msg .= "\n"; $msg = preg_replace("/(.{1,76}([ \n]|$))/", '\1
', $msg); $msg = preg_replace("|$end|", "$end", $msg, 1); $promptuser = 1; $cdata = $this->basecdata; $cdata['maintenanceonly'] = 1; $cdata['reloadstart'] = $reloadstart; $cdata['imageid'] = getImageId('noimage'); $cdata['compid'] = $data['rscid']; $cdata['newstateid'] = $data['stateid']; $cdata['oldstateid'] = $olddata['stateid']; $promptcont = addContinuationsEntry('AJsubmitComputerStateLater', $cdata, SECINDAY, 1, 0); $btntxt = 'Schedule State Change'; $title = 'Delayed State Change'; $data['stateid'] = $olddata['stateid']; # prevent state from being updated yet } else { # no reservations $this->updateVmhostProfile($data['rscid'], $data['vmprofileid'], $olddata['vmprofileid']); } } } elseif($olddata['stateid'] == 20 && $data['stateid'] == 2) { # only valid condition for VCL provisioned # check for reservations moveReservationsOffVMs($data['rscid']); cleanSemaphore(); $reloadstart = getCompFinalVMReservationTime($data['rscid'], 1); if($reloadstart == -1) { $msg = ''; if(count($updates)) $msg .= "Computer information changes were saved.
\nHowever, a "; else $msg .= "A "; $msg .= "problem was encountered while attempting to move VMs "; $msg .= "off of the computer. Please try again at a later time.\n"; $msg = preg_replace("/(.{1,76}([ \n]|$))/", '\1
', $msg); $promptuserfail = 1; $title = 'Change to Available Failed'; $data['stateid'] = $olddata['stateid']; } elseif($reloadstart > 0) { cleanSemaphore(); $end = date('n/j/y g:i a', $reloadstart); $msg = ''; if(count($updates)) $msg .= "Computer information changes saved.
\nHowever, this "; else $msg .= "This "; $msg .= "computer currently has VMs with reservations on them until "; $msg .= "$end and cannot be moved to the available state until then. "; $msg .= "You can:\n"; $msg .= "\n"; $msg = preg_replace("/(.{1,76}([ \n]|$))/", '\1
', $msg); $msg = preg_replace("|$end|", "$end", $msg, 1); $promptuser = 1; $cdata = $this->basecdata; $cdata['reloadstart'] = $reloadstart; $cdata['imageid'] = getImageId('noimage'); $cdata['compid'] = $data['rscid']; $cdata['newstateid'] = $data['stateid']; $cdata['oldstateid'] = $olddata['stateid']; $promptcont = addContinuationsEntry('AJsubmitComputerStateLater', $cdata, SECINDAY, 1, 0); $btntxt = 'Schedule State Change'; $title = 'Delayed State Change'; $data['stateid'] = $olddata['stateid']; # prevent state from being updated yet } else { # schedule tomaintenance reservations for VMs # might be better to just directly move the VMs to the maintenance state $vclreloadid = getUserlistID('vclreload@Local'); $imageid = getImageId('noimage'); $revid = getProductionRevisionid($imageid); $start = getReloadStartTime(); $end = $start + SECINMONTH; $startdt = unixToDatetime($start); $enddt = unixToDatetime($end); $query = "SELECT vm.id " . "FROM computer vm, " . "vmhost v " . "WHERE v.computerid = {$data['rscid']} AND " . "vm.vmhostid = v.id"; $qh = doQuery($query); $fail = 0; while($row = mysql_fetch_assoc($qh)) { if(! simpleAddRequest($row['id'], $imageid, $revid, $startdt, $enddt, 18, $vclreloadid)) { $fail = 1; break; } else $multirefresh = 2; } cleanSemaphore(); if($fail) { $data['stateid'] = $olddata['stateid']; # prevent state from being updated yet $msg = ''; if(count($updates)) $msg .= "Computer information changes were saved.
\nHowever, a "; else $msg .= "A "; $msg .= "problem was encountered while attempting to remove VMs "; $msg .= "from the computer. Please try again at a later time.\n"; $msg = preg_replace("/(.{1,76}([ \n]|$))/", '\1
', $msg); $promptuserfail = 1; $title = 'Change State to Available Failed'; } } } elseif($olddata['stateid'] == 20 && $data['stateid'] == 10) { # VCL provisioned and manually provisioned are the same # check for reservations moveReservationsOffVMs($data['rscid']); cleanSemaphore(); $reloadstart = getCompFinalVMReservationTime($data['rscid'], 1, 1); if($reloadstart == -1) { $msg = ''; if(count($updates)) $msg .= "Computer information changes were saved.
\nHowever, a "; else $msg .= "A "; $msg .= "problem was encountered while attempting to place assigned VMs "; $msg .= "into the maintenance state. Please try again at a later time.\n"; $msg = preg_replace("/(.{1,76}([ \n]|$))/", '\1
', $msg); $promptuserfail = 1; $title = 'Change to Maintenance Failed'; } elseif($reloadstart > 0) { cleanSemaphore(); if(unixToDatetime($reloadstart) == '2038-01-01 00:00:00') { $msg = ''; if(count($updates)) $msg .= "Computer information changes saved.
\nHowever, this "; else $msg .= "This "; $msg .= "computer currently has VMs assigned to it that have server "; $msg .= "reservations with indefinite endings. The computer cannot "; $msg .= "be moved to the maintenance state while these reservations exist."; $msg = preg_replace("/(.{1,76}([ \n]|$))/", '\1
', $msg); $promptuserfail = 1; $title = 'Change to Maintenance Failed'; $data['stateid'] = $olddata['stateid']; # prevent state from being updated } else { $end = date('n/j/y g:i a', $reloadstart); $msg = ''; if(count($updates)) $msg .= "Computer information changes saved.
\nHowever, this "; else $msg .= "This "; $msg .= "computer currently has VMs with reservations on them until "; $msg .= "$end and cannot be moved to the maintenance state until then. "; $msg .= "You can:\n"; $msg .= "\n"; $msg = preg_replace("/(.{1,76}([ \n]|$))/", '\1
', $msg); $msg = preg_replace("|$end|", "$end", $msg, 1); $promptuser = 1; $cdata = $this->basecdata; $cdata['reloadstart'] = $reloadstart; $cdata['imageid'] = getImageId('noimage'); $cdata['compid'] = $data['rscid']; $cdata['newstateid'] = $data['stateid']; $cdata['oldstateid'] = $olddata['stateid']; $promptcont = addContinuationsEntry('AJsubmitComputerStateLater', $cdata, SECINDAY, 1, 0); $btntxt = 'Schedule State Change'; $title = 'Delayed State Change'; $data['stateid'] = $olddata['stateid']; # prevent state from being updated yet } } else { $query = "UPDATE computer c " . "INNER JOIN vmhost v ON (c.vmhostid = v.id) " . "SET c.stateid = 10, " . "c.notes = 'maintenance with host {$data['rscid']}' " . "WHERE v.computerid = {$data['rscid']}"; doQuery($query); cleanSemaphore(); $multirefresh = 1; } } elseif($olddata['stateid'] == 10 && $data['stateid'] == 2) { if(is_numeric($olddata['vmprofileid'])) { $vclreloadid = getUserlistID('vclreload@Local'); $imageid = getImageId('noimage'); $revid = getProductionRevisionid($imageid); $start = getReloadStartTime(); $end = $start + SECINMONTH; $startdt = unixToDatetime($start); $enddt = unixToDatetime($end); # move VMs to reload state so vcld will not skip them due to being in maintenance $query = "UPDATE computer c, " . "vmhost v " . "SET c.stateid = 19, " . "c.notes = '' " . "WHERE v.computerid = {$data['rscid']} AND " . "c.vmhostid = v.id"; doQuery($query); $query = "SELECT vm.id " . "FROM computer vm, " . "vmhost v " . "WHERE v.computerid = {$data['rscid']} AND " . "vm.vmhostid = v.id"; $qh = doQuery($query); $fails = array(); while($row = mysql_fetch_assoc($qh)) { if(! simpleAddRequest($row['id'], $imageid, $revid, $startdt, $enddt, 18, $vclreloadid)) { $fails[] = $row['id']; } else $multirefresh = 2; } if(count($fails)) { # just directly remove any VMs that failed to be scheduled $query = "UPDATE computer " . "SET stateid = 10, " . "vmhostid = NULL, " . "notes = '' " . "WHERE id IN (" . implode(',', $fails) . ")"; doQuery($query); } } } elseif($olddata['stateid'] == 20 && $data['stateid'] == 20 && $olddata['vmprofileid'] != $data['vmprofileid']) { if($data['provisioning'] != 'none') { $profiles = getVMProfiles($data['vmprofileid']); if($profiles[$olddata['vmprofileid']]['imageid'] == $profiles[$data['vmprofileid']]['imageid']) { $query = "UPDATE vmhost " . "SET vmprofileid = {$data['vmprofileid']} " . "WHERE computerid = {$data['rscid']} AND " . "vmprofileid = {$olddata['vmprofileid']}"; doQuery($query); } else { moveReservationsOffVMs($data['rscid']); cleanSemaphore(); $reloadstart = getCompFinalVMReservationTime($data['rscid'], 1); if($reloadstart == -1) { $msg = ''; if(count($updates)) $msg .= "Computer information changes were saved.
\nHowever, a "; else $msg .= "A "; $msg .= "problem was encountered while attempting to place assigned "; $msg .= "VMs into the maintenance state while reloading the computer. "; $msg .= "Please try again at a later time.\n"; $msg = preg_replace("/(.{1,76}([ \n]|$))/", '\1
', $msg); $promptuserfail = 1; $title = 'Change VM Host Profile Failed'; } elseif($reloadstart > 0) { cleanSemaphore(); $end = date('n/j/y g:i a', $reloadstart); $msg = ''; if(count($updates)) $msg .= "Computer information changes saved.
\nHowever, this "; else $msg .= "This "; $msg .= "computer must be reloaded to change to the selected VM Host "; $msg .= "Profile and there are VMs on it with reservations until $end. "; $msg .= "You can:\n"; $msg .= "\n"; $msg = preg_replace("/(.{1,76}([ \n]|$))/", '\1
', $msg); $msg = preg_replace("|$end|", "$end", $msg, 1); $promptuser = 1; $cdata = $this->basecdata; $cdata['reloadstart'] = $reloadstart; $cdata['imageid'] = $profiles[$data['vmprofileid']]['imageid']; $cdata['compid'] = $data['rscid']; $cdata['newstateid'] = $data['stateid']; $cdata['oldstateid'] = $olddata['stateid']; $cdata['oldprofileid'] = $olddata['vmprofileid']; $cdata['vmprofileid'] = $data['vmprofileid']; $promptcont = addContinuationsEntry('AJsubmitComputerStateLater', $cdata, SECINDAY, 1, 0); $btntxt = 'Schedule Reload'; $title = 'Delayed VM Host Profile Change'; } else { # schedule VMs to be removed $vclreloadid = getUserlistID('vclreload@Local'); $imageid = getImageId('noimage'); $revid = getProductionRevisionid($imageid); $start = getReloadStartTime(); $end = $start + SECINMONTH; $startdt = unixToDatetime($start); $enddt = unixToDatetime($end); $query = "SELECT vm.id " . "FROM computer vm, " . "vmhost v " . "WHERE v.computerid = {$data['rscid']} AND " . "vm.vmhostid = v.id"; $qh = doQuery($query); $fails = array(); $cnt = 0; while($row = mysql_fetch_assoc($qh)) { $cnt++; if(! simpleAddRequest($row['id'], $imageid, $revid, $startdt, $enddt, 18, $vclreloadid)) { $fails[] = $row['id']; } } if(count($fails)) { # just directly remove any VMs that failed to be scheduled $query = "UPDATE computer " . "SET stateid = 10, " . "vmhostid = NULL, " . "notes = '' " . "WHERE id IN (" . implode(',', $fails) . ")"; doQuery($query); } cleanSemaphore(); # schedule host to be reloaded if($cnt) $start = time() + 120; # allow 2 minutes for VMs to be removed $rc = $this->scheduleTovmhostinuse($data['rscid'], $profiles[$data['vmprofileid']]['imageid'], $start, $data['vmprofileid'], $olddata['vmprofileid']); if($rc == 0) { $msg = ''; if(count($updates)) $msg .= "Computer information changes were saved.
\nHowever, a "; else $msg .= "A "; $msg .= "problem was encountered while attempting to reload the "; $msg .= "computer with the selected VM Host Profile. Please try "; $msg .= "again at a later time.\n"; $msg = preg_replace("/(.{1,76}([ \n]|$))/", '\1
', $msg); $promptuserfail = 1; $title = 'VM Host Reload Failed'; } else $multirefresh = 3; } } } else { $query = "UPDATE vmhost " . "SET vmprofileid = {$data['vmprofileid']} " . "WHERE computerid = {$data['rscid']} AND " . "vmprofileid = {$olddata['vmprofileid']}"; doQuery($query); } } elseif($olddata['stateid'] != 10 && $data['stateid'] == 10) { moveReservationsOffComputer($data['rscid']); cleanSemaphore(); $reloadstart = getCompFinalReservationTime($data['rscid']); if($reloadstart) { $end = date('n/j/y g:i a', $reloadstart); $msg = ''; if(count($updates)) $msg .= "Computer information changes saved.
\nHowever, this "; else $msg .= "This "; $msg .= "computer has reservations on it until $end. You can:\n"; $msg .= "\n"; $msg = preg_replace("/(.{1,76}([ \n]|$))/", '\1
', $msg); $msg = preg_replace("|$end|", "$end", $msg, 1); $promptuser = 1; $cdata = $this->basecdata; $cdata['reloadstart'] = $reloadstart; $cdata['imageid'] = getImageId('noimage'); $cdata['compid'] = $data['rscid']; $cdata['newstateid'] = $data['stateid']; $cdata['oldstateid'] = $olddata['stateid']; $promptcont = addContinuationsEntry('AJsubmitComputerStateLater', $cdata, SECINDAY, 1, 0); $btntxt = 'Schedule Maintenance'; $title = 'Delayed Maintenance'; } # else let UPDATE move it to maintenance } # notes (do these at the end because we don't want to update notes if # state prevented from being changed) # staying in maintenance if($olddata['stateid'] == 10 && $data['stateid'] == 10) { $testnotes = $olddata['notes']; # check for notes being changed if(strpos($testnotes, '@') === true) { $tmp = explode('@', $olddata['notes']); $testnotes = $tmp[1]; } if($testnotes != $data['notes']) { $ts = unixToDatetime(time()); $updates[] = "notes = '{$user['unityid']} $ts@{$data['notes']}'"; } } # changing to maintenance elseif($data['stateid'] == 10) { $ts = unixToDatetime(time()); $updates[] = "notes = '{$user['unityid']} $ts@{$data['notes']}'"; } # removing from maintenance elseif($olddata['stateid'] == 10 && $data['stateid'] != 10) { $updates[] = "notes = ''"; } # stateid if($data['stateid'] != $olddata['stateid']) $updates[] = "stateid = {$data['stateid']}"; if(count($updates)) { $query = "UPDATE computer SET " . implode(', ', $updates) . " WHERE id = {$data['rscid']}"; doQuery($query); } } # clear user resource cache for this type $key = getKey(array(array($this->restype . "Admin"), array("administer"), 0, 1, 0, 0)); unset($_SESSION['userresources'][$key]); $key = getKey(array(array($this->restype . "Admin"), array("administer"), 0, 0, 0, 0)); unset($_SESSION['userresources'][$key]); $key = getKey(array(array($this->restype . "Admin"), array("manageGroup"), 0, 1, 0, 0)); unset($_SESSION['userresources'][$key]); $key = getKey(array(array($this->restype . "Admin"), array("manageGroup"), 0, 0, 0, 0)); unset($_SESSION['userresources'][$key]); $args = $this->defaultGetDataArgs; $arr = array('status' => 'success'); if(is_array($data['rscid'])) { $tmp = $this->getData($args); $arr['addmode'] = 'multiple'; $arr['data'] = array(); foreach($data['rscid'] as $compid) { $tmp[$compid]['name'] = $tmp[$compid]['hostname']; $arr['data'][] = $tmp[$compid]; } $arr['grouphelp'] = "Select groups from the list on the right and click the " . "Add button to add the new computer set to those groups.

"; $cdata = $this->basecdata; $cdata['newids'] = $data['rscid']; $cdata['mode'] = 'add'; $arr['addcont'] = addContinuationsEntry('AJaddRemGroupResource', $cdata); $cdata['mode'] = 'remove'; $arr['remcont'] = addContinuationsEntry('AJaddRemGroupResource', $cdata); } else { if($add) $arr['addmode'] = 'single'; $args['rscid'] = $data['rscid']; $tmp = $this->getData($args); $data = $tmp[$data['rscid']]; $arr['data'] = $data; $arr['data']['name'] = $arr['data']['hostname']; } if($add) { $arr['action'] = 'add'; $arr['nogroups'] = 0; $groups = getUserResources(array($this->restype . 'Admin'), array('manageGroup'), 1); if(count($groups[$this->restype])) $arr['groupingHTML'] = $this->groupByResourceHTML(); else $arr['nogroups'] = 1; } else $arr['action'] = 'edit'; if($promptuser) { $arr['promptuser'] = 1; $arr['btntxt'] = $btntxt; $arr['title'] = $title; $arr['msg'] = $msg; $arr['cont'] = $promptcont; } elseif($promptuserfail) { $arr['promptuserfail'] = 1; $arr['title'] = $title; $arr['msg'] = $msg; } if($multirefresh) $arr['multirefresh'] = $multirefresh; sendJSON($arr); } ///////////////////////////////////////////////////////////////////////////// /// /// \fn validateResourceData() /// /// \return array with these fields:\n /// \b rscid - id of resource (from computer table)\n /// \b name - hostname of computer\n /// \b startnum - start number when doing multiple add\n /// \b endnum - end number when doing multiple add\n /// \b owner\n /// \b type - type of computer\n /// \b IPaddress - public IP address\n /// \b privateIPaddress - private IP address\n /// \b eth0macaddress - public MAC address\n /// \b eth1macaddress - private MAC address\n /// \b startpubipaddress - start public IP address when doing multiple add\n /// \b endpubipaddress - end public IP address when doing multiple add\n /// \b startprivipaddress - start private IP address when doing multiple /// add\n /// \b endprivipaddress - end private IP address when doing multiple add\n /// \b startmac - start MAC address when doing multiple add\n /// \b provisioningid - id of provisioning engine for computer(s)\n /// \b stateid - id for state of computer\n /// \b notes - maintenance notes when setting computer to maintenance state\n /// \b vmprofileid - id of vmprofile when setting to vmhostinuse state\n /// \b platformid - id of platform\n /// \b scheduleid - id of schedule\n /// \b ram\n /// \b cores\n /// \b procspeed\n /// \b network\n /// \b predictivemoduleid - id of module to use when preloading nodes\n /// \b natenabled - 1 to use NAT for this computer, 0 not to\n /// \b nathostid - id of NAT host for this computer\n /// \b location - free string describing location\n /// \b mode - 'edit' or 'add'\n /// \b addmode - 'single' or 'multiple'\n /// \b startpubiplong - numeric value for start public IP address when doing /// multiple add\n /// \b endpubiplong - numeric value for end public IP address when doing /// multiple add\n /// \b startpriviplong - numeric value for start private IP address when /// doing multiple add\n /// \b endpriviplong - numeric value for end private IP address when doing /// multiple add\n /// \b error - 0 if submitted data validates; 1 if anything is invalid\n /// \b errormsg - if error = 1; string of error messages separated by html /// break tags /// /// \brief validates form input from editing or adding a computer /// ///////////////////////////////////////////////////////////////////////////// function validateResourceData() { global $user; $return = array('error' => 0); $return['rscid'] = getContinuationVar('rscid', 0); $return['name'] = processInputVar('name', ARG_STRING); $return['startnum'] = processInputVar('startnum', ARG_NUMERIC); $return['endnum'] = processInputVar('endnum', ARG_NUMERIC); $return['owner'] = processInputVar('owner', ARG_STRING, "{$user['unityid']}@{$user['affiliation']}"); $return['type'] = processInputVar('type', ARG_STRING); $return['IPaddress'] = processInputVar('ipaddress', ARG_STRING); $return['privateIPaddress'] = processInputVar('privateipaddress', ARG_STRING); $return['eth0macaddress'] = processInputVar('privatemac', ARG_STRING); $return['eth1macaddress'] = processInputVar('publicmac', ARG_STRING); $return['startpubipaddress'] = processInputVar('startpubipaddress', ARG_STRING); $return['endpubipaddress'] = processInputVar('endpubipaddress', ARG_STRING); $return['startprivipaddress'] = processInputVar('startprivipaddress', ARG_STRING); $return['endprivipaddress'] = processInputVar('endprivipaddress', ARG_STRING); $return['startmac'] = processInputVar('startmac', ARG_STRING); $return['provisioningid'] = processInputVar('provisioningid', ARG_NUMERIC); $return['stateid'] = processInputVar('stateid', ARG_NUMERIC); $return['notes'] = processInputVar('notes', ARG_STRING); $return['vmprofileid'] = processInputVar('vmprofileid', ARG_NUMERIC); $return['platformid'] = processInputVar('platformid', ARG_NUMERIC); $return['scheduleid'] = processInputVar('scheduleid', ARG_NUMERIC); $return['ram'] = processInputVar('ram', ARG_NUMERIC); $return['cores'] = processInputVar('cores', ARG_NUMERIC); $return['procspeed'] = processInputVar('procspeed', ARG_NUMERIC); $return['network'] = processInputVar('network', ARG_NUMERIC); $return['predictivemoduleid'] = processInputVar('predictivemoduleid', ARG_NUMERIC); $return['natenabled'] = processInputVar('natenabled', ARG_NUMERIC); $return['nathostid'] = processInputVar('nathostid', ARG_NUMERIC); $return['nathostenabled'] = processInputVar('nathostenabled', ARG_NUMERIC); $return['natpublicIPaddress'] = processInputVar('natpublicipaddress', ARG_STRING); $return['natinternalIPaddress'] = processInputVar('natinternalipaddress', ARG_STRING); $return['location'] = processInputVar('location', ARG_STRING); $addmode = processInputVar('addmode', ARG_STRING); if(! is_null($addmode) && $addmode != 'single' && $addmode != 'multiple') { $return['error'] = 1; $return['errormsg'] = "Invalid Add mode submitted"; return $return; } $olddata = getContinuationVar('olddata'); if($return['rscid'] == 0) $return['mode'] = 'add'; else $return['mode'] = 'edit'; $errormsg = array(); # hostname $hostreg = '/^[a-zA-Z0-9_][-a-zA-Z0-9_\.]{1,49}$/'; if($return['mode'] == 'add' && $addmode == 'multiple') $hostreg = '/^[a-zA-Z0-9_%][-a-zA-Z0-9_\.%]{1,49}$/'; if(! preg_match($hostreg, $return['name'])) { $return['error'] = 1; $errormsg[] = "Hostname can only contain letters, numbers, dashes(-), periods(.), and underscores(_). It can be from 1 to 50 characters long"; } elseif($this->checkForHostname($return['name'], $return['rscid'])) { $return['error'] = 1; $errormsg[] = "A computer already exists with this hostname."; } # add multiple if($return['mode'] == 'add' && $addmode == 'multiple') { # startnum/endnum if($return['startnum'] < 0 || $return['startnum'] > 255) { $return['error'] = 1; $errormsg[] = "Start must be from 0 to 255"; } if($return['endnum'] < 0 || $return['endnum'] > 255) { $return['error'] = 1; $errormsg[] = "End must be from 0 to 255"; } if($return['startnum'] >= 0 && $return['startnum'] <= 255 && $return['endnum'] >= 0 && $return['endnum'] <= 255 && $return['startnum'] > $return['endnum']) { $return['error'] = 1; $errormsg[] = "Start must be >= End"; } $checkhosts = array(); for($i = $return['startnum']; $i <= $return['endnum']; $i++) $checkhosts[] = str_replace('%', $i, $return['name']); $allhosts = implode("','", $checkhosts); $query = "SELECT hostname FROM computer " . "WHERE hostname IN ('$allhosts') AND " . "deleted = 0"; $qh = doQuery($query); $exists = array(); while($row = mysql_fetch_assoc($qh)) $exists[] = $row['hostname']; if(count($exists)) { $hosts = implode(', ', $exists); $return['error'] = 1; $errormsg[] = "There are already computers with these hostnames: $hosts"; } } else { $return['startnum'] = 0; $return['endnum'] = 0; } # owner if(! validateUserid($return['owner'])) { $return['error'] = 1; $errormsg[] = "Submitted owner is not valid"; } # type if(! preg_match('/^(blade|lab|virtualmachine)$/', $return['type'])) { $return['error'] = 1; $errormsg[] = "Submitted type is not valid"; } # edit or add single if($return['rscid'] || ($return['mode'] == 'add' && $addmode == 'single')) { # ipaddress if(! validateIPv4addr($return['IPaddress'])) { $return['error'] = 1; $errormsg[] = "Invalid Public IP address. Must be w.x.y.z with each of " . "w, x, y, and z being between 1 and 255 (inclusive)"; } # private ipaddress if(strlen($return['privateIPaddress']) && ! validateIPv4addr($return['privateIPaddress'])) { $return['error'] = 1; $errormsg[] = "Invalid Private IP address. Must be w.x.y.z with each of " . "w, x, y, and z being between 1 and 255 (inclusive)"; } # eth0macaddress if(strlen($return['eth0macaddress'])) { if(! preg_match('/^(([A-Fa-f0-9]){2}:){5}([A-Fa-f0-9]){2}$/', $return["eth0macaddress"])) { $return['error'] = 1; $errormsg[] = "Invalid Private MAC address. Must be XX:XX:XX:XX:XX:XX " . "with each pair of XX being from 00 to FF (inclusive)"; } elseif($this->checkForMACaddress($return['eth0macaddress'], 0, $return['rscid'])) { $return['error'] = 1; $errormsg[] = "There is already a computer with this Private MAC address."; } } # eth1macaddress if(strlen($return['eth1macaddress'])) { if(! preg_match('/^(([A-Fa-f0-9]){2}:){5}([A-Fa-f0-9]){2}$/', $return["eth1macaddress"])) { $return['error'] = 1; $errormsg[] = "Invalid Public MAC address. Must be XX:XX:XX:XX:XX:XX " . "with each pair of XX being from 00 to FF (inclusive)"; } elseif($this->checkForMACaddress($return['eth1macaddress'], 1, $return['rscid'])) { $return['error'] = 1; $errormsg[] = "There is already a computer with this Public MAC address."; } } } else { $return['IPaddress'] = ''; $return['privateIPaddress'] = ''; $return['eth0macaddress'] = ''; $return['eth1macaddress'] = ''; } # add multiple if($return['mode'] == 'add' && $addmode == 'multiple') { if(! validateIPv4addr($return['startpubipaddress'])) { $return['error'] = 1; $errormsg[] = "Invalid Start Public IP address. Must be w.x.y.z with each of " . "w, x, y, and z being between 1 and 255 (inclusive)"; } if(! validateIPv4addr($return['endpubipaddress'])) { $return['error'] = 1; $errormsg[] = "Invalid End Public IP address. Must be w.x.y.z with each of " . "w, x, y, and z being between 1 and 255 (inclusive)"; } if(! validateIPv4addr($return['startprivipaddress'])) { $return['error'] = 1; $errormsg[] = "Invalid Start Private IP address. Must be w.x.y.z with each of " . "w, x, y, and z being between 1 and 255 (inclusive)"; } if(! validateIPv4addr($return['endprivipaddress'])) { $return['error'] = 1; $errormsg[] = "Invalid End Private IP address. Must be w.x.y.z with each of " . "w, x, y, and z being between 1 and 255 (inclusive)"; } $startpubiplong = ip2long($return['startpubipaddress']); $endpubiplong = ip2long($return['endpubipaddress']); if($startpubiplong > $endpubiplong) { $return['error'] = 1; $errormsg[] = "Start Public IP Address must be lower or equal to End Public IP Address"; } elseif(($endpubiplong - $startpubiplong) != ($return['endnum'] - $return['startnum'])) { $return['error'] = 1; $errormsg[] = "Public IP Address range does not equal Start/End range"; } $startpriviplong = ip2long($return['startprivipaddress']); $endpriviplong = ip2long($return['endprivipaddress']); if($startpriviplong > $endpriviplong) { $return['error'] = 1; $errormsg[] = "Start Private IP Address must be lower or equal to End Private IP Address"; } elseif(($endpriviplong - $startpriviplong) != ($return['endnum'] - $return['startnum'])) { $return['error'] = 1; $errormsg[] = "Private IP Address range does not equal Start/End range"; } $return['startpubiplong'] = $startpubiplong; $return['endpubiplong'] = $endpubiplong; $return['startpriviplong'] = $startpriviplong; $return['endpriviplong'] = $endpriviplong; $cnt = $endpubiplong - $startpubiplong + 1; if($return['startmac'] != '') { if(! preg_match('/^(([A-Fa-f0-9]){2}:){5}([A-Fa-f0-9]){2}$/', $return['startmac'])) { $return['error'] = 1; $errormsg[] = "Invalid Start MAC address. Must be XX:XX:XX:XX:XX:XX " . "with each pair of XX being from 00 to FF (inclusive)"; } elseif($this->checkMultiAddMacs($return['startmac'], $cnt, $msg, $macs)) { $return['error'] = 1; $errormsg[] = $msg; } $return['macs'] = $macs; } else $return['macs'] = array(); } else { $return['startpubipaddress'] = ''; $return['endpubipaddress'] = ''; $return['startprivipaddress'] = ''; $return['endprivipaddress'] = ''; $return['startmac'] = ''; } # provisioningid $provisioning = getProvisioning(); if(! array_key_exists($return['provisioningid'], $provisioning)) { $return['error'] = 1; $errormsg[] = "Invalid Provisioning Engine selected"; } else $return['provisioning'] = $provisioning[$return['provisioningid']]['name']; # stateid 2 - available, 10 - maintenance, 20 - vmhostinuse if(! preg_match('/^(2|10|20)$/', $return['stateid']) && ($return['mode'] == 'add' || $return['stateid'] != $olddata['stateid'])) { $return['error'] = 1; $errormsg[] = "Invalid value submitted for State"; } # validate type/provisioning combinations $provtypes = getProvisioningTypes(); if(($return['mode'] == 'add' || $olddata['provisioningid'] != $return['provisioningid']) && ! array_key_exists($return['provisioningid'], $provtypes[$return['type']])) { $return['error'] = 1; $errormsg[] = "Invalid Provisioning Engine selected for computer type"; } # validate type/provisioning/state combinations if($return['mode'] == 'add' || $olddata['stateid'] != $return['stateid']) { if($return['type'] == 'lab') { if($return['stateid'] != 2 && $return['stateid'] != 10) { $return['error'] = 1; $errormsg[] = "Invalid state submitted for computer type Lab"; } } elseif($return['type'] == 'virtualmachine') { if($return['stateid'] != 10 && ($return['mode'] == 'add' || ! is_numeric($olddata['vmhostid']) || $return['stateid'] != 2)) { $return['error'] = 1; $errormsg[] = "Invalid state submitted for computer type Virtual Machine"; } } elseif($return['type'] == 'blade') { if($provisioning[$return['provisioningid']]['name'] == 'none' && $return['stateid'] != 10 && $return['stateid'] != 20) { $return['error'] = 1; $errormsg[] = "Invalid state submitted for computer type Bare Metal"; } } } # notes if($return['stateid'] == 10) { if(! preg_match('/^([-a-zA-Z0-9_\. ,#\(\)=\+:;]{0,5000})$/', $return['notes'])) { $return['error'] = 1; $errormsg[] = "Maintenance reason can be up to 5000 characters long and may only
contain letters, numbers, spaces and these characters: - , . _ # ( ) = + : ;"; } } else $return['notes'] = ''; # vmprofileid $profiles = getVMProfiles(); if($return['type'] == 'blade' && $return['stateid'] == 20 && ! array_key_exists($return['vmprofileid'], $profiles)) { $return['error'] = 1; $errormsg[] = "Invalid value submitted for VM Host Profile"; } # platformid $platforms = getPlatforms(); if(! array_key_exists($return['platformid'], $platforms)) { $return['error'] = 1; $errormsg[] = "Invalid value submitted for Platform"; } # scheduleid $schedules = getSchedules(); if(! array_key_exists($return['scheduleid'], $schedules)) { $return['error'] = 1; $errormsg[] = "Invalid value submitted for Schedule"; } # ram if($return['ram'] < 500 || $return['ram'] > 16777215) { $return['error'] = 1; $errormsg[] = "Invalid value submitted for RAM"; } # cores if($return['cores'] < 1 || $return['cores'] > 255) { $return['error'] = 1; $errormsg[] = "Invalid value submitted for No. Cores"; } # procspeed if($return['procspeed'] < 500 || $return['procspeed'] > 10000) { $return['error'] = 1; $errormsg[] = "Invalid value submitted for Processor Speed"; } # network if(! preg_match('/^(10|100|1000|10000|100000)$/', $return['network'])) { $return['error'] = 1; $errormsg[] = "Invalid value submitted for Network"; } # predictivemoduleid $premodules = getPredictiveModules(); if(! array_key_exists($return['predictivemoduleid'], $premodules)) { $return['error'] = 1; $errormsg[] = "Invalid value submitted for Predictive Loading Module"; } $naterror = 0; # natenabled if($return['natenabled'] != 0 && $return['natenabled'] != 1) { $return['error'] = 1; $errormsg[] = "Invalid value for Connect Using NAT"; $naterror = 1; } # nathostid $nathosts = getNAThosts(); if(($return['natenabled'] && $return['nathostid'] == 0) || ($return['nathostid'] != 0 && ! array_key_exists($return['nathostid'], $nathosts))) { $return['error'] = 1; $errormsg[] = "Invalid value submitted for NAT Host"; $naterror = 1; } # nat change - check for active reservations $vclreloadid = getUserlistID('vclreload@Local'); if($return['mode'] == 'edit') { if($olddata['nathostid'] == '') $olddata['nathostid'] = 0; if(! $naterror && ($olddata['natenabled'] != $return['natenabled'] || $olddata['nathostid'] != $return['nathostid'])) { $query = "SELECT rq.id " . "FROM request rq, " . "reservation rs " . "WHERE rs.requestid = rq.id AND " . "rs.computerid = {$return['rscid']} AND " . "rq.start <= NOW() AND " . "rq.end > NOW() AND " . "rq.stateid NOT IN (1,5,11,12) AND " . "rq.laststateid NOT IN (1,5,11,12) AND " . "rq.userid != $vclreloadid"; $qh = doQuery($query); if(mysql_num_rows($qh)) { $return['error'] = 1; $errormsg[] = "This computer has an active reservation. NAT settings cannot be changed for computers having
active reservations."; } } } $nathosterror = 0; # nathostenabled if($return['nathostenabled'] != 0 && $return['nathostenabled'] != 1) { $return['error'] = 1; $errormsg[] = "Invalid value for Use as NAT Host"; $nathosterror = 1; } # natpublicIPaddress if($return['nathostenabled'] && ($return['mode'] == 'edit' || $addmode == 'single')) { if(! validateIPv4addr($return['natpublicIPaddress'])) { $return['error'] = 1; $errormsg[] = "Invalid NAT Public IP address. Must be w.x.y.z with each of " . "w, x, y, and z being between 1 and 255 (inclusive)"; $nathosterror = 1; } # natinternalIPaddress if(! validateIPv4addr($return['natinternalIPaddress'])) { $return['error'] = 1; $errormsg[] = "Invalid NAT Internal IP address. Must be w.x.y.z with each of " . "w, x, y, and z being between 1 and 255 (inclusive)"; $nathosterror = 1; } } # nat host change - check for active reservations if(! $nathosterror && $return['mode'] == 'edit') { if($olddata['nathostenabled'] != $return['nathostenabled'] || $olddata['natpublicIPaddress'] != $return['natpublicIPaddress'] || $olddata['natinternalIPaddress'] != $return['natinternalIPaddress']) { $query = "SELECT rq.id " . "FROM request rq, " . "reservation rs, " . "nathostcomputermap nhcm, " . "nathost nh " . "WHERE rs.requestid = rq.id AND " . "rs.computerid = nhcm.computerid AND " . "nhcm.nathostid = nh.id AND " . "nh.resourceid = {$olddata['resourceid']} AND " . "rq.start <= NOW() AND " . "rq.end > NOW() AND " . "rq.stateid NOT IN (1,5,11,12) AND " . "rq.laststateid NOT IN (1,5,11,12) AND " . "rq.userid != $vclreloadid"; $qh = doQuery($query); if(mysql_num_rows($qh)) { $return['error'] = 1; $errormsg[] = "This computer is the NAT host for other computers that have active reservations. NAT host
settings cannot be changed while providing NAT for active reservations."; } } } # location if(! preg_match('/^([-a-zA-Z0-9_\. ,@#\(\)]{0,255})$/', $return['location'])) { $return['error'] = 1; $errormsg[] = "Invalid value submitted for Location"; } if($return['mode'] == 'add') $return['addmode'] = $addmode; if($return['error']) $return['errormsg'] = implode('
', $errormsg); return $return; } ///////////////////////////////////////////////////////////////////////////// /// /// \fn checkForHostname($hostname, $compid) /// /// \param $hostname - a computer hostname /// \param $compid - (optional) a computer id to ignore /// /// \return 1 if $hostname is already in the computer table, 0 if not /// /// \brief checks for $hostname being somewhere in the computer table except /// for $compid /// ///////////////////////////////////////////////////////////////////////////// function checkForHostname($hostname, $compid='') { $query = "SELECT id FROM computer " . "WHERE hostname = '$hostname' AND " . "deleted = 0"; if(! empty($compid)) $query .= " AND id != $compid"; $qh = doQuery($query); if(mysql_num_rows($qh)) return 1; return 0; } ///////////////////////////////////////////////////////////////////////////// /// /// \fn checkForMACaddress($mac, $num, $compid) /// /// \param $mac - computer mac address /// \param $num - which mac address to check - 0 or 1 /// \param $compid - (optional) a computer id to ignore /// /// \return 1 if $mac/$num is already in the computer table, 0 if not /// /// \brief checks for $mac being somewhere in the computer table except /// for $compid /// ///////////////////////////////////////////////////////////////////////////// function checkForMACaddress($mac, $num, $compid='') { if($num == 0) $field = 'eth0macaddress'; else $field = 'eth1macaddress'; $query = "SELECT id FROM computer " . "WHERE $field = '$mac' AND " . "deleted = 0"; if(! empty($compid)) $query .= " AND id != $compid"; $qh = doQuery($query); if(mysql_num_rows($qh)) return 1; return 0; } ///////////////////////////////////////////////////////////////////////////// /// /// \fn checkForIPaddress($ipaddress, $type, $compid) /// /// \param $ipaddress - a computer ip address /// \param $type - 'public' or 'private' - which IP address to check /// \param $compid - (optional) a computer id to ignore /// /// \return 1 if $ipaddress is already in the computer table, 0 if not /// /// \brief checks for $ipaddress being somewhere in the computer table except /// for $compid /// ///////////////////////////////////////////////////////////////////////////// function checkForIPaddress($ipaddress, $type, $compid='') { if($type == 'public') $field = 'IPaddress'; else $field = 'privateIPaddress'; $query = "SELECT id FROM computer " . "WHERE $field = '$ipaddress'"; if(! empty($compid)) $query .= " AND id != $compid"; $qh = doQuery($query); if(mysql_num_rows($qh)) return 1; return 0; } ///////////////////////////////////////////////////////////////////////////// /// /// \fn addResource($data) /// /// \param $data - array of needed data for adding a new resource /// /// \return id of new resource /// /// \brief handles adding a new computer and other associated data to the /// database /// ///////////////////////////////////////////////////////////////////////////// function addResource($data) { global $user; $ownerid = getUserlistID($data['owner']); $noimageid = getImageId('noimage'); $norevid = getProductionRevisionid($noimageid); $keys = array('hostname', 'ownerid', 'type', 'IPaddress', 'privateIPaddress', 'eth0macaddress', 'eth1macaddress', 'provisioningid', 'stateid', 'platformid', 'scheduleid', 'RAM', 'procnumber', 'procspeed', 'network', 'currentimageid', 'imagerevisionid', 'location', 'predictivemoduleid'); if($data['addmode'] == 'single') { $eth0 = "'{$data['eth0macaddress']}'"; if($data['eth0macaddress'] == '') $eth0 = 'NULL'; $eth1 = "'{$data['eth1macaddress']}'"; if($data['eth1macaddress'] == '') $eth1 = 'NULL'; $values = array("'{$data['name']}'", $ownerid, "'{$data['type']}'", "'{$data['IPaddress']}'", "'{$data['privateIPaddress']}'", $eth0, $eth1, $data['provisioningid'], $data['stateid'], $data['platformid'], $data['scheduleid'], $data['ram'], $data['cores'], $data['procspeed'], $data['network'], $noimageid, $norevid, "'{$data['location']}'", $data['predictivemoduleid']); $query = "INSERT INTO computer (" . implode(', ', $keys) . ") VALUES (" . implode(', ', $values) . ")"; doQuery($query); $rscid = dbLastInsertID(); # vmhost entry if($data['stateid'] == '20') { $query = "INSERT INTO vmhost " . "(computerid, " . "vmlimit, " . "vmprofileid) " . "VALUES ($rscid, " . "5, " . "{$data['vmprofileid']})"; doQuery($query); } # NAT if($data['natenabled']) { $query = "INSERT INTO nathostcomputermap " . "(computerid, " . "nathostid) " . "VALUES ($rscid, " . "{$data['nathostid']})"; doQuery($query); } // add entry in resource table $query = "INSERT INTO resource " . "(resourcetypeid, " . "subid) " . "VALUES (12, " . "$rscid)"; doQuery($query); $resourceid = dbLastInsertID(); # NAT host if($data['nathostenabled']) { $query = "INSERT INTO nathost " . "(resourceid, " . "publicIPaddress, " . "internalIPaddress) " . "VALUES " . "($resourceid, " . "'{$data['natpublicIPaddress']}', " . "'{$data['natinternalIPaddress']}')"; doQuery($query); } return $rscid; } else { # add multiple computers $alldis = array(); for($i = $data['startnum'], $cnt = 0; $i <= $data['endnum']; $i++, $cnt++) { $hostname = str_replace('%', $i, $data["name"]); $pubip = long2ip($data['startpubiplong'] + $cnt); $privip = long2ip($data['startpriviplong'] + $cnt); if(count($data['macs'])) { $eth0 = "'" . $data['macs'][$cnt * 2] . "'"; $eth1 = "'" . $data['macs'][($cnt * 2) + 1] . "'"; } else { $eth0 = 'NULL'; $eth1 = 'NULL'; } $values = array("'$hostname'", $ownerid, "'{$data['type']}'", "'$pubip'", "'$privip'", $eth0, $eth1, $data['provisioningid'], $data['stateid'], $data['platformid'], $data['scheduleid'], $data['ram'], $data['cores'], $data['procspeed'], $data['network'], $noimageid, $norevid, "'{$data['location']}'", $data['predictivemoduleid']); $query = "INSERT INTO computer (" . implode(', ', $keys) . ") VALUES (" . implode(', ', $values) . ")"; doQuery($query); $rscid = dbLastInsertID(); # vmhost entry if($data['stateid'] == '20') { $query = "INSERT INTO vmhost " . "(computerid, " . "vmlimit, " . "vmprofileid) " . "VALUES ($rscid, " . "5, " . "{$data['vmprofileid']})"; doQuery($query); } # NAT if($data['natenabled']) { $query = "INSERT INTO nathostcomputermap " . "(computerid, " . "nathostid) " . "VALUES ($rscid, " . "{$data['nathostid']})"; doQuery($query); } // add entry in resource table $query = "INSERT INTO resource " . "(resourcetypeid, " . "subid) " . "VALUES (12, " . "$rscid)"; doQuery($query); $allids[] = $rscid; } return $allids; } } //////////////////////////////////////////////////////////////////////////////// /// /// \fn AJcanceltovmhostinuse() /// /// \brief cancels any reservations to place the computer in the vmhostinuse /// state /// //////////////////////////////////////////////////////////////////////////////// function AJcanceltovmhostinuse() { global $mysql_link_vcl; $compid = getContinuationVar('compid'); $type = 'none'; $query = "DELETE FROM request " . "WHERE start > NOW() AND " . "stateid = 21 AND " . "id IN (SELECT requestid " . "FROM reservation " . "WHERE computerid = $compid)"; doQuery($query); if(mysql_affected_rows($mysql_link_vcl)) $type = 'future'; $query = "UPDATE request rq, " . "reservation rs, " . "state ls " . "SET rq.stateid = 1 " . "WHERE rs.requestid = rq.id AND " . "rs.computerid = $compid AND " . "rq.start <= NOW() AND " . "rq.laststateid = ls.id AND " . "ls.name = 'tovmhostinuse'"; doQuery($query); if(mysql_affected_rows($mysql_link_vcl)) $type = 'current'; $query = "SELECT rq.start " . "FROM request rq, " . "reservation rs, " . "state ls, " . "state cs " . "WHERE rs.requestid = rq.id AND " . "rs.computerid = $compid AND " . "rq.laststateid = ls.id AND " . "rq.stateid = cs.id AND " . "ls.name = 'tovmhostinuse' AND " . "cs.name NOT IN ('failed', 'maintenance', 'complete', 'deleted') AND " . "rq.end > NOW() " . "ORDER BY rq.start"; $qh = doQuery($query); if(mysql_num_rows($qh)) $arr = array('status' => 'failed'); else { if($type == 'now') $msg = "The reservation currently being processed to place this " . "computer in the vmhostinuse state has been flagged for " . "deletion. As soon as the deletion can be processed, the " . "computer will be set to the available state."; else $msg = "The reservation scheduled to place this computer in the " . "vmhostinuse state has been deleted."; $arr = array('status' => 'success', 'msg' => $msg); } sendJSON($arr); } ///////////////////////////////////////////////////////////////////////////// /// /// \fn scheduleTovmhostinuse($compid, $imageid, $start, $vmprofileid, /// $oldvmprofileid) /// /// \param $compid - id of a computer /// \param $imageid - id of an image /// \param $start - start time in unix timestamp format /// \param $vmprofileid - id of vmprofile /// \param $oldvmprofileid - id of possible previous vmprofile /// /// \return 0 on failure, 1 on success /// /// \brief schedules or updates a reservation to move a host to the /// vmhostinuse state /// ///////////////////////////////////////////////////////////////////////////// function scheduleTovmhostinuse($compid, $imageid, $start, $vmprofileid, $oldvmprofileid) { # create a reload reservation to load machine with image # corresponding to selected vm profile $vclreloadid = getUserlistID('vclreload@Local'); $revid = getProductionRevisionid($imageid); $end = $start + SECINYEAR; # don't want anyone making a future reservation for this machine $startdt = unixToDatetime($start); $enddt = unixToDatetime($end); $failed = 0; $mnid = findManagementNode($compid, $startdt, 'now'); if($mnid == 0) return 0; # check for existing tovmhostinuse reservation $query = "SELECT rq.id, " . "rq.start, " . "rq.end, " . "rs.imageid " . "FROM request rq, " . "reservation rs " . "WHERE rs.requestid = rq.id AND " . "rs.computerid = $compid AND " . "rq.stateid = 21 AND " . "rq.start > NOW() " . "ORDER BY rq.start " . "LIMIT 1"; $qh = doQuery($query); if($row = mysql_fetch_assoc($qh)) { if(! retryGetSemaphore($imageid, $revid, $mnid, $compid, $startdt, $enddt, $row['id'])) return 0; # update existing reservation $updates = array(); $startts = datetimeToUnix($row['start']); if($start < $startts) $updates[] = "rq.start = '$startdt'"; elseif($start > $startts) $this->startchange = $startts; if($row['imageid'] != $imageid) $updates[] = "rs.imageid = $imageid"; if(count($updates)) { $query = "UPDATE request rq, " . "reservation rs " . "SET " . implode(',', $updates) ." WHERE rs.requestid = rq.id AND " . "rq.id = {$row['id']}"; doQuery($query); } } else { if(! retryGetSemaphore($imageid, $revid, $mnid, $compid, $startdt, $enddt)) return 0; # add new reservation if(! (simpleAddRequest($compid, $imageid, $revid, $startdt, $enddt, 21, $vclreloadid))) return 0; } cleanSemaphore(); $this->updateVmhostProfile($compid, $vmprofileid, $oldvmprofileid); return 1; } ///////////////////////////////////////////////////////////////////////////// /// /// \fn updateVmhostProfile($compid, $newprofileid, $oldprofileid) /// /// \param $compid - id of computer /// \param $newprofileid - id of new vmprofile /// \param $oldprofileid - id of possible previous vmprofile /// /// \brief updates a vmhost entry's vmprofileid or creates a new vmhost entry /// ///////////////////////////////////////////////////////////////////////////// function updateVmhostProfile($compid, $newprofileid, $oldprofileid) { if(is_numeric($oldprofileid)) { if($oldprofileid != $newprofileid) { # update existing entry $query = "UPDATE vmhost " . "SET vmprofileid = $newprofileid " . "WHERE computerid = $compid AND " . "vmprofileid = $oldprofileid"; doQuery($query); } } else { # create vmhost entry $query = "INSERT INTO vmhost " . "(computerid, " . "vmlimit, " . "vmprofileid) " . "VALUES ($compid, " . "5, " . "$newprofileid)"; doQuery($query); } } ///////////////////////////////////////////////////////////////////////////// /// /// \fn AJsubmitComputerStateLater() /// /// \brief schedules a computer to be converted to another state at a future /// time /// ///////////////////////////////////////////////////////////////////////////// function AJsubmitComputerStateLater() { $compid = getContinuationVar('compid'); $maintenanceonly = getContinuationVar('maintenanceonly', 0); $start = getContinuationVar('reloadstart'); $end = $start + SECINYEAR; $startdt = unixToDatetime($start); $enddt = unixToDatetime($end); $vmprofileid = getContinuationVar('vmprofileid', 0); $oldprofileid = getContinuationVar('oldprofileid', 0); $newstateid = getContinuationVar('newstateid', 0); $oldstateid = getContinuationVar('oldstateid', 0); $imageid = getContinuationVar('imageid'); $revid = getProductionRevisionid($imageid); $mode = processInputVar('mode', ARG_STRING); $msg = ''; $refreshcount = 0; if($oldstateid == 10 && $newstateid == 20 && ! is_null($mode) && $mode != 'direct' && $mode != 'reload') { $errmsg = "Invalid information submitted"; $ret = array('status' => 'error', 'errormsg' => $errmsg); sendJSON($ret); return; } $delayed = 0; # maintenance directly back to vmhostinuse if($mode == 'direct') { $vmids = getContinuationVar('vmids'); if(count($vmids)) { $allids = implode(',', $vmids); $query = "UPDATE computer " . "SET stateid = 2, " . "notes = '' " . "WHERE id in ($allids)"; doQuery($query); } $query = "UPDATE computer " . "SET stateid = 20, " . "notes = '' " . "WHERE id = $compid"; doQuery($query); $msg .= "The computer has been moved back to the vmhostinuse state and "; $msg .= "the appropriate VMs have been moved to the available state."; $title = "Change to vmhostinuse"; $refreshcount = 1; } # maintenance back to vmhostinuse with a reload elseif($mode == 'reload') { $vmids = getContinuationVar('vmids'); if(count($vmids)) $this->scheduleVMsToAvailable($vmids); $start = getReloadStartTime(); $rc = $this->scheduleTovmhostinuse($compid, $imageid, $start, $vmprofileid, $oldprofileid); if($rc == 0) { $errmsg .= "A problem was encountered while attempting to reload the "; $errmsg .= "computer with the selected VM Host Profile. Please try "; $errmsg .= "again at a later time.\n"; $errmsg = preg_replace("/(.{1,76}([ \n]|$))/", '\1
', $errmsg); $ret = array('status' => 'error', 'errormsg' => $errmsg); sendJSON($ret); return; } $msg .= "The computer has been scheduled to go back to the vmhostinuse "; $msg .= "state and the appropriate VMs have been scheduled to go back "; $msg .= "to the available state at %s."; $title = "Change to vmhostinuse"; } # anything else to vmhostinuse elseif($oldstateid != 20 && $newstateid == 20) { moveReservationsOffComputer($compid); cleanSemaphore(); $mnid = findManagementNode($compid, unixToDatetime($start), 'future'); $tmp = getCompFinalReservationTime($compid, 21); $checkstart = getExistingChangeStateStartTime($compid, 21); if(! $checkstart && $checkstart != $start && $tmp > $start) { $delayed = 1; $start = $tmp; $end = $start + SECINYEAR; $startdt = unixToDatetime($start); $enddt = unixToDatetime($end); } $vclreloadid = getUserlistID('vclreload@Local'); if($maintenanceonly) { if(! retryGetSemaphore($imageid, $revid, $mnid, $compid, $start, $end)) { $errmsg = "An error was encountered while trying to schedule this
\n"; $errmsg .= "computer for the maintenance state. Please try again later.\n"; $ret = array('status' => 'error', 'errormsg' => $errmsg); sendJSON($ret); return; } # create a tomaintenance reservation if(! (simpleAddRequest($compid, $imageid, $revid, $startdt, $enddt, 18, $vclreloadid))) { $errmsg = "An error was encountered while trying to schedule this
\n"; $errmsg .= "computer for the maintenance state. Please try again later.\n"; $ret = array('status' => 'error', 'errormsg' => $errmsg); sendJSON($ret); cleanSemaphore(); return; } $msg .= "The computer has been scheduled to be moved to the "; $msg .= "maintenance state at %s."; $title = "Change to maintenance state"; } else { # create a reload reservation to load machine with image # corresponding to selected vm profile $rc = $this->scheduleTovmhostinuse($compid, $imageid, $start, $vmprofileid, $oldprofileid); if(isset($this->startchange)) { $start = $this->startchange; $delayed = 1; } if($rc == 0) { $errmsg = "An error was encountered while trying to convert this "; $errmsg .= "computer to a VM host server. Please try again later."; $errmsg = preg_replace("/(.{1,76}([ \n]|$))/", '\1
', $errmsg); $ret = array('status' => 'error', 'errormsg' => $errmsg); sendJSON($ret); return; } $msg .= "The computer has been scheduled to be moved to the "; $msg .= "vmhostinuse state at %s."; $title = "Change to vmhostinuse state"; } cleanSemaphore(); } # vmhostinuse to available elseif($oldstateid == 20 && $newstateid == 2) { $tmp = getCompFinalVMReservationTime($compid, 1); if($tmp == -1) { $errmsg .= "A problem was encountered while attempting to schedule "; $errmsg .= "assigned VMs to be removed from the computer. Please "; $errmsg .= "try again at a later time.\n"; $errmsg = preg_replace("/(.{1,76}([ \n]|$))/", '\1
', $errmsg); $ret = array('status' => 'error', 'errormsg' => $errmsg); sendJSON($ret); return; } elseif($tmp > $start) { $delayed = 1; $start = $tmp; $end = $start + SECINYEAR; $startdt = unixToDatetime($start); $enddt = unixToDatetime($end); } $vclreloadid = getUserlistID('vclreload@Local'); $query = "SELECT vm.id " . "FROM computer vm, " . "vmhost v " . "WHERE v.computerid = $compid AND " . "vm.vmhostid = v.id"; $qh = doQuery($query); $fail = 0; while($row = mysql_fetch_assoc($qh)) { if(! simpleAddRequest($row['id'], $imageid, $revid, $startdt, $enddt, 18, $vclreloadid)) { $fail = 1; break; } } cleanSemaphore(); if($fail) { $errmsg = "A problem was encountered while attempting to remove VMs "; $errmsg .= "from the computer. Please try again at a later time.\n"; $errmsg = preg_replace("/(.{1,76}([ \n]|$))/", '\1
', $errmsg); $ret = array('status' => 'error', 'errormsg' => $errmsg); sendJSON($ret); return; } else { $start = $start + 300; $end = $start + SECINYEAR; $startdt = unixToDatetime($start); $enddt = unixToDatetime($end); if(! simpleAddRequest($compid, $imageid, $revid, $startdt, $enddt, 19, $vclreloadid)) { $errmsg = "A problem was encountered while attempting to schedule "; $errmsg .= "the computer back to the available state. Please try "; $errmsg .= "again at a later time.\n"; $errmsg = preg_replace("/(.{1,76}([ \n]|$))/", '\1
', $errmsg); $title = 'Change State to Available Failed'; $ret = array('status' => 'error', 'errormsg' => $errmsg); sendJSON($ret); return; } $msg .= "The computer has been scheduled to be moved to the "; $msg .= "available state at %s."; $title = "Change to available state"; } } # vmhostinuse to maintenance # vmhostinuse to vmhostinuse with a profile change elseif(($oldstateid == 20 && $newstateid == 10) || ($oldstateid == 20 && $newstateid == 20 && $oldprofileid != $vmprofileid)) { if($newstateid == 10) { $tomaintenance = 1; $reloadstateid = 18; } else { $tomaintenance = 0; $reloadstateid = 21; } moveReservationsOffVMs($compid); cleanSemaphore(); $mnid = findManagementNode($compid, unixToDatetime($start), 'future'); $tmp = getCompFinalVMReservationTime($compid, 1, 1); if($tmp == -1) { if($tomaintenance) { $errmsg .= "A problem was encountered while attempting to schedule "; $errmsg .= "assigned VMs to be moved to the maintenance state. "; $errmsg .= "Please try again at a later time.\n"; } else { $errmsg .= "A problem was encountered while attempting to schedule "; $errmsg .= "assigned VMs to be moved to the maintenance state while "; $errmsg .= "the computer is reloaded. Please try again at a later time.\n"; } $errmsg = preg_replace("/(.{1,76}([ \n]|$))/", '\1
', $errmsg); $ret = array('status' => 'error', 'errormsg' => $errmsg); sendJSON($ret); return; } elseif($tmp > $start) $delayed = 1; $vclreloadid = getUserlistID('vclreload@Local'); $start = $tmp; $end = $start + SECINYEAR; $startdt = unixToDatetime($start); $enddt = unixToDatetime($end); $fail = 0; $vmids = array(); $query = "SELECT vm.id " . "FROM computer vm, " . "vmhost v " . "WHERE v.computerid = $compid AND " . "vm.vmhostid = v.id"; $qh = doQuery($query); while($row = mysql_fetch_assoc($qh)) { $checkstart = getExistingChangeStateStartTime($row['id'], 18); if($checkstart) { if($checkstart > $start) # update start time of existing tomaintenance reservation updateExistingToState($row['id'], $startdt, 18); # leave existing tomaintenance reservation as is } elseif(! simpleAddRequest($row['id'], $imageid, $revid, $startdt, $enddt, 18, $vclreloadid)) { $fail = 1; break; } $vmids[] = $row['id']; } if(count($vmids)) { $allids = implode(',', $vmids); $query = "UPDATE computer " . "SET notes = 'maintenance with host $compid' " . "WHERE id IN ($allids)"; doQuery($query); } cleanSemaphore(); if($fail) { $errmsg = "A problem was encountered while attempting to schedule "; $errmsg .= "the VMs to the maintenance state. Please try "; $errmsg .= "again at a later time.\n"; $errmsg = preg_replace("/(.{1,76}([ \n]|$))/", '\1
', $errmsg); $ret = array('status' => 'error', 'errormsg' => $errmsg); sendJSON($ret); return; } else { $start = $start + 300; $end = $start + SECINYEAR; $startdt = unixToDatetime($start); $enddt = unixToDatetime($end); $checkstart = getExistingChangeStateStartTime($compid, 18); if($checkstart) { if($checkstart > $start) # update start time of existing tomaintenance reservation updateExistingToState($compid, $startdt, 18); # leave existing tomaintenance reservation as is } elseif(! simpleAddRequest($compid, $imageid, $revid, $startdt, $enddt, $reloadstateid, $vclreloadid)) { if($tomaintenance) { $errmsg = "A problem was encountered while attempting to schedule "; $errmsg .= "the node to the maintenance state. Please try "; $errmsg .= "again at a later time.\n"; } else { $errmsg = "A problem was encountered while attempting to schedule "; $errmsg .= "the node to be reloaded. Please try again at a later time.\n"; } $errmsg = preg_replace("/(.{1,76}([ \n]|$))/", '\1
', $errmsg); $ret = array('status' => 'error', 'errormsg' => $errmsg); sendJSON($ret); return; } if($tomaintenance) { $msg .= "The computer has been scheduled to be moved to the "; $msg .= "maintenance state at %s."; $title = "Change to maintenance state"; } else { $msg .= "The computer has been scheduled to be reloaded with "; $msg .= "the selected VM Host Profile at %s."; $title = "Reload Computer"; } } } # anything else to maintenance elseif($oldstateid != 10 && $newstateid == 10) { $mnid = findManagementNode($compid, unixToDatetime($start), 'future'); if(! retryGetSemaphore($imageid, $revid, $mnid, $compid, $start, $end)) { $errmsg = "An error was encountered while trying to schedule this
\n"; $errmsg .= "computer for the maintenance state. Please try again later.\n"; $ret = array('status' => 'error', 'errormsg' => $errmsg); sendJSON($ret); return; } # create a tomaintenance reservation $vclreloadid = getUserlistID('vclreload@Local'); if(! (simpleAddRequest($compid, $imageid, $revid, $startdt, $enddt, 18, $vclreloadid))) { $errmsg = "An error was encountered while trying to schedule this
\n"; $errmsg .= "computer for the maintenance state. Please try again later.\n"; $ret = array('status' => 'error', 'errormsg' => $errmsg); sendJSON($ret); cleanSemaphore(); return; } $msg .= "The computer has been scheduled to be moved to the "; $msg .= "maintenance state at %s."; $title = "Change to maintenance state"; } if($delayed) { $note = "NOTE: The time for the scheduled change has been updated "; $note .= "from what was previously reported.
\n"; $msg = $note . $msg; } $schtime = date('g:i a \o\n n/j/y', $start); $msg = sprintf($msg, $schtime); $msg = preg_replace("/(.{1,76}([ \n]|$))/", '\1
', $msg); $ret = array('status' => 'success', 'title' => $title, 'clearselection' => 1, 'refreshcount' => $refreshcount, 'msg' => $msg); sendJSON($ret); } ///////////////////////////////////////////////////////////////////////////// /// /// \fn AJreloadComputers() /// /// \brief confirms reloading of computers with specified image /// ///////////////////////////////////////////////////////////////////////////// function AJreloadComputers() { $imageid = processInputVar('imageid', ARG_NUMERIC); $resources = getUserResources(array("imageAdmin", "imageCheckOut")); if(! array_key_exists($imageid, $resources['image'])) { $ret = array('status' => 'noaccess'); sendJSON($ret); return; } $compids = $this->validateCompIDs(); if(array_key_exists('error', $compids)) { $ret = array('status' => 'error', 'errormsg' => $compids['msg']); sendJSON($ret); return; } if(count($compids) == 0) { $ret = array('status' => 'noaction'); sendJSON($ret); return; } $computers = $this->getData($this->defaultGetDataArgs); $imagedata = getImages(0, $imageid); $reloadnow = array(); $reloadasap = array(); $noreload = array(); foreach($compids as $compid) { switch($computers[$compid]['state']) { case "available": case "failed": case "reloading": $reloadnow[] = $compid; break; case "inuse": case "timeout": case "reserved": $reloadasap[] = $compid; break; case "maintenance": $noreload[] = $compid; break; default: $noreload[] = $compid; break; } } $msg = ''; if(count($reloadnow)) { $msg .= "The following computers will be immediately reloaded with "; $msg .= "{$imagedata[$imageid]['prettyname']}:
\n"; foreach($reloadnow as $compid) $msg .= "{$computers[$compid]['hostname']}
\n"; $msg .= "
\n"; } if(count($reloadasap)) { $msg .= "The following computers are currently in use and will have "; $msg .= "{$imagedata[$imageid]['prettyname']} set as "; $msg .= "a priority for reloading at the end of the existing reservation "; $msg .= "on each node:
\n"; foreach($reloadasap as $compid) $msg .= "{$computers[$compid]['hostname']}
\n"; $msg .= "
\n"; } if(count($noreload)) { $msg .= "The following computers are currently in the maintenance "; $msg .= "state and therefore will have nothing done to them:
\n"; foreach($noreload as $compid) $msg .= "{$computers[$compid]['hostname']}
\n"; $msg .= "
\n"; } $cdata = $this->basecdata; $cdata['imageid'] = $imageid; $cdata['imagename'] = $imagedata[$imageid]['prettyname']; $cdata['compids'] = $compids; $ret = array('status' => 'success', 'title' => "Reload Computers", 'btntxt' => 'Reload Computers', 'actionmsg' => $msg); if(count($reloadnow) || count($reloadasap)) { $cont = addContinuationsEntry('AJsubmitReloadComputers', $cdata, SECINDAY, 1, 0); $ret['cont'] = $cont; } else { $ret['cont'] = ''; $ret['disablesubmit'] = 1; } sendJSON($ret); } ///////////////////////////////////////////////////////////////////////////// /// /// \fn AJsubmitReloadComputers() /// /// \brief reloads computers with specified image /// ///////////////////////////////////////////////////////////////////////////// function AJsubmitReloadComputers() { $data = getContinuationVar(); # imageid, compids, imagename $start = getReloadStartTime(); $end = $start + 1200; // + 20 minutes $startstamp = unixToDatetime($start); $endstamp = unixToDatetime($end); $imagerevisionid = getProductionRevisionid($data['imageid']); $computers = $this->getData($this->defaultGetDataArgs); $reloadnow = array(); $reloadasap = array(); $fails = array(); $passes = array(); foreach($data['compids'] as $compid) { if($computers[$compid]['state'] == 'available' || $computers[$compid]['state'] == 'failed') { $mn = findManagementNode($compid, unixToDatetime($start), 1); if($mn == 0) { $fails[] = $compid; continue; } if(getSemaphore($data['imageid'], $imagerevisionid, $mn, $compid, $startstamp, $endstamp)) { $query = "SELECT rq.id " . "FROM request rq, " . "reservation rs, " . "state s " . "WHERE rs.requestid = rq.id AND " . "rq.stateid = s.id AND " . "rs.computerid = $compid AND " . "rq.start < '$endstamp' AND " . "rq.end > '$startstamp' AND " . "s.name NOT IN ('complete', 'deleted', 'failed', 'timeout')"; $qh = doQuery($query); if(! mysql_num_rows($qh)) $reloadnow[] = $compid; else $reloadasap[] = $compid; } else $reloadasap[] = $compid; } } $vclreloadid = getUserlistID('vclreload@Local'); foreach($reloadnow as $compid) { if(simpleAddRequest($compid, $data['imageid'], $imagerevisionid, $startstamp, $endstamp, 19, $vclreloadid)) $passes[] = $compid; else $fails[] = $compid; } // release semaphore lock on nodes cleanSemaphore(); if(count($reloadasap)) { $compids = implode(',', $reloadasap); $query = "UPDATE computer " . "SET nextimageid = {$data['imageid']} " . "WHERE id IN ($compids)"; doQuery($query, 101); } $msg = ''; if(count($passes)) { $msg .= "The following computers are being immediately reloaded with "; $msg .= "{$data['imagename']}:
\n"; foreach($passes as $compid) $msg .= "{$computers[$compid]['hostname']}
\n"; } if(count($reloadasap)) { if(count($passes)) $msg .= "
"; $msg .= "The following computers have {$data['imagename']} "; $msg .= "set as a priority for reloading at the end of their existing "; $msg .= "reservations:
\n"; foreach($reloadasap as $compid) $msg .= "{$computers[$compid]['hostname']}
\n"; } if(count($fails)) { if(count($passes) || count($reloadasap)) $msg .= "
"; $msg .= "No functional management node was found for the following "; $msg .= "computers. They could not be reloaded at this time:
\n"; foreach($fails as $compid) $msg .= "{$computers[$compid]['hostname']}
\n"; } $ret = array('status' => 'success', 'title' => "Reload Computers", 'refreshcount' => 4, 'msg' => $msg); sendJSON($ret); } ///////////////////////////////////////////////////////////////////////////// /// /// \fn AJdeleteComputers() /// /// \brief confirms deleting submitted computers /// ///////////////////////////////////////////////////////////////////////////// function AJdeleteComputers() { $compids = $this->validateCompIDs(); if(array_key_exists('error', $compids)) { $ret = array('status' => 'error', 'errormsg' => $compids['msg']); sendJSON($ret); return; } if(count($compids) == 0) { $ret = array('status' => 'noaction'); sendJSON($ret); return; } $compdata = $this->getData($this->defaultGetDataArgs); $skipcompids = array(); $allids = implode(',', $compids); $query = "SELECT rs.computerid " . "FROM reservation rs, " . "request rq, " . "state s " . "WHERE rs.requestid = rq.id AND " . "rq.stateid = s.id AND " . "rs.computerid in ($allids) AND " . "s.name NOT IN ('deleted', 'failed', 'complete') AND " . "rq.end > NOW()"; $qh = doQuery($query); while($row = mysql_fetch_assoc($qh)) $skipcompids[] = $row['computerid']; $query = "SELECT DISTINCT bc.computerid " . "FROM blockTimes bt, " . "blockComputers bc, " . "blockRequest br " . "WHERE bc.computerid in ($allids) AND " . "bc.blockTimeid = bt.id AND " . "bt.blockRequestid = br.id AND " . "bt.end > NOW() AND " . "bt.skip = 0 AND " . "br.status = 'accepted'"; $qh = doQuery($query); while($row = mysql_fetch_assoc($qh)) $skipcompids[] = $row['computerid']; $delids = array_diff($compids, $skipcompids); $msg = ''; if(count($delids)) { $msg .= "Delete the following computers?

\n"; foreach($delids as $id) $msg .= "{$compdata[$id]['hostname']}
\n"; $msg .= '
'; } if(count($skipcompids)) { $msg .= "The following computers are currently in use and cannot be "; $msg .= "deleted at this time:

\n"; $msg .= "\n"; foreach($skipcompids as $id) $msg .= "{$compdata[$id]['hostname']}
\n"; $msg .= "
\n"; $msg .= "
\n"; } $cdata = $this->basecdata; $cdata['compids'] = $delids; $ret = array('status' => 'success', 'title' => "Delete Computers", 'btntxt' => 'Delete Computers', 'actionmsg' => $msg); if(count($delids)) { $cont = addContinuationsEntry('AJsubmitDeleteComputers', $cdata, SECINDAY, 1, 0); $ret['cont'] = $cont; } else { $ret['cont'] = ''; $ret['disablesubmit'] = 1; } sendJSON($ret); } ///////////////////////////////////////////////////////////////////////////// /// /// \fn AJsubmitDeleteComputers() /// /// \brief flags submitted computers as deleted /// ///////////////////////////////////////////////////////////////////////////// function AJsubmitDeleteComputers() { $compids = getContinuationVar('compids'); $start = getReloadStartTime(); $end = $start + 1200; // + 20 minutes $startstamp = unixToDatetime($start); $endstamp = unixToDatetime($end); $computers = $this->getData($this->defaultGetDataArgs); $fails = array(); $passes = array(); # get ids from getUserResources because that data should already be in cache $resources = getUserResources(array("imageAdmin", "imageCheckOut")); $tmp = array_keys($resources['image']); $imageid = $tmp[0]; $revid = getProductionRevisionid($imageid); $tmp = array_keys($resources['managementnode']); $mnid = $tmp[0]; foreach($compids as $compid) { if(retryGetSemaphore($imageid, $revid, $mnid, $compid, $startstamp, $endstamp)) $passes[] = $compid; else $fails[] = $compid; } $allids = implode(',', $passes); $query = "SELECT rs.computerid " . "FROM reservation rs, " . "request rq, " . "state s " . "WHERE rs.requestid = rq.id AND " . "rq.stateid = s.id AND " . "rs.computerid in ($allids) AND " . "s.name NOT IN ('deleted', 'failed', 'complete') AND " . "rq.end > NOW()"; $qh = doQuery($query); while($row = mysql_fetch_assoc($qh)) $fails[] = $row['computerid']; $delids = array_diff($compids, $fails); # FIXME this will throw an error if two computers will end up with the # same hostname after -UNDELETED-ID gets removed $allids = implode(',', $delids); $query = "UPDATE computer " . "SET deleted = 1, " . "datedeleted = NOW(), " . "hostname = REPLACE(hostname, CONCAT('-UNDELETED-', id), ''), " . "vmhostid = NULL " . "WHERE id IN ($allids)"; doQuery($query); // release lock cleanSemaphore(); if(count($delids)) { $msg = "The following computers were deleted:

\n"; foreach($delids as $compid) $msg .= "{$computers[$compid]['hostname']}
\n"; $msg .= "
"; } if(count($fails)) { $msg .= "The following computers are currently in use and could not be "; $msg .= "deleted at this time:

\n"; $msg .= "\n"; foreach($fails as $id) $msg .= "{$compdata[$id]['hostname']}
\n"; $msg .= "
\n"; $msg .= "
\n"; } # clear user resource cache for this type $key = getKey(array(array($this->restype . "Admin"), array("administer"), 0, 1, 0, 0)); unset($_SESSION['userresources'][$key]); $key = getKey(array(array($this->restype . "Admin"), array("administer"), 0, 0, 0, 0)); unset($_SESSION['userresources'][$key]); $ret = array('status' => 'success', 'title' => "Delete Computers", 'clearselection' => 1, 'refreshcount' => 1, 'msg' => $msg); sendJSON($ret); } ///////////////////////////////////////////////////////////////////////////// /// /// \fn AJcompStateChange() /// /// \brief confirms changing state of submitted computers /// ///////////////////////////////////////////////////////////////////////////// function AJcompStateChange() { $newstateid = processInputVar('stateid', ARG_NUMERIC); $states = getContinuationVar('states'); if(! array_key_exists($newstateid, $states)) { $ret = array('status' => 'noaction'); sendJSON($ret); return; } $cdata = $this->basecdata; $cdata['newstateid'] = $newstateid; $tmp = getUserResources(array($this->restype . "Admin"), array("administer"), 0, 1); $computers = $tmp['computer']; $msg = ''; $complist = ''; $compids = $this->validateCompIDs(); if($newstateid == 2) { $msg .= "You are about to place the following computers into the "; $msg .= "available state:

\n"; foreach($compids as $compid) $complist .= $computers[$compid] . "
\n"; $complist .= "
\n"; $cdata['compids'] = $compids; } elseif($newstateid == 10) { $msg .= "Please enter a reason you are changing the following computers to "; $msg .= "the maintenance state:

\n"; $msg .= "

\n"; $msg .= "These computers will be placed into the maintenance state:

\n"; foreach($compids as $compid) $complist .= $computers[$compid] . "
\n"; $complist .= "
\n"; $cdata['compids'] = $compids; } elseif($newstateid == 20) { $profiles = getVMProfiles(); $cdata['profiles'] = $profiles; $msg .= "Select a VM Host Profile to use on the selected computers:"; $msg .= "

\n"; $msg .= selectInputAutoDijitHTML('', $profiles, 'profileid'); $msg .= "

\n"; $msg .= "These computers will be deployed as VM Hosts:

\n"; foreach($compids as $compid) $complist .= $computers[$compid] . "
\n"; $complist .= "
\n"; $cdata['compids'] = $compids; } elseif($newstateid == 23) { $msg .= "These computers will be placed into the hpc state:

\n"; foreach($compids as $compid) $complist .= $computers[$compid] . "
\n"; $complist .= "
\n"; $cdata['compids'] = $compids; } $cont = addContinuationsEntry('AJsubmitCompStateChange', $cdata, SECINDAY, 1, 0); $ret = array('status' => 'success', 'title' => "State Change", 'btntxt' => 'Submit State Change', 'cont' => $cont, 'actionmsg' => $msg, 'complist' => $complist); sendJSON($ret); } ///////////////////////////////////////////////////////////////////////////// /// /// \fn AJsubmitCompStateChange() /// /// \brief changes state of submitted computers /// ///////////////////////////////////////////////////////////////////////////// function AJsubmitCompStateChange() { global $user; $newstateid = getContinuationVar('newstateid'); $compids = getContinuationVar('compids'); $states = getStates(); $ret = array('status' => 'success', 'title' => "Change State", 'clearselection' => 0, 'newstate' => $states[$newstateid], 'refreshcount' => 1); # get ids from getUserResources because that data should already be in cache $resources = getUserResources(array("imageAdmin", "imageCheckOut")); $tmp = array_keys($resources['image']); $semimageid = $tmp[0]; $semrevid = getProductionRevisionid($semimageid); if(! empty($resources['managementnode'])) { $tmp = array_keys($resources['managementnode']); $semmnid = $tmp[0]; } else { $allmns = array_keys(getManagementNodes('future')); if(empty($allmns)) { $ret = array('status' => 'error', 'errormsg' => 'No management nodes are available for controlling the submitted computers.'); sendJSON($ret); return; } $semmnid = $allmns[0]; } if($newstateid == 2) { $fails = array('provnone' => array(), 'reserved' => array(), 'hostfail' => array(), 'hasvms' => array()); $availablenow = array(); $checkvms = array(); $checkhosts = array(); $noaction = array(); $computers = $this->getData($this->defaultGetDataArgs); $inusecompids = array(); $allids = implode(',', $compids); $query = "SELECT rs.computerid " . "FROM reservation rs, " . "request rq " . "WHERE rs.requestid = rq.id AND " . "rq.end > NOW() AND " . "rq.start < NOW() AND " . "rq.stateid NOT IN (1, 5, 11, 12) AND " # TODO might not want 11 (timeout) . "rs.computerid IN ($allids)"; $qh = doQuery($query); while($row = mysql_fetch_assoc($qh)) $inusecompids[$row['computerid']] = 1; # check initial conditions foreach($compids as $compid) { # already in available if($computers[$compid]['state'] == 'available') { $noaction[] = $compid; continue; } # no provisioning engine if($computers[$compid]['provisioning'] == 'None') { $fails['provnone'][] = $compid; continue; } # non-VM in maintenance without a vmhost entry or in hpc if($computers[$compid]['state'] == 'hpc' || ($computers[$compid]['state'] == 'maintenance' && is_null($computers[$compid]['vmprofileid']) && $computers[$compid]['type'] != 'virtualmachine')) { $availablenow[] = $compid; continue; } # has active reservation if(array_key_exists($compid, $inusecompids)) { $fails['reserved'][] = $compid; continue; } # in reload, reloading, reserved, inuse, or failed with no active reservation if(preg_match('/^(reload|reloading|reserved|inuse|failed|timeout)$/', $computers[$compid]['state'])) { $availablenow[] = $compid; continue; } # vmhostinuse - check for assigned VMs if($computers[$compid]['state'] == 'vmhostinuse') { $checkvms[] = $compid; continue; } # VM in maintenance if($computers[$compid]['state'] == 'maintenance' && $computers[$compid]['type'] == 'virtualmachine') { $checkhosts[] = $compid; continue; } # maintenance - check for previously being a vmhost if($computers[$compid]['state'] == 'maintenance' && ! is_null($computers[$compid]['vmprofileid'])) { $checkvms[] = $compid; continue; } } if(count($checkvms)) { $ids = implode(',', $checkvms); $query = "SELECT h.id, " . "COUNT(vm.id) AS count " . "FROM computer h " . "LEFT JOIN vmhost vh ON (h.id = vh.computerid) " . "LEFT JOIN computer vm ON (vh.id = vm.vmhostid) " . "WHERE h.id IN ($ids) " . "GROUP BY vh.computerid"; $qh = doQuery($query); while($row = mysql_fetch_assoc($qh)) { if($row['count']) $fails['hasvms'][] = $row['id']; else $availablenow[] = $row['id']; } } if(count($checkhosts)) { $ids = implode(',', $checkhosts); $query = "SELECT h.stateid, " . "vm.id " . "FROM computer vm " . "LEFT JOIN vmhost vh ON (vm.vmhostid = vh.id) " . "LEFT JOIN computer h ON (vh.computerid = h.id) " . "WHERE vm.id IN ($ids)"; $qh = doQuery($query); while($row = mysql_fetch_assoc($qh)) { if($row['stateid'] != 20) $fails['hostfail'][] = $row['id']; else $availablenow[] = $row['id']; } } if(count($availablenow)) { $allids = implode(',', $availablenow); $query = "UPDATE computer " . "SET stateid = 2, " . "notes = '' " . "WHERE id IN ($allids)"; doQuery($query); } $msg = ''; if(count($noaction)) { $msg .= "The following computers were already in the available "; $msg .= "state:

\n"; foreach($noaction as $compid) $msg .= "{$computers[$compid]['hostname']}
\n"; $msg .= "
\n"; } if(count($availablenow)) { $msg .= "The following computers were changed to the available "; $msg .= "state:

\n"; foreach($availablenow as $compid) $msg .= "{$computers[$compid]['hostname']}
\n"; $msg .= "
\n"; } if(count($fails['provnone'])) { $msg .= "\n"; $msg .= "The following computers cannot be in the available state "; $msg .= "because they have no provisioning engine:

\n"; foreach($fails['provnone'] as $compid) $msg .= "{$computers[$compid]['hostname']}
\n"; $msg .= "
\n"; } if(count($fails['reserved'])) { $msg .= "\n"; $msg .= "The following computers are currently in use and could not have "; $msg .= "their states changed at this time:

\n"; foreach($fails['reserved'] as $compid) $msg .= "{$computers[$compid]['hostname']}
\n"; $msg .= "
\n"; } if(count($fails['hasvms'])) { $msg .= "\n"; $msg .= "The following computers currently have VMs assigned to them "; $msg .= "and cannot be moved to available until the VMs are removed:"; $msg .= "

\n"; foreach($fails['hasvms'] as $compid) $msg .= "{$computers[$compid]['hostname']}
\n"; $msg .= "
\n"; } if(count($fails['hostfail'])) { $msg .= "\n"; $msg .= "The following VMs are not currently assigned to a host in "; $msg .= "the vmhostinuse state:

\n"; foreach($fails['hostfail'] as $compid) $msg .= "{$computers[$compid]['hostname']}
\n"; $msg .= "
\n"; } } # switching to maintenance or hpc elseif($newstateid == 10 || $newstateid == 23) { if($newstateid == 10) { $notes = processInputVar('notes', ARG_STRING); if(get_magic_quotes_gpc()) $notes = stripslashes($notes); $notes = mysql_real_escape_string($notes); $notes = $user["unityid"] . " " . unixToDatetime(time()) . "@" . $notes; } $vclreloadid = getUserlistID('vclreload@Local'); $computers = $this->getData($this->defaultGetDataArgs); $noaction = array(); $changenow = array(); $changeasap = array(); $changetimes = array(); $vmwithhost = array(); $fails = array(); $semstart = unixToDatetime(time()); $semend = '2038-01-01 00:00:00'; foreach($compids as $compid) { if($newstateid == 10 && $computers[$compid]['type'] == 'virtualmachine' && in_array($computers[$compid]['vmhostcomputerid'], $compids)) $vmwithhost[] = $compid; if(($newstateid == 10 && $computers[$compid]['state'] == 'maintenance') || ($newstateid == 23 && $computers[$compid]['state'] == 'hpc')) { $noaction[] = $compid; continue; } # try to move future reservations off of computer moveReservationsOffComputer($compid); cleanSemaphore(); $reloadstart = getCompFinalReservationTime($compid); if($computers[$compid]['state'] == 'vmhostinuse') { $sem = array('imageid' => $semimageid, 'revid' => $semrevid, 'mnid' => $semmnid, 'start' => $semstart, 'end' => $semend); moveReservationsOffVMs($compid, $sem); cleanSemaphore(); $reloadstart = getCompFinalVMReservationTime($compid, 1, 1); if($reloadstart == -1) { cleanSemaphore(); $fails[] = $compid; continue; } elseif($reloadstart > 0) { if(unixToDatetime($reloadstart) == '2038-01-01 00:00:00') { # host has a VM reserved indefintely $fails[] = $compid; continue; } # schedule tomaintenance/tohpc reservations for VMs and host $noimageid = getImageId('noimage'); $revid = getProductionRevisionid($noimageid); $startdt = unixToDatetime($reloadstart); $end = $reloadstart + SECINMONTH; $enddt = unixToDatetime($end); $query = "SELECT vm.id " . "FROM computer vm, " . "vmhost v " . "WHERE v.computerid = $compid AND " . "vm.vmhostid = v.id"; $qh = doQuery($query); $setnoteids = array(); while($row = mysql_fetch_assoc($qh)) { $checkstart = getExistingChangeStateStartTime($row['id'], 18); if($checkstart) { if($checkstart > $reloadstart) # update start time of existing tomaintenance reservation updateExistingToState($row['id'], $startdt, 18); # leave existing tomaintenance reservation as is } # add tomaintenance reservation elseif(! simpleAddRequest($row['id'], $noimageid, $revid, $startdt, $enddt, 18, $vclreloadid)) { cleanSemaphore(); $fails[] = $compid; continue(2); # jump out of while, continue with foreach loop } $setnoteids[] = $row['id']; } if($newstateid == 10 && count($setnoteids)) { $inids = implode(',', $setnoteids); $query = "UPDATE computer " . "SET notes = 'maintenance with host $compid' " . "WHERE id IN ($inids)"; doQuery($query); } $start = $reloadstart + 300; # allow 5 minutes for VMs to get removed $startdt = unixToDatetime($start); # lock this computer if(! retryGetSemaphore($semimageid, $semrevid, $semmnid, $compid, $startdt, $enddt)) { cleanSemaphore(); $fails[] = $compid; continue; } if($newstateid == 10) $tostateid = 18; else $tostateid = 22; $checkstart = getExistingChangeStateStartTime($compid, $tostateid); if($checkstart) { if($checkstart > $start) # update start time of existing tomaintenance/tohpc reservation updateExistingToState($compid, $startdt, $tostateid); # leave existing tomaintenance/tohpc reservation as is } elseif(! simpleAddRequest($compid, $noimageid, $revid, $startdt, $enddt, $tostateid, $vclreloadid)) { cleanSemaphore(); $fails[] = $compid; continue; } cleanSemaphore(); $changetimes[$compid] = $start; $changeasap[] = $compid; continue; } else { if($newstateid == 10) $note = "maintenance with host $compid"; else $note = "maintenance so $compid can go to hpc"; # no VMs or no reservations on assigned VMs $query = "UPDATE computer c " . "INNER JOIN vmhost v ON (c.vmhostid = v.id) " . "SET c.stateid = 10, " . "c.notes = '$note' " . "WHERE v.computerid = $compid"; doQuery($query); } } elseif($reloadstart) { if(unixToDatetime($reloadstart) == '2038-01-01 00:00:00') { # node is reserved indefintely $fails[] = $compid; continue; } # computer has reservations, schedule tomaintenance $noimageid = getImageId('noimage'); $revid = getProductionRevisionid($noimageid); $startdt = unixToDatetime($reloadstart); $end = $reloadstart + SECINMONTH; $enddt = unixToDatetime($end); # lock this computer if(! retryGetSemaphore($semimageid, $semrevid, $semmnid, $compid, $startdt, $enddt)) { $fails[] = $compid; cleanSemaphore(); continue; } if($newstateid == 10) $tostateid = 18; else $tostateid = 22; $checkstart = getExistingChangeStateStartTime($compid, $tostateid); if($checkstart) { if($checkstart > $reloadstart) # update start time of existing tomaintenance/tohpc reservation updateExistingToState($compid, $startdt, $tostateid); else # leave existing tomaintenance/tohpc reservation as is $reloadstart = $checkstart; } elseif(! simpleAddRequest($compid, $noimageid, $revid, $startdt, $enddt, $tostateid, $vclreloadid)) { $fails[] = $compid; cleanSemaphore(); continue; } cleanSemaphore(); $changetimes[$compid] = $reloadstart; $changeasap[] = $compid; continue; } # change to maintenance/tohpc state and save in $changenow // if we wait and put them all in maintenance/hpc at the same time, # we may end up moving reservations to the computer later in the # loop # lock this computer if(! retryGetSemaphore($semimageid, $semrevid, $semmnid, $compid, $semstart, $semend)) { $fails[] = $compid; cleanSemaphore(); continue; } $query = "UPDATE computer " . "SET stateid = $newstateid " . "WHERE id = $compid"; doQuery($query, 101); $changenow[] = $compid; cleanSemaphore(); } if($newstateid == 10 && (count($noaction) || count($changeasap))) { $comparr = array_merge($noaction, $changeasap); $allids = implode(',', $comparr); if(count($vmwithhost)) $skipids = implode(',', $vmwithhost); else $skipids = "''"; $query = "UPDATE computer " . "SET notes = '$notes' " . "WHERE id IN ($allids) AND " . "id NOT IN ($skipids)"; doQuery($query, 101); $updatevms = array_intersect($vmwithhost, $comparr); if(count($updatevms)) { $inids = implode(',', $updatevms); $query = "UPDATE computer vm " . "INNER JOIN vmhost v ON (vm.vmhostid = v.id) " . "SET vm.notes = CONCAT('maintenance with host ', v.computerid) " . "WHERE vm.id IN ($inids)"; doQuery($query); } } if($newstateid == 10) $newstate = 'maintenance'; else $newstate = 'hpc'; $msg = ''; if(count($changenow)) { $msg .= "The following computers were immediately placed into the "; $msg .= "$newstate state:

\n"; $msg .= "\n"; foreach($changenow as $compid) $msg .= "{$computers[$compid]['hostname']}
\n"; $msg .= "

\n"; } if(count($changeasap)) { $msg .= "The following computers are currently reserved "; $msg .= "and will be placed in the $newstate state at the time listed "; $msg .= "for each computer:\n"; $msg .= "\n"; $msg .= " \n"; $msg .= " \n"; $msg .= " \n"; $msg .= " \n"; foreach($changeasap as $compid) { $msg .= " \n"; $msg .= " \n"; $time = date('n/j/y g:i a', $changetimes[$compid]); $msg .= " \n"; $msg .= " \n"; } $msg .= "
ComputerTime
{$computers[$compid]['hostname']}$time
\n"; $msg .= "
\n"; } if(count($fails)) { $msg .= "The following computers are currently reserved "; $msg .= "but could not be scheduled to be moved to the $newstate state "; $msg .= "at this time:

\n"; $msg .= "\n"; foreach($fails as $compid) $msg .= "{$computers[$compid]['hostname']}
\n"; $msg .= "

\n"; } if(count($noaction)) { $msg .= "The following computers were already in the $newstate state"; if($newstateid == 10) $msg .= " and had their notes on being in the maintenance state updated"; $msg .= ":

\n"; foreach($noaction as $compid) $msg .= "{$computers[$compid]['hostname']}
\n"; $msg .= "
\n"; } } # switching to vmhostinuse elseif($newstateid == 20) { $profileid = processInputVar('profileid', ARG_NUMERIC); $profiles = getContinuationVar('profiles'); if(! array_key_exists($profileid, $profiles)) { $ret = array('status' => 'error', 'errormsg' => 'Invalid profile submitted'); sendJSON($ret); return; } $vclreloadid = getUserlistID('vclreload@Local'); $imagerevisionid = getProductionRevisionid($profiles[$profileid]['imageid']); $computers = $this->getData($this->defaultGetDataArgs); $noaction = array(); $changenow = array(); $changenowreload = array(); $changeasap = array(); $changetimes = array(); $fails = array(); $semstart = unixToDatetime(time()); $semend = '2038-01-01 00:00:00'; $maintvmids = array(); $vmnotallowed = array(); $allvmids = array(); $allids = implode(',', $compids); $query = "SELECT v.computerid AS compid, " . "vm.id AS vmid, " . "vm.notes, " . "vm.stateid AS vmstateid " . "FROM computer vm, " . "vmhost v " . "WHERE v.computerid IN ($allids) AND " . "vm.vmhostid = v.id"; $qh = doQuery($query); while($row = mysql_fetch_assoc($qh)) { if(! array_key_exists($row['compid'], $maintvmids)) $maintvmids[$row['compid']] = array(); if($row['vmstateid'] == 10 && $row['notes'] == "maintenance with host {$row['compid']}") $maintvmids[$row['compid']][] = $row['vmid']; $allvmids[$row['compid']][] = $row['vmid']; } foreach($compids as $compid) { if($computers[$compid]['type'] == 'virtualmachine') { $vmnotallowed[] = $compid; continue; } # try to move future reservations off of computer moveReservationsOffComputer($compid); cleanSemaphore(); if($computers[$compid]['state'] == 'maintenance') { if($computers[$compid]['provisioning'] != 'None') { # schedule tovmhostinuse $start = getReloadStartTime(); # put computer in reload state so vcld will not ignore due to being in maintenance $query = "UPDATE computer " . "SET stateid = 19 " . "WHERE id = $compid"; doQuery($query); $rc = $this->scheduleTovmhostinuse($compid, $profiles[$profileid]['imageid'], $start, $profileid, $computers[$compid]['vmprofileid']); cleanSemaphore(); if(! $rc) { $fails[] = $compid; continue; } if(! is_null($computers[$compid]['vmprofileid']) && array_key_exists($compid, $maintvmids) && count($maintvmids[$compid])) { $noimageid = getImageId('noimage'); $revid = getProductionRevisionid($noimageid); $reloadstart = $start + 1800; $reloadstartdt = unixToDatetime($reloadstart); $end = $reloadstart + 3600; $enddt = unixToDatetime($end); foreach($maintvmids[$compid] as $vmid) { if(! retryGetSemaphore($semimageid, $semrevid, $semmnid, $vmid, $reloadstartdt, $enddt)) continue; simpleAddRequest($vmid, $noimageid, $revid, $reloadstartdt, $enddt, 19, $vclreloadid); # continue even if failed to schedule VM to be reloaded } cleanSemaphore(); } $changenowreload[] = $compid; } else { $query = "UPDATE computer " . "SET stateid = 20, " . "notes = '' " . "WHERE id = $compid"; doQuery($query); $this->updateVmhostProfile($compid, $profileid, $computers[$compid]['vmprofileid']); if(array_key_exists($compid, $maintvmids) && count($maintvmids[$compid])) { $allids = implode(',', $maintvmids[$compid]); $query = "UPDATE computer " . "SET stateid = 2, " . "notes = '' " . "WHERE id in ($allids)"; doQuery($query); } $changenow[] = $compid; } } elseif($computers[$compid]['state'] == 'hpc') { if($computers[$compid]['provisioning'] != 'None') { # schedule tovmhostinuse $start = getReloadStartTime(); # put computer in reload state so vcld will not ignore due to being in maintenance $query = "UPDATE computer " . "SET stateid = 19 " . "WHERE id = $compid"; doQuery($query); $rc = $this->scheduleTovmhostinuse($compid, $profiles[$profileid]['imageid'], $start, $profileid, $computers[$compid]['vmprofileid']); cleanSemaphore(); if(! $rc) { $fails[] = $compid; continue; } $changenowreload[] = $compid; } else { $query = "UPDATE computer " . "SET stateid = 20, " . "notes = '' " . "WHERE id = $compid"; doQuery($query); $this->updateVmhostProfile($compid, $profileid, $computers[$compid]['vmprofileid']); $changenow[] = $compid; } } elseif($computers[$compid]['state'] == 'vmhostinuse') { if($profiles[$computers[$compid]['vmprofileid']]['imageid'] != $profiles[$profileid]['imageid']) { if($computers[$compid]['provisioning'] != 'None') { $sem = array('imageid' => $semimageid, 'revid' => $semrevid, 'mnid' => $semmnid, 'start' => $semstart, 'end' => $semend); moveReservationsOffVMs($compid, $sem); cleanSemaphore(); $reloadstart = getCompFinalVMReservationTime($compid, 1); if($reloadstart < 0) { $fails[] = $compid; cleanSemaphore(); continue; } if($reloadstart == 0) $start = getReloadStartTime(); else $start = $reloadstart; $noimageid = getImageId('noimage'); $revid = getProductionRevisionid($noimageid); $startdt = unixToDatetime($start); $end = $start + SECINWEEK; $enddt = unixToDatetime($end); if($start == $reloadstart) { # check for existing reload reservations for all VMs and host $times = array(); $reqids = array(); $inids = implode(',', $allvmids[$compid]); $query = "SELECT UNIX_TIMESTAMP(MIN(rq.start)) AS start, " . "rs.computerid, " . "rq.id " . "FROM request rq, " . "reservation rs " . "WHERE rs.requestid = rq.id AND " . "rs.computerid IN ($inids) AND " . "rq.stateid = 19 AND " . "rs.imageid = $noimageid AND " . "rq.start > NOW() " . "GROUP BY rs.computerid " . "ORDER BY start"; $qh = doQuery($query); if(mysql_num_rows($qh) == count($allvmids)) { while($row = mysql_fetch_assoc($qh)) { $times[$row['start']] = 1; $reqids[] = $row['id']; } if(count($times) == 1) { # found existing reload reservations for all VMs, now check host $hoststart = $times[0] + 300; $hoststartdt = unixToDatetime($hoststart); $hostend = $hoststart + SECINYEAR; $hostenddt = unixToDatetime($hostend); $query = "SELECT rq.id, " . "rq.start " . "FROM request rq, " . "reservation rs " . "WHERE rs.requestid = rq.id AND " . "rs.computerid = $compid AND " . "rq.start = '$hoststartdt' AND " . "rq.end = '$hostenddt' AND " . "rs.imageid = '{$profiles[$profileid]['imageid']}' AND " . "rq.stateid = 21"; $qh = doQuery($query); if($row = mysql_fetch_assoc($qh)) { # node was previously scheduled to be reloaded for vmhostinuse if($times[0] > $start) { # update existing reservations $allreqids = implode(',', $reqids); $query1 = "UPDATE request " . "SET start = '$startdt', " . "end = '$enddt' " . "WHERE id IN ($allreqids)"; # delay host by 5 minutes $start = $start + 300; $startdt = unixToDatetime($start); $end = $start + SECINYEAR; $enddt = unixToDatetime($end); # lock this computer if(! retryGetSemaphore($semimageid, $semrevid, $semmnid, $compid, $startdt, $enddt)) { $fails[] = $compid; continue; } doQuery($query1); $query2 = "UPDATE request " . "SET start = '$startdt', " . "end = '$enddt' " . "WHERE id = {$row['id']}"; doQuery($query2); $changeasap[] = $compid; $changetimes[$compid] = $start; } else { # just leave the existing ones there $changeasap[] = $compid; $changetimes[$compid] = $times[0] + 300; } cleanSemaphore(); continue; } } } } if(array_key_exists($compid, $allvmids)) { foreach($allvmids[$compid] as $vmid) { $rc = simpleAddRequest($vmid, $noimageid, $revid, $startdt, $enddt, 19, $vclreloadid); if(! $rc) { $fails[] = $compid; cleanSemaphore(); continue(2); # jump out of this foreach to the bigger foreach } } } $start = $start + 300; # give 5 minutes for VMs $rc = $this->scheduleTovmhostinuse($compid, $profiles[$profileid]['imageid'], $start, $profileid, $computers[$compid]['vmprofileid']); if(! $rc) { $fails[] = $compid; continue; } if($reloadstart) { $changeasap[] = $compid; $changetimes[$compid] = $reloadstart; } else $changenowreload[] = $compid; } else { $this->updateVmhostProfile($compid, $profileid, $computers[$compid]['vmprofileid']); $changenow[] = $compid; } } else $noaction[] = $compid; } elseif(($reloadstart = moveReservationsOffComputer($compid)) == 0) { $start = getCompFinalReservationTime($compid, 21); $rc = $this->scheduleTovmhostinuse($compid, $profiles[$profileid]['imageid'], $start, $profileid, $computers[$compid]['vmprofileid']); if(! $rc) { $fails[] = $compid; continue; } $changeasap[] = $compid; if(isset($this->startchange)) $start = $this->startchange; $changetimes[$compid] = $start; } else { if($computers[$compid]['provisioning'] != 'None') { $start = getCompFinalReservationTime($compid, 21); $now = 0; if($start == 0) { $start = getReloadStartTime(); $now = 1; } $rc = $this->scheduleTovmhostinuse($compid, $profiles[$profileid]['imageid'], $start, $profileid, $computers[$compid]['vmprofileid']); if(! $rc) { $fails[] = $compid; continue; } if($now) $changenowreload[] = $compid; else { $changeasap[] = $compid; $changetimes[$compid] = $start; } } else { $query = "UPDATE computer " . "SET stateid = 20, " . "notes = '' " . "WHERE id = $compid"; doQuery($query); $this->updateVmhostProfile($compid, $profileid, $computers[$compid]['vmprofileid']); $changenow[] = $compid; } } } $msg = ''; if(count($changenow)) { $msg .= "The following computers were placed into the vmhostinuse state "; $msg .= "or had their VM Host Profiles updated:

\n"; foreach($changenow as $compid) $msg .= "{$computers[$compid]['hostname']}
\n"; $msg .= "
\n"; $ret['clearselection'] = 1; $ret['refreshcount'] = 5; } if(count($changenowreload)) { $msg .= "The following computers have been scheduled to be immediately reloaded
\n"; $msg .= "and placed into the vmhostinuse state:

\n"; foreach($changenowreload as $compid) $msg .= "{$computers[$compid]['hostname']}
\n"; $msg .= "
\n"; $ret['clearselection'] = 1; $ret['refreshcount'] = 5; } if(count($changeasap)) { $msg .= "The following computers are currently reserved and have been scheduled
\n"; $msg .= "to be reloaded and placed into the vmhostinuse state at the time listed
\n"; $msg .= "for each computers:

\n"; $msg .= "\n"; $msg .= " \n"; $msg .= " \n"; $msg .= " \n"; $msg .= " \n"; foreach($changeasap as $compid) { $msg .= " \n"; $msg .= " \n"; $time = date('n/j/y g:i a', $changetimes[$compid]); $msg .= " \n"; $msg .= " \n"; } $msg .= "
ComputerReload time
{$computers[$compid]['hostname']}$time
\n"; $msg .= "
\n"; } if(count($fails)) { $msg .= "Problems were encountered while trying to move the following computers
\n"; $msg .= "to the vmhostinuse state:

\n"; foreach($fails as $compid) $msg .= "{$computers[$compid]['hostname']}
\n"; $msg .= "
\n"; } if(count($vmnotallowed)) { $msg .= "The following computers are VMs which cannot be placed into the "; $msg .= "vmhostinuse state:

\n"; foreach($vmnotallowed as $compid) $msg .= "{$computers[$compid]['hostname']}
\n"; $msg .= "
\n"; } if(count($noaction)) { $msg .= "The following computers were already in the vmhostinuse state:

\n"; foreach($noaction as $compid) $msg .= "{$computers[$compid]['hostname']}
\n"; $msg .= "
\n"; } } # clear user resource cache for this type $key = getKey(array(array($this->restype . "Admin"), array("administer"), 0, 1, 0, 0)); unset($_SESSION['userresources'][$key]); $key = getKey(array(array($this->restype . "Admin"), array("administer"), 0, 0, 0, 0)); unset($_SESSION['userresources'][$key]); $ret['msg'] = $msg; sendJSON($ret); } ///////////////////////////////////////////////////////////////////////////// /// /// \fn AJcompProvisioningChange() /// /// \brief confirms changing provisioning engine of submitted computers /// ///////////////////////////////////////////////////////////////////////////// function AJcompProvisioningChange() { $provisioningid = processInputVar('provisioningid', ARG_NUMERIC); $provisioning = getProvisioning(); if(! array_key_exists($provisioningid, $provisioning)) { $ret = array('status' => 'error', 'errormsg' => 'Invalid Provisioning Engine submitted.'); sendJSON($ret); return; } $compids = $this->validateCompIDs(); if(array_key_exists('error', $compids)) { $ret = array('status' => 'error', 'errormsg' => $compids['msg']); sendJSON($ret); return; } if(count($compids) == 0) { $ret = array('status' => 'noaction'); sendJSON($ret); return; } $tmp = getUserResources(array($this->restype . "Admin"), array("administer"), 0, 1); $computers = $tmp['computer']; $msg = "Change the Provisioning Engine of the following
computers to "; $msg .= "{$provisioning[$provisioningid]['prettyname']}?

\n"; $complist = ''; foreach($compids as $compid) $complist .= $computers[$compid] . "
\n"; $complist .= "
\n"; $cdata = $this->basecdata; $cdata['compids'] = $compids; $cdata['provisioningid'] = $provisioningid; $cdata['provisioningname'] = $provisioning[$provisioningid]['prettyname']; $cont = addContinuationsEntry('AJsubmitCompProvisioningChange', $cdata, SECINDAY, 1, 0); $ret = array('status' => 'success', 'title' => "Provisioning Engine Change", 'btntxt' => 'Submit Provisioning Engine Change', 'cont' => $cont, 'actionmsg' => $msg, 'complist' => $complist); sendJSON($ret); } ///////////////////////////////////////////////////////////////////////////// /// /// \fn AJsubmitCompProvisioningChange /// /// \brief changes provisioning engine of submitted computers /// ///////////////////////////////////////////////////////////////////////////// function AJsubmitCompProvisioningChange() { $provisioningid = getContinuationVar('provisioningid'); $provname = getContinuationVar('provisioningname'); $compids = getContinuationVar('compids'); $startcheck = time() + 900; $startcheckdt = unixToDatetime($startcheck); $allids = implode(',', $compids); $fails = array(); $query = "SELECT rs.computerid " . "FROM request rq, " . "reservation rs " . "WHERE rs.requestid = rq.id AND " . "rs.computerid IN ($allids) AND " . "rq.start <= '$startcheckdt' AND " . "rq.end > NOW()"; $qh = doQuery($query); while($row = mysql_fetch_assoc($qh)) $fails[] = $row['computerid']; $nowids = array_diff($compids, $fails); $allids = implode(',', $nowids); $query = "UPDATE computer " . "SET provisioningid = $provisioningid " . "WHERE id in ($allids)"; doQuery($query); $resources = getUserResources(array($this->restype . "Admin"), array("administer")); $compdata = $resources[$this->restype]; if(count($nowids)) { $msg = "The following computers had their Provisioning Engine set to $provname:

\n"; foreach($nowids as $compid) $msg .= "{$compdata[$compid]}
\n"; $msg .= "
"; } if(count($fails)) { $msg .= "The following computers have or will soon have reservations "; $msg .= "on them and could not have their Provisioning Engine changed "; $msg .= "at this time:

\n"; $msg .= "\n"; foreach($fails as $id) $msg .= "{$compdata[$id]}
\n"; $msg .= "
\n"; $msg .= "
\n"; } $ret = array('status' => 'success', 'title' => "Change Provisioning Engine", 'clearselection' => 1, 'refreshcount' => 1, 'msg' => $msg); sendJSON($ret); } ///////////////////////////////////////////////////////////////////////////// /// /// \fn AJcompPredictiveModuleChange() /// /// \brief confirms changing provisioning engine of submitted computers /// ///////////////////////////////////////////////////////////////////////////// function AJcompPredictiveModuleChange() { $predictivemoduleid = processInputVar('predictivemoduleid', ARG_NUMERIC); $premodules = getPredictiveModules(); if(! array_key_exists($predictivemoduleid, $premodules)) { $ret = array('status' => 'error', 'errormsg' => 'Invalid Predictive Loading Module submitted.'); sendJSON($ret); return; } $compids = $this->validateCompIDs(); if(array_key_exists('error', $compids)) { $ret = array('status' => 'error', 'errormsg' => $compids['msg']); sendJSON($ret); return; } if(count($compids) == 0) { $ret = array('status' => 'noaction'); sendJSON($ret); return; } $tmp = getUserResources(array($this->restype . "Admin"), array("administer"), 0, 1); $computers = $tmp['computer']; $msg = "Change the Predictive Loading Module of the following
computers to "; $msg .= "{$premodules[$predictivemoduleid]['prettyname']}?

\n"; $complist = ''; foreach($compids as $compid) $complist .= $computers[$compid] . "
\n"; $complist .= "
\n"; $cdata = $this->basecdata; $cdata['compids'] = $compids; $cdata['predictivemoduleid'] = $predictivemoduleid; $cdata['predictivemodulename'] = $premodules[$predictivemoduleid]['prettyname']; $cont = addContinuationsEntry('AJsubmitCompPredictiveModuleChange', $cdata, SECINDAY, 1, 0); $ret = array('status' => 'success', 'title' => "Predictive Loading Module Change", 'btntxt' => 'Submit Predictive Loading Module Change', 'cont' => $cont, 'actionmsg' => $msg, 'complist' => $complist); sendJSON($ret); } ///////////////////////////////////////////////////////////////////////////// /// /// \fn AJsubmitCompPredictiveModuleChange /// /// \brief changes provisioning engine of submitted computers /// ///////////////////////////////////////////////////////////////////////////// function AJsubmitCompPredictiveModuleChange() { $predictivemoduleid = getContinuationVar('predictivemoduleid'); $predictivename = getContinuationVar('predictivemodulename'); $compids = getContinuationVar('compids'); $allids = implode(',', $compids); $query = "UPDATE computer " . "SET predictivemoduleid = $predictivemoduleid " . "WHERE id in ($allids)"; doQuery($query); $resources = getUserResources(array($this->restype . "Admin"), array("administer")); $compdata = $resources[$this->restype]; $msg = "The following computers had their Predictive Loading Module
set to $predictivename:

\n"; foreach($compids as $compid) $msg .= "{$compdata[$compid]}
\n"; $msg .= "
"; $ret = array('status' => 'success', 'title' => "Change Predictive Loading Module", 'clearselection' => 0, 'refreshcount' => 1, 'msg' => $msg); sendJSON($ret); } ///////////////////////////////////////////////////////////////////////////// /// /// \fn AJcompNATchange() /// /// \brief confirms changing provisioning engine of submitted computers /// ///////////////////////////////////////////////////////////////////////////// function AJcompNATchange() { $natenabled = processInputVar('natenabled', ARG_NUMERIC); $nathostid = processInputVar('nathostid', ARG_NUMERIC); $nathosts = getNAThosts(); if(($natenabled != 0 && $natenabled != 1) || ($nathostid != 0 && ! array_key_exists($nathostid, $nathosts))) { $ret = array('status' => 'error', 'errormsg' => 'Invalid value submitted.'); sendJSON($ret); return; } $compids = $this->validateCompIDs(); if(array_key_exists('error', $compids)) { $ret = array('status' => 'error', 'errormsg' => $compids['msg']); sendJSON($ret); return; } if(count($compids) == 0) { $ret = array('status' => 'noaction'); sendJSON($ret); return; } $allids = implode(',', $compids); $inusecompids = array(); $vclreloadid = getUserlistID('vclreload@Local'); $query = "SELECT rs.computerid " . "FROM request rq, " . "reservation rs " . "WHERE rs.requestid = rq.id AND " . "rs.computerid IN ($allids) AND " . "rq.start <= NOW() AND " . "rq.end > NOW() AND " . "rq.stateid NOT IN (1,5,11,12) AND " . "rq.laststateid NOT IN (1,5,11,12) AND " . "rq.userid != $vclreloadid"; $qh = doQuery($query); while($row = mysql_fetch_assoc($qh)) $inusecompids[] = $row['computerid']; $tmp = getUserResources(array($this->restype . "Admin"), array("administer"), 0, 1); $computers = $tmp['computer']; $msg = ''; if(count($inusecompids)) { $msg .= "The following computers are currently in use and cannot have
"; $msg .= "NAT settings changed at this time:

\n"; $complist = ''; foreach($inusecompids as $compid) $complist .= $computers[$compid] . "
\n"; $msg .= "
$complist
\n"; $compids = array_diff($compids, $inusecompids); } if(count($compids)) { if($natenabled) { $msg .= "Enable Connect Using NAT and set the NAT "; $msg .= "host
to {$nathosts[$nathostid]['hostname']}"; $msg .= " for the following computers?

"; } else { $msg .= "Disable Connect Using NAT for the following "; $msg .= "computers?

"; } } $complist = ''; foreach($compids as $compid) $complist .= $computers[$compid] . "
\n"; $complist .= "
\n"; $cdata = $this->basecdata; $cdata['compids'] = $compids; $cdata['natenabled'] = $natenabled; $cdata['nathostid'] = $nathostid; $cont = addContinuationsEntry('AJsubmitCompNATchange', $cdata, SECINDAY, 1, 0); $ret = array('status' => 'success', 'title' => "Connect Using NAT Change", 'btntxt' => 'Submit Connect Using NAT Change', 'cont' => $cont, 'actionmsg' => $msg, 'complist' => $complist); if(empty($compids)) { $ret['status'] = 'error'; $ret['errormsg'] = $ret['actionmsg']; unset($ret['actionmsg']); } sendJSON($ret); } ///////////////////////////////////////////////////////////////////////////// /// /// \fn AJsubmitCompNATchange /// /// \brief changes provisioning engine of submitted computers /// ///////////////////////////////////////////////////////////////////////////// function AJsubmitCompNATchange() { $natenabled = getContinuationVar('natenabled'); $nathostid = getContinuationVar('nathostid'); $compids = getContinuationVar('compids'); $allids = implode(',', $compids); $query = "DELETE FROM nathostcomputermap " . "WHERE computerid IN ($allids)"; doQuery($query); if($natenabled) { $query = "INSERT INTO nathostcomputermap " . "SELECT id, " . "$nathostid " . "FROM computer " . "WHERE id IN ($allids)"; doQuery($query); } $resources = getUserResources(array($this->restype . "Admin"), array("administer")); $compdata = $resources[$this->restype]; $msg = "Connect Using NAT was "; if($natenabled) $msg .= "Enabled"; else $msg .= "Disabled"; $msg .= " for the following computers:

\n"; foreach($compids as $compid) $msg .= "{$compdata[$compid]}
\n"; $msg .= "
"; $ret = array('status' => 'success', 'title' => "Change Connect Using NAT", 'clearselection' => 0, 'refreshcount' => 1, 'nathostid' => $nathostid, # todo 'msg' => $msg); sendJSON($ret); } ///////////////////////////////////////////////////////////////////////////// /// /// \fn AJcompScheduleChange() /// /// \brief confirms changing schedule of submitted computers /// ///////////////////////////////////////////////////////////////////////////// function AJcompScheduleChange() { $schid = processInputVar('schid', ARG_NUMERIC); $resources = getUserResources(array("scheduleAdmin"), array("manageGroup")); if(! array_key_exists($schid, $resources['schedule'])) { $ret = array('status' => 'error', 'errormsg' => 'You do not have access to the selected schedule.'); sendJSON($ret); return; } $compids = $this->validateCompIDs(); if(array_key_exists('error', $compids)) { $ret = array('status' => 'error', 'errormsg' => $compids['msg']); sendJSON($ret); return; } if(count($compids) == 0) { $ret = array('status' => 'noaction'); sendJSON($ret); return; } $tmp = getUserResources(array($this->restype . "Admin"), array("administer"), 0, 1); $computers = $tmp['computer']; $msg = "Change the schedule of the following computers to "; $msg .= "{$resources['schedule'][$schid]}?

\n"; $complist = ''; foreach($compids as $compid) $complist .= $computers[$compid] . "
\n"; $complist .= "
\n"; $cdata = $this->basecdata; $cdata['compids'] = $compids; $cdata['schid'] = $schid; $cdata['schname'] = $resources['schedule'][$schid]; $cdata['complist'] = $complist; $cont = addContinuationsEntry('AJsubmitCompScheduleChange', $cdata, SECINDAY, 1, 0); $ret = array('status' => 'success', 'title' => "Schedule Change", 'btntxt' => 'Submit Schedule Change', 'cont' => $cont, 'actionmsg' => $msg, 'complist' => $complist); sendJSON($ret); } ///////////////////////////////////////////////////////////////////////////// /// /// \fn AJsubmitCompScheduleChange() /// /// \brief changes schedule of submitted computers /// ///////////////////////////////////////////////////////////////////////////// function AJsubmitCompScheduleChange() { $schid = getContinuationVar('schid'); $schname = getContinuationVar('schname'); $compids = getContinuationVar('compids'); $complist = getContinuationVar('complist'); $allids = implode(',', $compids); $query = "UPDATE computer " . "SET scheduleid = $schid " . "WHERE id in ($allids)"; doQuery($query); $msg = "The schedule for the following computer(s) was set to "; $msg .= "$schname:
$complist\n"; # clear user resource cache for this type $key = getKey(array(array($this->restype . "Admin"), array("administer"), 0, 1, 0, 0)); unset($_SESSION['userresources'][$key]); $key = getKey(array(array($this->restype . "Admin"), array("administer"), 0, 0, 0, 0)); unset($_SESSION['userresources'][$key]); $ret = array('status' => 'success', 'title' => "Change Schedule", 'clearselection' => 1, 'refreshcount' => 1, 'msg' => $msg); sendJSON($ret); } ///////////////////////////////////////////////////////////////////////////// /// /// \fn AJgenerateDHCPdata() /// /// \brief generates configuration data for dhcpd /// ///////////////////////////////////////////////////////////////////////////// function AJgenerateDHCPdata() { $type = processInputVar('type', ARG_STRING); if($type != 'public' && $type != 'private') { $ret = array('status' => 'noaction'); sendJSON($ret); return; } if($type == 'private') { $mnip = processInputVar('mnip', ARG_STRING); if(! validateIPv4addr($mnip)) { sendJSON(array('status' => 'error', 'errmsg' => 'invalid IP address submitted')); return; } $ipprefix = 'private'; } else $ipprefix = ''; $nic = processInputVar('nic', ARG_STRING); if($nic != 'eth0' && $nic != 'eth1') $nic = 'eth0'; $compids = $this->validateCompIDs(); if(array_key_exists('error', $compids)) { $ret = array('status' => 'error', 'errormsg' => $compids['msg']); sendJSON($ret); return; } if(count($compids) == 0) { $ret = array('status' => 'noaction'); sendJSON($ret); return; } $comps = $this->getData($this->defaultGetDataArgs); if($type == 'private') { $octets = explode('.', $mnip); $hexmnip = sprintf('%02x:%02x:%02x:%02x', $octets[0], $octets[1], $octets[2], $octets[3]); } $noips = array(); $dhcpd = ''; $leases = ''; foreach($compids as $id) { if(empty($comps[$id]["{$ipprefix}IPaddress"]) || empty($comps[$id]["{$nic}macaddress"])) { $noips[] = $comps[$id]['hostname']; continue; } $tmp = explode('.', $comps[$id]['hostname']); $dhcpd .= "\t\thost {$tmp[0]} {\n"; $dhcpd .= "\t\t\toption host-name \"{$tmp[0]}\";\n"; $dhcpd .= "\t\t\thardware ethernet {$comps[$id]["{$nic}macaddress"]};\n"; $dhcpd .= "\t\t\tfixed-address {$comps[$id]["{$ipprefix}IPaddress"]};\n"; if($type == 'private') { $dhcpd .= "\t\t\tfilename \"/tftpboot/pxelinux.0\";\n"; $dhcpd .= "\t\t\toption dhcp-server-identifier $mnip;\n"; $dhcpd .= "\t\t\tnext-server $mnip;\n"; } $dhcpd .= "\t\t}\n\n"; $leases .= "host {$tmp[0]} {\n"; $leases .= "\tdynamic;\n"; $leases .= "\thardware ethernet {$comps[$id]["{$nic}macaddress"]};\n"; $leases .= "\tfixed-address {$comps[$id]["{$ipprefix}IPaddress"]};\n"; $leases .= "\tsupersede server.ddns-hostname = \"{$tmp[0]}\";\n"; $leases .= "\tsupersede host-name = \"{$tmp[0]}\";\n"; if($type == 'private') { $leases .= "\tif option vendor-class-identifier = \"ScaleMP\" {\n"; $leases .= "\t\tsupersede server.filename = \"vsmp/pxelinux.0\";\n"; $leases .= "\t} else {\n"; $leases .= "\t\tsupersede server.filename = \"pxelinux.0\";\n"; $leases .= "\t}\n"; $leases .= "\tsupersede server.next-server = $hexmnip;\n"; } $leases .= "}\n"; } $msg = ''; if(! empty($noips)) { $msg .= "The following computers did not have "; $msg .= "a $type IP address or an $nic MAC address entry and therefore "; $msg .= "could not be included in the data below:

\n"; $msg .= implode("
\n", $noips); $msg .= "

\n"; } if(! empty($dhcpd)) { $msg .= "Data to be added to dhcpd.conf:
"; $msg .= "
$dhcpd
"; $msg .= "


\n"; $msg .= "Data to be added to dhcpd.leases:
"; $msg .= "
$leases
"; } $ret = array('status' => 'onestep', 'title' => ucfirst($type) . " dhcpd Data", 'actionmsg' => $msg); sendJSON($ret); } ///////////////////////////////////////////////////////////////////////////// /// /// \fn AJhostsData() /// /// \brief generates /etc/hosts data for submitted computers /// ///////////////////////////////////////////////////////////////////////////// function AJhostsData() { $compids = $this->validateCompIDs(); if(array_key_exists('error', $compids)) { $ret = array('status' => 'error', 'errormsg' => $compids['msg']); sendJSON($ret); return; } if(count($compids) == 0) { $ret = array('status' => 'noaction'); sendJSON($ret); return; } $comps = $this->getData($this->defaultGetDataArgs); $hosts = ''; foreach($compids as $id) { if(! empty($comps[$id]['privateIPaddress'])) $hosts .= "{$comps[$id]['privateIPaddress']}\t{$comps[$id]['hostname']}\n"; else $noips[] = $comps[$id]['hostname']; } $msg = "Data to be added to /etc/hosts:

"; $msg .= "
$hosts
"; $ret = array('status' => 'onestep', 'title' => 'Generate /etc/hosts Data', 'actionmsg' => $msg); sendJSON($ret); } ///////////////////////////////////////////////////////////////////////////// /// /// \fn validateCompIDs() /// /// \return array of computerids; if user does not have access to any /// submitted computers, returns array with 'error' set to 1 and 'msg' set /// to an error message listing computers the user does not have access to /// /// \brief validates user access to submitted computers /// ///////////////////////////////////////////////////////////////////////////// function validateCompIDs() { $compids = processInputVar('compids', ARG_MULTINUMERIC); $resources = getUserResources(array($this->restype . "Admin"), array("administer"), 0, 1); $usercomps = $resources[$this->restype]; $noaccess = array(); foreach($compids as $id) { if(! array_key_exists($id, $usercomps)) $noaccess[] = $usercomps[$id]; } if(count($noaccess)) { $ret = array('error' => 1); $ret['msg'] = "Access denied to these computers:

" . implode('
', $noaccess) . "

"; return $ret; } return $compids; } ///////////////////////////////////////////////////////////////////////////// /// /// \fn scheduleVMsToAvailable() /// /// \param $vmids - array of ids of VMs to set schedule to available state /// /// \brief sets VMs to failed state so that they cannot be scheduled and /// creates a reload reservation for the noimage image /// ///////////////////////////////////////////////////////////////////////////// function scheduleVMsToAvailable($vmids) { # TODO test with vcld that will handle reservation for noimage okay # schedule $vmids to have noimage "loaded" on them in 15 minutes $allids = implode(',', $vmids); $query = "UPDATE computer " . "SET stateid = 5, " # set to failed instead of available so cannot be scheduled by users . "notes = '' " . "WHERE id IN ($allids)"; doQuery($query); $imageid = getImageId('noimage'); $revid = getProductionRevisionid($imageid); $start = time() + 900; $end = $start + 3600; $startdt = unixToDatetime($start); $enddt = unixToDatetime($end); $vclreloadid = getUserlistID('vclreload@Local'); foreach($vmids as $vmid) // if simpleAddRequest fails, vm is left assigned and in failed state, which is fine simpleAddRequest($vmid, $imageid, $revid, $startdt, $enddt, 19, $vclreloadid); } ///////////////////////////////////////////////////////////////////////////// /// /// \fn checkMultiAddMacs($startmac, $cnt, &$errmsg, &$macs) /// /// \param $startmac - starting mac address /// \param $cnt - number of computers for which to generate addresses /// \param $errmsg - if conflict, error message is put in here /// \param $macs - array of generated addresses is put in here /// /// \return 1 if error; 0 if success /// /// \brief generates all required mac addresses for adding multiple /// computers; checks that there are no duplicates with existing computers /// ///////////////////////////////////////////////////////////////////////////// function checkMultiAddMacs($startmac, $cnt, &$errmsg, &$macs) { $tmp = explode(':', $startmac); $topdec = hexdec($tmp[0] . $tmp[1] . $tmp[2]); $botdec = hexdec($tmp[3] . $tmp[4] . $tmp[5]); $topmac = "{$tmp[0]}:{$tmp[1]}:{$tmp[2]}"; $topplus = implode(':', str_split(dechex($topdec + 1), 2)); $start = $botdec; $macs = array(); $eth0macs = array(); $eth1macs = array(); $toggle = 0; $end = $start + ($cnt * 2); for($i = $start; $i < $end; $i++) { if($i > 16777215) { $val = $i - 16777216; $tmp = sprintf('%06x', $val); $tmp2 = str_split($tmp, 2); $macs[] = $topplus . ':' . implode(':', $tmp2); } else { $tmp = sprintf('%06x', $i); $tmp2 = str_split($tmp, 2); $macs[] = $topmac . ':' . implode(':', $tmp2); } if($toggle % 2) $eth1macs[] = $topmac . ':' . implode(':', $tmp2); else $eth0macs[] = $topmac . ':' . implode(':', $tmp2); $toggle++; } $ineth0s = implode("','", $eth0macs); $ineth1s = implode("','", $eth1macs); $query = "SELECT id " . "FROM computer " . "WHERE eth0macaddress IN ('$ineth0s') OR " . "eth1macaddress IN ('$ineth1s')"; $qh = doQuery($query); $errmsg = ''; if(mysql_num_rows($qh)) { $errmsg .= "The specified starting MAC address combined with the number "; $errmsg .= "of computers entered will result in a MAC address already "; $errmsg .= "assigned to another computer."; return 1; } elseif($i > 16777215 && $topdec == 16777215) { $errmsg .= "Starting MAC address too large for given given number of machines"; return 1; } return 0; } ///////////////////////////////////////////////////////////////////////////// /// /// \fn AJaddRemGroupResource() /// /// \brief adds or removes groups for a computer and sends JSON response; /// overridden from base class to handle case of adding multiple computers /// and being able to assign them all to a computer group at once /// ///////////////////////////////////////////////////////////////////////////// function AJaddRemGroupResource() { $newids = getContinuationVar('newids'); if(is_null($newids)) { $rscid = processInputVar('id', ARG_NUMERIC); $resources = getUserResources(array($this->restype . "Admin"), array("manageGroup")); if(! array_key_exists($rscid, $resources[$this->restype])) { $arr = array('status' => 'noaccess'); sendJSON($arr); return; } } $groups = getUserResources(array($this->restype . "Admin"), array("manageGroup"), 1); $tmp = processInputVar('listids', ARG_STRING); $tmp = explode(',', $tmp); $groupids = array(); foreach($tmp as $id) { if(! is_numeric($id)) continue; if(! array_key_exists($id, $groups[$this->restype])) { $arr = array('status' => 'noaccess'); sendJSON($arr); return; } $groupids[] = $id; } $args = $this->defaultGetDataArgs; if(is_null($newids)) $args['rscid'] = $rscid; $resdata = $this->getData($args); $mode = getContinuationVar('mode'); if($mode == 'add') { $adds = array(); if(is_null($newids)) { foreach($groupids as $id) $adds[] = "({$resdata[$rscid]['resourceid']}, $id)"; } else { foreach($newids as $newrscid) { foreach($groupids as $id) $adds[] = "({$resdata[$newrscid]['resourceid']}, $id)"; } } $query = "INSERT IGNORE INTO resourcegroupmembers " . "(resourceid, resourcegroupid) VALUES "; $query .= implode(',', $adds); doQuery($query); } else { $rems = implode(',', $groupids); if(is_null($newids)) $query = "DELETE FROM resourcegroupmembers " . "WHERE resourceid = {$resdata[$rscid]['resourceid']} AND " . "resourcegroupid IN ($rems)"; else { $allrscids = array(); foreach($newids as $newrscid) $allrscids[] = $resdata[$newrscid]['resourceid']; $allrscids = implode(',', $allrscids); $query = "DELETE FROM resourcegroupmembers " . "WHERE resourceid IN ($allrscids) AND " . "resourcegroupid IN ($rems)"; } doQuery($query); } $_SESSION['userresources'] = array(); $regids = "^" . implode('$|^', $groupids) . "$"; $arr = array('status' => 'success', 'regids' => $regids, 'inselobj' => 'ingroups', 'outselobj' => 'outgroups'); sendJSON($arr); } } ?>