You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@vcl.apache.org by jf...@apache.org on 2010/08/30 21:39:31 UTC
svn commit: r990918 - in /incubator/vcl/trunk/web: ./ .ht-inc/
.ht-inc/maintenance/ css/ js/
Author: jfthomps
Date: Mon Aug 30 19:39:30 2010
New Revision: 990918
URL: http://svn.apache.org/viewvc?rev=990918&view=rev
Log:
VCL-208
Ability to easily put the VCL site into a maintenance state
xmlrpcWrappers.php: modified XMLRPCextendRequest and XMLRPCsetRequestEnding - added check for isAvailable returning -2; if so, return errorcode 46: requested time is during a maintenance window
utils.php:
-modified initGlobals - added case statement for including sitemaintenance.php
-added maintenanceCheck - prints notice about site being down for maintenance if during maintenance window
-added maintenanceNotice - prints notice about upcoming maintenance window
-modified isAvailable - calls schCheckMaintenance to see if request conflicts with scheduled maintenance window; return -2 if it does
-added schCheckMaintenance - checks for time window conflicting with a maintenance window
-added numdatetimeToDatetime
-modified getTimeSlots - create entries for maintenance windows
-modified showTimeTable - print blocks for maintenance windows
-added checkInMaintenanceForTimeTable
-added getMaintItems
-added getMaintItemsForTimeTable
-modified printHTMLHeader - added call to maintenanceNotice
-modified getNavMenu - added entry for Site Maintenance to show up for ADMIN_DEVELOPER users
-modified getExtraCSS - return empty array if no matched modes (removes a php warning message)
-modified getDojoHTML - added includes and header stuff for siteMaintenance mode
states.php: added siteMaintenance, AJcreateSiteMaintenance, AJgetSiteMaintenanceData, AJgetDelSiteMaintenanceData, AJeditSiteMaintenance, and AJDeleteSiteMaintenance
conf-default.php: added DEFAULTTHEME - this is the theme that will be used when the site is placed in maintenance if $_COOKIE['VCLSKIN'] is not set
requests.php: modified AJupdateWaitTime and submitEditRequest - added check for isAvailable returning -2 and if so, display message about not being able to schedule due to scheduled downtime
sitemaintenance.php: initial add
maintenance: added directory for placing maintenance files
testsetup.php: added section to test write access to maintenance directory
index.php: added call to maintenanceCheck before calling dbConnect
css/vcl.css: added #maintenancenotice - this is the div that shows up notifying users of an upcoming maintenance window
js/sitemaintenance.js - initial add
Added:
incubator/vcl/trunk/web/.ht-inc/maintenance/
incubator/vcl/trunk/web/.ht-inc/sitemaintenance.php
incubator/vcl/trunk/web/js/sitemaintenance.js
Modified:
incubator/vcl/trunk/web/.ht-inc/conf-default.php
incubator/vcl/trunk/web/.ht-inc/requests.php
incubator/vcl/trunk/web/.ht-inc/states.php
incubator/vcl/trunk/web/.ht-inc/utils.php
incubator/vcl/trunk/web/.ht-inc/xmlrpcWrappers.php
incubator/vcl/trunk/web/css/vcl.css
incubator/vcl/trunk/web/index.php
incubator/vcl/trunk/web/testsetup.php
Modified: incubator/vcl/trunk/web/.ht-inc/conf-default.php
URL: http://svn.apache.org/viewvc/incubator/vcl/trunk/web/.ht-inc/conf-default.php?rev=990918&r1=990917&r2=990918&view=diff
==============================================================================
--- incubator/vcl/trunk/web/.ht-inc/conf-default.php (original)
+++ incubator/vcl/trunk/web/.ht-inc/conf-default.php Mon Aug 30 19:39:30 2010
@@ -81,6 +81,8 @@ define("USEFILTERINGSELECT", 1); // set
// the filteringselect can be a little slow for a large number of items
define("FILTERINGSELECTTHRESHOLD", 300); // if USEFILTERINGSELECT = 1, only use them for selects up to this size
+define("DEFAULTTHEME", 'default'); // this is the theme that will be used when the site is placed in maintenance if $_COOKIE['VCLSKIN'] is not set
+
$ENABLE_ITECSAUTH = 0; // use ITECS accounts (also called "Non-NCSU" accounts)
$userlookupUsers = array(1, # admin
Modified: incubator/vcl/trunk/web/.ht-inc/requests.php
URL: http://svn.apache.org/viewvc/incubator/vcl/trunk/web/.ht-inc/requests.php?rev=990918&r1=990917&r2=990918&view=diff
==============================================================================
--- incubator/vcl/trunk/web/.ht-inc/requests.php (original)
+++ incubator/vcl/trunk/web/.ht-inc/requests.php Mon Aug 30 19:39:30 2010
@@ -251,6 +251,10 @@ function AJupdateWaitTime() {
$rc = isAvailable($images, $imageid, $start, $end, '');
semUnlock();
print "dojo.byId('waittime').innerHTML = ";
+ if($rc == -2) {
+ print "'<font color=red>Selection not currently available due to scheduled system downtime for maintenance</font>'; ";
+ print "if(dojo.byId('newsubmit')) dojo.byId('newsubmit').value = 'View Time Table';";
+ }
if($rc < 1) {
print "'<font color=red>Selection not currently available</font>'; ";
print "if(dojo.byId('newsubmit')) dojo.byId('newsubmit').value = 'View Time Table';";
@@ -1840,8 +1844,13 @@ function submitEditRequest() {
'length' => $data['length'],
'requestid' => $data['requestid']);
$cont = addContinuationsEntry('selectTimeTable', $cdata);
- print "The time you have requested is not available. You may ";
- print "<a href=\"" . BASEURL . SCRIPT . "?continuation=$cont\">";
+ if($rc == -2) {
+ print "The time you have requested is not available due to scheduled ";
+ print "system downtime for maintenance. ";
+ }
+ else
+ print "The time you have requested is not available. ";
+ print "You may <a href=\"" . BASEURL . SCRIPT . "?continuation=$cont\">";
print "view a timetable</a> of free and reserved times to find ";
print "a time that will work for you.<br>\n";
addChangeLogEntry($request["logid"], NULL, unixToDatetime($end),
Added: incubator/vcl/trunk/web/.ht-inc/sitemaintenance.php
URL: http://svn.apache.org/viewvc/incubator/vcl/trunk/web/.ht-inc/sitemaintenance.php?rev=990918&view=auto
==============================================================================
--- incubator/vcl/trunk/web/.ht-inc/sitemaintenance.php (added)
+++ incubator/vcl/trunk/web/.ht-inc/sitemaintenance.php Mon Aug 30 19:39:30 2010
@@ -0,0 +1,582 @@
+<?php
+/*
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * \file
+ */
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \fn siteMaintenance()
+///
+/// \brief prints a page for managing site maintenance
+///
+////////////////////////////////////////////////////////////////////////////////
+function siteMaintenance() {
+ $update = getContinuationVar('update', 0);
+ $items = getMaintItems();
+
+ $rt = '';
+ if(! $update) {
+ $rt .= "<h2>Site Maintenance</h2>\n";
+ $rt .= "<div id=\"maintenancediv\">\n";
+ }
+ $rt .= "<button dojoType=\"dijit.form.Button\" type=\"button\">\n";
+ $rt .= " Schedule Site Maintenance\n";
+ $rt .= " <script type=\"dojo/method\" event=\"onClick\">\n";
+ $cont = addContinuationsEntry('AJcreateSiteMaintenance', array('update' => 1));
+ $rt .= " showAddSiteMaintenance('$cont');\n";
+ $rt .= " </script>\n";
+ $rt .= "</button><br>\n";
+ if(count($items)) {
+ $rt .= "<table>\n";
+ $rt .= "<tr>\n";
+ $rt .= "<td colspan=2></td>\n";
+ $rt .= "<th style=\"vertical-align: bottom;\">Start</th>\n";
+ $rt .= "<th style=\"vertical-align: bottom;\">End</th>\n";
+ $rt .= "<th style=\"vertical-align: bottom;\">Owner</th>\n";
+ $rt .= "<th style=\"vertical-align: bottom;\">Created</th>\n";
+ $rt .= "<th style=\"vertical-align: bottom;\">Reason <small>(hover for more)</small></th>\n";
+ $rt .= "<th style=\"vertical-align: bottom;\">User Message <small>(hover for more)</small></th>\n";
+ $rt .= "<th style=\"vertical-align: bottom;\">Inform Hours Ahead</th>\n";
+ $rt .= "<th style=\"vertical-align: bottom;\">Allow Reservations</th>\n";
+ $rt .= "</tr>\n";
+ foreach($items as $item) {
+ $tmp = datetimeToUnix($item['start']);
+ $start = date('g:i&\n\b\s\p;A n/j/Y', $tmp);
+ $tmp = datetimeToUnix($item['end']);
+ $end = date('g:i&\n\b\s\p;A n/j/Y', $tmp);
+ $tmp = datetimeToUnix($item['created']);
+ $created = date('g:i&\n\b\s\p;A n/j/Y', $tmp);
+ $rt .= "<tr>\n";
+ $rt .= "<td>\n";
+ $rt .= "<button dojoType=\"dijit.form.Button\" type=\"button\">\n";
+ $rt .= " Edit\n";
+ $rt .= " <script type=\"dojo/method\" event=\"onClick\">\n";
+ $data = array('id' => $item['id']);
+ $cont = addContinuationsEntry('AJgetSiteMaintenanceData', $data);
+ $rt .= " showEditSiteMaintenance('$cont');\n";
+ $rt .= " </script>\n";
+ $rt .= "</button>\n";
+ $rt .= "</td>\n";
+ $rt .= "<td>\n";
+ $rt .= "<button dojoType=\"dijit.form.Button\" type=\"button\">\n";
+ $rt .= " Delete\n";
+ $rt .= " <script type=\"dojo/method\" event=\"onClick\">\n";
+ $cont = addContinuationsEntry('AJgetDelSiteMaintenanceData', $data);
+ $rt .= " confirmDeleteSiteMaintenance('$cont');\n";
+ $rt .= " </script>\n";
+ $rt .= "</button>\n";
+ $rt .= "</td>\n";
+ $rt .= "<td align=center>$start</td>\n";
+ $rt .= "<td align=center>$end</td>\n";
+ $rt .= "<td align=center>{$item['owner']}</td>\n";
+ $rt .= "<td align=center>$created</td>\n";
+ if(strlen($item['reason']) < 30)
+ $rt .= "<td align=center>{$item['reason']}</td>\n";
+ else {
+ $rt .= "<td align=center>\n";
+ $reason = substr($item['reason'], 0, 30) . '...';
+ $rt .= " <span id=\"morereason\">$reason</span>\n";
+ $rt .= " <div dojoType=\"dijit.Tooltip\" connectId=\"morereason\">\n";
+ $reason = preg_replace('/(.{1,50}[ \n])/', '\1<br>', $item['reason']);
+ $reason = preg_replace('/\n<br>\n/', "<br><br>\n", $reason);
+ $rt .= "$reason</div>\n";
+ $rt .= "</td>\n";
+ }
+ if(strlen($item['usermessage']) < 30)
+ $rt .= "<td align=center>{$item['usermessage']}</td>\n";
+ else {
+ $rt .= "<td align=center>\n";
+ $msg = substr($item['usermessage'], 0, 30) . '...';
+ $rt .= " <span id=\"moreusermsg\">$msg</span>\n";
+ $rt .= " <div dojoType=\"dijit.Tooltip\" connectId=\"moreusermsg\">\n";
+ $msg = preg_replace('/(.{1,50}[ \n])/', '\1<br>', $item['usermessage']);
+ $msg = preg_replace('/\n<br>\n/', "<br><br>\n", $msg);
+ $rt .= "$msg</div>\n";
+ $rt .= "</td>\n";
+ }
+ $hours = $item['informhoursahead'] % 24;
+ if($hours == 1)
+ $hours = (int)($item['informhoursahead'] / 24) . " days, 1 hour";
+ else
+ $hours = (int)($item['informhoursahead'] / 24) . " days, $hours hours";
+ $rt .= "<td align=center>$hours</td>\n";
+ if($item['allowreservations'])
+ $rt .= "<td align=center>Yes</td>\n";
+ else
+ $rt .= "<td align=center>No</td>\n";
+ $rt .= "</tr>\n";
+ }
+ $rt .= "</table>\n";
+ }
+ if($update) {
+ $send = str_replace("\n", '', $rt);
+ $send = str_replace("'", "\'", $send);
+ $send = preg_replace("/>\s*</", "><", $send);
+ print setAttribute('maintenancediv', 'innerHTML', $send);
+ print "AJdojoCreate('maintenancediv');";
+ return;
+ }
+ print $rt;
+ print "</div>\n"; # end maintenancediv
+
+ print "<div id=\"editDialog\" dojoType=\"dijit.Dialog\" autofocus=\"false\">\n";
+ print "<h2><span id=\"editheader\"></span></h2>\n";
+ print "<span id=\"edittext\"></span><br><br>\n";
+ print "<table summary=\"\">\n";
+ print " <tr>\n";
+ print " <th align=\"right\">Start:</th>\n";
+ print " <td>\n";
+ print " <div type=\"text\" id=\"starttime\" dojoType=\"dijit.form.TimeTextBox\" ";
+ print "required=\"true\" style=\"width: 80px\"></div>\n";
+ print " <div type=\"text\" id=\"startdate\" dojoType=\"dijit.form.DateTextBox\" ";
+ print "required=\"true\" style=\"width: 100px\"></div>\n";
+ print " </td>\n";
+ print " </tr>\n";
+ print " <tr>\n";
+ print " <th align=\"right\">End:</th>\n";
+ print " <td>\n";
+ print " <div type=\"text\" id=\"endtime\" dojoType=\"dijit.form.TimeTextBox\" ";
+ print "required=\"true\" style=\"width: 80px\"></div>\n";
+ print " <div type=\"text\" id=\"enddate\" dojoType=\"dijit.form.DateTextBox\" ";
+ print "required=\"true\" style=\"width: 100px\"></div>\n";
+ print " </td>\n";
+ print " </tr>\n";
+ print " <tr valign=\"top\">\n";
+ print " <th align=\"right\">Inform Hours Ahead:</th>\n";
+ print " <td>\n";
+ print " <input dojoType=\"dijit.form.NumberSpinner\"\n";
+ print " constraints=\"{min:1,max:65535}\"\n";
+ print " maxlength=\"3\"\n";
+ print " id=\"hoursahead\"\n";
+ print " format=\"updateDaysHours\"\n";
+ print " required=\"true\"\n";
+ print " style=\"width: 70px\">\n";
+ print " <span id=dayshours></span>\n";
+ print " </td>\n";
+ print " </tr>\n";
+ print " <tr valign=\"top\">\n";
+ print " <th align=\"right\">Allow Reservations:</th>\n";
+ print " <td>\n";
+ print " <select id=allowreservations dojoType=\"dijit.form.Select\">";
+ print " <option value=\"1\">Yes</option>\n";
+ print " <option value=\"0\">No</option>\n";
+ print " </select>\n";
+ print " </td>\n";
+ print " </tr>\n";
+ print "</table>\n";
+ print "<b>Reason</b> (this is not displayed to any users and is just for your records):<br>\n";
+ print "<textarea id=\"reason\" dojoType=\"dijit.form.Textarea\" style=\"width: 400px;\">\n";
+ print "</textarea><br>\n";
+ print "<b>User Message</b> (this will be displayed on the site during the maintenance window):<br>\n";
+ print "<textarea id=\"usermessage\" dojoType=\"dijit.form.Textarea\" style=\"width: 400px;\">\n";
+ print "</textarea>\n";
+ print "<input type=\"hidden\" id=\"submitcont\">\n";
+ print "<div align=\"center\">\n";
+ print "<button dojoType=\"dijit.form.Button\" type=\"button\" id=\"editsubmitbtn\">\n";
+ print " Save Changes\n";
+ print " <script type=\"dojo/method\" event=\"onClick\">\n";
+ print " editSubmit();\n";
+ print " </script>\n";
+ print "</button>\n";
+ print "<button dojoType=\"dijit.form.Button\" type=\"button\">\n";
+ print " Cancel\n";
+ print " <script type=\"dojo/method\" event=\"onClick\">\n";
+ print " clearEdit();\n";
+ print " </script>\n";
+ print "</button>\n";
+ print "</div>\n";
+ print "</div>\n"; # edit dialog
+
+ print "<div id=\"confirmDialog\" dojoType=\"dijit.Dialog\" title=\"Delete Site Maintenance\">\n";
+ print "<h2>Delete Site Maintenance</h2>\n";
+ print "Click <b>Delete Entry</b> to delete this site maintenance entry<br><br>\n";
+ print "<table summary=\"\">\n";
+ print " <tr>\n";
+ print " <th align=\"right\">Start:</th>\n";
+ print " <td><span id=\"start\"></span></td>\n";
+ print " </tr>\n";
+ print " <tr>\n";
+ print " <th align=\"right\">End:</th>\n";
+ print " <td><span id=\"end\"></span></td>\n";
+ print " </tr>\n";
+ print " <tr>\n";
+ print " <th align=\"right\">Owner:</th>\n";
+ print " <td><span id=\"owner\"></span></td>\n";
+ print " </tr>\n";
+ print " <tr>\n";
+ print " <th align=\"right\">Created:</th>\n";
+ print " <td><span id=\"created\"></span></td>\n";
+ print " </tr>\n";
+ print " <tr valign=\"top\">\n";
+ print " <th align=\"right\">Inform Hours Ahead:</th>\n";
+ print " <td><span id=\"informhoursahead\"></span></td>\n";
+ print " </tr>\n";
+ print " <tr valign=\"top\">\n";
+ print " <th align=\"right\">Allow Reservations:</th>\n";
+ print " <td><span id=\"delallowreservations\"></span></td>\n";
+ print " </tr>\n";
+ print " <tr valign=top>\n";
+ print " <th align=\"right\">Reason:</th>\n";
+ print " <td><span id=\"delreason\"></span></td>\n";
+ print " </tr>\n";
+ print " <tr valign=top>\n";
+ print " <th align=\"right\">User Message:</th>\n";
+ print " <td><span id=\"delusermessage\"></span></td>\n";
+ print " </tr>\n";
+ print "</table>\n";
+ print "<input type=\"hidden\" id=\"delsubmitcont\">\n";
+ print "<div align=\"center\">\n";
+ print "<button dojoType=\"dijit.form.Button\" type=\"button\">\n";
+ print " Delete Entry\n";
+ print " <script type=\"dojo/method\" event=\"onClick\">\n";
+ print " deleteSiteMaintenance();\n";
+ print " </script>\n";
+ print "</button>\n";
+ print "<button dojoType=\"dijit.form.Button\" type=\"button\">\n";
+ print " Cancel\n";
+ print " <script type=\"dojo/method\" event=\"onClick\">\n";
+ print " dijit.byId('confirmDialog').hide();\n";
+ print " </script>\n";
+ print "</button>\n";
+ print "</div>\n";
+ print "</div>\n"; # confirm dialog
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \fn AJcreateSiteMaintenance()
+///
+/// \brief creates an file in the maintenance directory, creates an entry in
+/// the sitemaintenance table and does a javascript page reload
+///
+////////////////////////////////////////////////////////////////////////////////
+function AJcreateSiteMaintenance() {
+ global $user;
+ $data = processSiteMaintenanceInput();
+ if($data['err'])
+ return;
+
+ if(! writeMaintenanceFile($data['startts'], $data['endts'], $data['usermessage'])) {
+ print "alert('Failed to create maintenance file on web server.\\n";
+ print "Please have sysadmin check permissions on maintenance directory.');\n";
+ return;
+ }
+
+ $reason = mysql_real_escape_string($data['reason']);
+ $usermessage = mysql_real_escape_string($data['usermessage']);
+ $query = "INSERT INTO sitemaintenance "
+ . "(start, "
+ . "end, "
+ . "ownerid, "
+ . "created, "
+ . "reason, "
+ . "usermessage, "
+ . "informhoursahead, "
+ . "allowreservations) "
+ . "VALUES "
+ . "('{$data['startdt']}', "
+ . "'{$data['enddt']}', "
+ . "{$user['id']}, "
+ . "NOW(), "
+ . "'$reason', "
+ . "'$usermessage', "
+ . "{$data['hoursahead']}, "
+ . "{$data['allowreservations']})";
+ doQuery($query, 101);
+ $_SESSION['usersessiondata'] = array();
+ print "window.location.href = '" . BASEURL . SCRIPT . "?mode=siteMaintenance';";
+ #print "clearEdit();";
+ #siteMaintenance();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \fn AJgetSiteMaintenanceData()
+///
+/// \brief gets info about a sitemaintenance entry and returns it in JSON format
+///
+////////////////////////////////////////////////////////////////////////////////
+function AJgetSiteMaintenanceData() {
+ $id = getContinuationVar('id');
+ $tmp = getMaintItems($id);
+ $data = $tmp[$id];
+ $start = datetimeToUnix($data['start']) * 1000;
+ $end = datetimeToUnix($data['end']) * 1000;
+ $cdata = array('id' => $id,
+ 'update' => 1);
+ $cont = addContinuationsEntry('AJeditSiteMaintenance', $cdata,
+ SECINDAY, 1, 0);
+ $arr = array('start' => $start,
+ 'end' => $end,
+ 'hoursahead' => $data['informhoursahead'],
+ 'allowreservations' => $data['allowreservations'],
+ 'reason' => $data['reason'],
+ 'usermessage' => $data['usermessage'],
+ 'cont' => $cont);
+ sendJSON($arr);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \fn AJgetDelSiteMaintenanceData()
+///
+/// \brief gets info about a sitemaintenance entry to be displayed on the
+/// confirm delete dialog and returns it in JSON format
+///
+////////////////////////////////////////////////////////////////////////////////
+function AJgetDelSiteMaintenanceData() {
+ $id = getContinuationVar('id');
+ $tmp = getMaintItems($id);
+ $data = $tmp[$id];
+ $cdata = array('id' => $id,
+ 'update' => 1,
+ 'start' => datetimeToUnix($data['start']));
+ $cont = addContinuationsEntry('AJdeleteSiteMaintenance', $cdata,
+ SECINDAY, 1, 0);
+ $tmp = datetimeToUnix($data['start']);
+ $start = date('g:i A, n/j/Y', $tmp);
+ $tmp = datetimeToUnix($data['end']);
+ $end = date('g:i A, n/j/Y', $tmp);
+ $tmp = datetimeToUnix($data['created']);
+ $created = date('g:i A, n/j/Y', $tmp);
+ $hours = $data['informhoursahead'] % 24;
+ if($hours == 1)
+ $hours = (int)($data['informhoursahead'] / 24) . " days, 1 hour";
+ else
+ $hours = (int)($data['informhoursahead'] / 24) . " days, $hours hours";
+ $hours = "{$data['informhoursahead']} ($hours)";
+ if($data['allowreservations'])
+ $allowres = 'Yes';
+ else
+ $allowres = 'No';
+ $reason = preg_replace('/(.{1,50}[ \n])/', '\1<br>', $data['reason']);
+ $reason = preg_replace('/\n<br>\n/', "<br><br>\n", $reason);
+ $usermsg = preg_replace('/(.{1,50}[ \n])/', '\1<br>', $data['usermessage']);
+ $usermsg = preg_replace('/\n<br>\n/', "<br><br>\n", $usermsg);
+ $arr = array('start' => $start,
+ 'end' => $end,
+ 'owner' => $data['owner'],
+ 'created' => $created,
+ 'hoursahead' => $hours,
+ 'allowreservations' => $allowres,
+ 'reason' => $reason,
+ 'usermessage' => $usermsg,
+ 'cont' => $cont);
+ sendJSON($arr);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \fn AJeditSiteMaintenance()
+///
+/// \brief removes/adds file in maintenances directory and updates entry in
+/// sitemaintenance table
+///
+////////////////////////////////////////////////////////////////////////////////
+function AJeditSiteMaintenance() {
+ global $user;
+ $id = getContinuationVar('id');
+ $data = processSiteMaintenanceInput();
+
+ $olddata = getMaintItems($id);
+ $start = datetimeToUnix($olddata[$id]['start']);
+ if(! deleteMaintenanceFile($start) ||
+ ! writeMaintenanceFile($data['startts'], $data['endts'], $data['usermessage'])) {
+ print "alert('Failed to modify maintenance file on web server.\\n";
+ print "Please have sysadmin check permissions on maintenance directory.');\n";
+ print "dijit.byId('confirmDialog').hide();";
+ $data['err'] = 1;
+ }
+ if($data['err']) {
+ $data = array('id' => $id,
+ 'update' => 1);
+ $cont = addContinuationsEntry('AJeditSiteMaintenance', $data,
+ SECINDAY, 1, 0);
+ print "dojo.byId('submitcont').value = '$cont';";
+ return;
+ }
+
+ $reason = mysql_real_escape_string($data['reason']);
+ $usermessage = mysql_real_escape_string($data['usermessage']);
+ $query = "UPDATE sitemaintenance "
+ . "SET start = '{$data['startdt']}', "
+ . "end = '{$data['enddt']}', "
+ . "ownerid = {$user['id']}, "
+ . "created = NOW(), "
+ . "reason = '$reason', "
+ . "usermessage = '$usermessage', "
+ . "informhoursahead = {$data['hoursahead']}, "
+ . "allowreservations = {$data['allowreservations']} "
+ . "WHERE id = $id";
+ doQuery($query, 101);
+ $_SESSION['usersessiondata'] = array();
+ print "window.location.href = '" . BASEURL . SCRIPT . "?mode=siteMaintenance';";
+ #print "clearEdit();";
+ #siteMaintenance();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \fn processSiteMaintenanceInput()
+///
+/// \return array with these keys:\n
+/// \b hoursahead - corresponds to sitemaintenance table\n
+/// \b allowreservations - corresponds to sitemaintenance table\n
+/// \b reason - corresponds to sitemaintenance table\n
+/// \b usermessage - corresponds to sitemaintenance table\n
+/// \b startdt - datetime format for start of maintenance\n
+/// \b startts - unix timestamp format for start of maintenance\n
+/// \b enddt - datetime format for end of maintenance\n
+/// \b endts - unix timestamp format for end of maintenance\n
+/// \b err - whether or not an entry was found to be invalid
+///
+/// \brief validates form data for site maintenance items
+///
+////////////////////////////////////////////////////////////////////////////////
+function processSiteMaintenanceInput() {
+ $start = processInputVar('start', ARG_NUMERIC);
+ $end = processInputVar('end', ARG_NUMERIC);
+ $data['hoursahead'] = processInputVar('hoursahead', ARG_NUMERIC);
+ $data['allowreservations'] = processInputVar('allowreservations', ARG_NUMERIC);
+ $data['reason'] = processInputVar('reason', ARG_STRING);
+ $data['usermessage'] = processInputVar('usermessage', ARG_STRING);
+
+ $err = 0;
+
+ $now = time();
+ $data['startdt'] = numdatetimeToDatetime($start . '00');
+ $data['startts'] = datetimeToUnix($data['startdt']);
+ $data['enddt'] = numdatetimeToDatetime($end . '00');
+ $data['endts'] = datetimeToUnix($data['enddt']);
+
+ $reg = "/^[-0-9a-zA-Z\.,\?:;_@!#\(\)\n ]+$/";
+ if(! preg_match($reg, $data['reason'])) {
+ $errmsg = "Reason can only contain letters, numbers, spaces,\\nand these characters: . , ? : ; - _ @ ! # ( )";
+ $err = 1;
+ }
+ if(! preg_match($reg, $data['usermessage'])) {
+ $errmsg = "User Message can only contain letters, numbers, spaces,\\nand these characters: . , ? : ; - _ @ ! # ( )";
+ $err = 1;
+ }
+ if(! $err && $data['startts'] < $now) {
+ $errmsg = 'The start time and date must be later than the current time.';
+ $err = 1;
+ }
+ if(! $err && $data['endts'] <= $data['startts']) {
+ $errmsg = 'The end time and date must be later than the start time and date.';
+ $err = 1;
+ }
+ if(! $err && $data['hoursahead'] < 1) {
+ $errmsg = 'Inform Hours Ahead must be at least 1.';
+ $err = 1;
+ }
+ if(! $err && $data['hoursahead'] > 65535) {
+ $errmsg = 'Inform Hours Ahead must be less than 65536.';
+ $err = 1;
+ }
+ if(! $err && ($data['allowreservations'] != 0 && $data['allowreservations'] != 1))
+ $data['allowreservations'] = 0;
+ if(! $err && ! preg_match('/[A-Za-z]{2,}/', $data['usermessage'])) {
+ $errmsg = 'Something must be filled in for the User Message.';
+ $err = 1;
+ }
+ if($err)
+ print "alert('$errmsg');";
+ $data['err'] = $err;
+ return $data;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \fn AJdeleteSiteMaintenance()
+///
+/// \brief removes file from maintenance directory and deletes entry from
+/// sitemaintenance table
+///
+////////////////////////////////////////////////////////////////////////////////
+function AJdeleteSiteMaintenance() {
+ $id = getContinuationVar('id');
+ $start = getContinuationVar('start');
+ if(! deleteMaintenanceFile($start)) {
+ print "alert('Failed to delete maintenance file on web server.\\n";
+ print "Please have sysadmin check permissions on maintenance directory.');\n";
+ print "dijit.byId('confirmDialog').hide();";
+ return;
+ }
+ $query = "DELETE FROM sitemaintenance WHERE id = $id";
+ doQuery($query, 101);
+ $_SESSION['usersessiondata'] = array();
+ print "window.location.href = '" . BASEURL . SCRIPT . "?mode=siteMaintenance';";
+ #print "dijit.byId('confirmDialog').hide();";
+ #siteMaintenance();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \fn writeMaintenanceFile($start, $end, $msg)
+///
+/// \param $start - start time of maintenance entry in unix timestamp format
+/// \param $end - end time of maintenance entry in unix timestamp format
+/// \param $msg - user message for maintenance entry
+///
+/// \return true if file created; false if not
+///
+/// \brief creates a file in the maintenance directory
+///
+////////////////////////////////////////////////////////////////////////////////
+function writeMaintenanceFile($start, $end, $msg) {
+ $name = date('YmdHi', $start);
+ $reg = "|" . SCRIPT . "$|";
+ $file = preg_replace($reg, '', $_SERVER['SCRIPT_FILENAME']);
+ $file .= "/.ht-inc/maintenance/$name";
+ if(! $fh = fopen($file, 'w')) {
+ return false;
+ }
+ $numend = date('YmdHi', $end);
+ fwrite($fh, "END=$numend\n");
+ fwrite($fh, "$msg\n");
+ fclose($fh);
+ return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \fn deleteMaintenanceFile($start)
+///
+/// \param $start - start time of maintenance entry in unix timestamp format
+///
+/// \return true if file deleted; false if not
+///
+/// \brief removes a file from the maintenance directory
+///
+////////////////////////////////////////////////////////////////////////////////
+function deleteMaintenanceFile($start) {
+ $name = date('YmdHi', $start);
+ $reg = "|" . SCRIPT . "$|";
+ $file = preg_replace($reg, '', $_SERVER['SCRIPT_FILENAME']);
+ $file .= "/.ht-inc/maintenance/$name";
+ if(! file_exists($file))
+ return true;
+ if(! @unlink($file))
+ return false;
+ return true;
+}
+
+?>
Modified: incubator/vcl/trunk/web/.ht-inc/states.php
URL: http://svn.apache.org/viewvc/incubator/vcl/trunk/web/.ht-inc/states.php?rev=990918&r1=990917&r2=990918&view=diff
==============================================================================
--- incubator/vcl/trunk/web/.ht-inc/states.php (original)
+++ incubator/vcl/trunk/web/.ht-inc/states.php Mon Aug 30 19:39:30 2010
@@ -54,6 +54,7 @@ $actions["entry"] = array('main',
'editVMInfo',
'continuationsError',
'requestBlockAllocation',
+ 'siteMaintenance',
);
$noHTMLwrappers = array('sendRDPfile',
@@ -133,6 +134,11 @@ $noHTMLwrappers = array('sendRDPfile',
'AJviewBlockAllocation',
'AJviewBlockAllocationTimes',
'AJtoggleBlockTime',
+ 'AJcreateSiteMaintenance',
+ 'AJgetSiteMaintenanceData',
+ 'AJgetDelSiteMaintenanceData',
+ 'AJeditSiteMaintenance',
+ 'AJdeleteSiteMaintenance',
);
# main
@@ -608,6 +614,20 @@ $actions['pages']['AJupdateVMprofileItem
$actions['pages']['AJnewProfile'] = "vm";
$actions['pages']['AJdelProfile'] = "vm";
+# site maintenance
+$actions['mode']['siteMaintenance'] = "siteMaintenance";
+$actions['mode']['AJcreateSiteMaintenance'] = "AJcreateSiteMaintenance";
+$actions['mode']['AJgetSiteMaintenanceData'] = "AJgetSiteMaintenanceData";
+$actions['mode']['AJgetDelSiteMaintenanceData'] = "AJgetDelSiteMaintenanceData";
+$actions['mode']['AJeditSiteMaintenance'] = "AJeditSiteMaintenance";
+$actions['mode']['AJdeleteSiteMaintenance'] = "AJdeleteSiteMaintenance";
+$actions['pages']['siteMaintenance'] = "sitemaintenance";
+$actions['pages']['AJcreateSiteMaintenance'] = "sitemaintenance";
+$actions['pages']['AJgetSiteMaintenanceData'] = "sitemaintenance";
+$actions['pages']['AJgetDelSiteMaintenanceData'] = "sitemaintenance";
+$actions['pages']['AJeditSiteMaintenance'] = "sitemaintenance";
+$actions['pages']['AJdeleteSiteMaintenance'] = "sitemaintenance";
+
# RPC
$actions['mode']['xmlrpccall'] = "xmlrpccall";
$actions['mode']['xmlrpcaffiliations'] = "xmlrpcgetaffiliations";
Modified: incubator/vcl/trunk/web/.ht-inc/utils.php
URL: http://svn.apache.org/viewvc/incubator/vcl/trunk/web/.ht-inc/utils.php?rev=990918&r1=990917&r2=990918&view=diff
==============================================================================
--- incubator/vcl/trunk/web/.ht-inc/utils.php (original)
+++ incubator/vcl/trunk/web/.ht-inc/utils.php Mon Aug 30 19:39:30 2010
@@ -301,6 +301,9 @@ function initGlobals() {
case 'userLookup':
require_once(".ht-inc/privileges.php");
break;
+ case 'sitemaintenance':
+ require_once(".ht-inc/sitemaintenance.php");
+ break;
case 'vm':
require_once(".ht-inc/vm.php");
break;
@@ -545,6 +548,124 @@ function checkAccess() {
////////////////////////////////////////////////////////////////////////////////
///
+/// \fn maintenanceCheck()
+///
+/// \brief checks for site being in maintenance; if so, read user message from
+/// current maintenance file; print site header, maintenance message, and site
+/// foother; then exit; also removes any old maintenance files
+///
+////////////////////////////////////////////////////////////////////////////////
+function maintenanceCheck() {
+ global $authed, $mode, $user;
+ $now = time();
+ $reg = "|" . SCRIPT . "$|";
+ $search = preg_replace($reg, '', $_SERVER['SCRIPT_FILENAME']);
+ $search .= "/.ht-inc/maintenance/";
+ $files = glob("$search*");
+ $inmaintenance = 0;
+ foreach($files as $file) {
+ if(! preg_match("|^$search([0-9]{4})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})$|", $file, $matches))
+ continue;
+ #YYYYMMDDHHMM
+ $tmp = "{$matches[1]}-{$matches[2]}-{$matches[3]} {$matches[4]}:{$matches[5]}:00";
+ $start = datetimeToUnix($tmp);
+ if($start < $now) {
+ # check to see if end time has been reached
+ $fh = fopen($file, 'r');
+ $msg = '';
+ while($line = fgetss($fh)) {
+ if(preg_match("/^END=([0-9]{4})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})$/", $line, $matches)) {
+ $tmp = "{$matches[1]}-{$matches[2]}-{$matches[3]} {$matches[4]}:{$matches[5]}:00";
+ $end = datetimeToUnix($tmp);
+ if($end < $now) {
+ fclose($fh);
+ unlink($file);
+ $_SESSION['usersessiondata'] = array();
+ return;
+ }
+ else
+ $inmaintenance = 1;
+ }
+ else
+ $msg .= $line;
+ }
+ fclose($fh);
+ if($inmaintenance)
+ break;
+ }
+ }
+ if($inmaintenance) {
+ $authed = 0;
+ $mode = 'inmaintenance';
+ $user = array();
+ if(array_key_exists('VCLSKIN', $_COOKIE))
+ $skin = strtolower($_COOKIE['VCLSKIN']);
+ else
+ $skin = DEFAULTTHEME;
+ require_once("themes/$skin/page.php");
+ printHTMLHeader();
+ print "<h2>Site Currently Under Maintenance</h2>\n";
+ if(! empty($msg)) {
+ $msg = htmlentities($msg);
+ $msg = preg_replace("/\n/", "<br>\n", $msg);
+ print "$msg<br>\n";
+ }
+ else
+ print "This site is currently in maintenance.<br>\n";
+ $niceend = date('l, F jS, Y \a\t g:i A', $end);
+ print "The maintenance is scheduled to end <b>$niceend</b>.<br><br><br>\n";
+ printHTMLFooter();
+ exit;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \fn maintenanceNotice()
+///
+/// \brief checks nformhoursahead for upcoming maintenance items and prints
+/// message about upcoming maintenance if currently within warning window
+///
+////////////////////////////////////////////////////////////////////////////////
+function maintenanceNotice() {
+ $items = getMaintItems();
+ foreach($items as $item) {
+ $start = datetimeToUnix($item['start']);
+ $file = date('YmdHi', $start);
+ $secahead = $item['informhoursahead'] * 3600;
+ if($start - $secahead < time()) {
+ $reg = "|" . SCRIPT . "$|";
+ $search = preg_replace($reg, '', $_SERVER['SCRIPT_FILENAME']);
+ $search .= "/.ht-inc/maintenance/$file";
+ $files = glob("$search");
+ if(empty($files)) {
+ $_SESSION['usersessiondata'] = array();
+ return;
+ }
+ $nicestart = date('g:i A \o\n l, F jS, Y', $start);
+ $niceend = date('g:i A \o\n l, F jS, Y', datetimeToUnix($item['end']));
+ print "<div id=\"maintenancenotice\">\n";
+ print "<b>NOTICE</b>: This site will be down for maintenance during ";
+ print "the following times:<br><br>\n";
+ print "Start: $nicestart<br>\n";
+ print "End: $niceend.<br><br>\n";
+ if($item['allowreservations']) {
+ print "You will be able to access your reserved machines during ";
+ print "this maintenance. However, you will not be able to access ";
+ print "information on how to connect to them.<br>\n";
+ }
+ else {
+ print "You will not be able to access any of your reservations ";
+ print "during this maintenance.<br>\n";
+ }
+ print "</div>\n";
+ return;
+ }
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
/// \fn clearPrivCache()
///
/// \brief sets userresources, nodeprivileges, cascadenodeprivileges, and
@@ -3232,6 +3353,9 @@ function isAvailable($images, $imageid,
$requestInfo["imageid"] = $imageid;
$allocatedcompids = array(0);
+ if(schCheckMaintenance($start, $end))
+ return -2;
+
if($requestInfo["start"] <= time()) {
$now = 1;
$nowfuture = 'now';
@@ -3677,6 +3801,33 @@ function RPCisAvailable($imageid, $start
////////////////////////////////////////////////////////////////////////////////
///
+/// \fn schCheckMaintenance($start, $end)
+///
+/// \param $start - unix timestamp for start of reservation
+/// \param $end - unix timestamp for end of reservation
+///
+/// \return true if time window conflicts with maintenance window; false if not
+///
+/// \brief checks to see if the specified window conflicts with a maintenance
+/// window
+///
+////////////////////////////////////////////////////////////////////////////////
+function schCheckMaintenance($start, $end) {
+ $startdt = unixToDatetime($start);
+ $enddt = unixToDatetime($end);
+ $query = "SELECT id "
+ . "FROM sitemaintenance "
+ . "WHERE (allowreservations = 0 AND "
+ . "(('$enddt' > start) AND ('$startdt' < end))) OR "
+ . "(('$startdt' > (start - INTERVAL 30 MINUTE)) AND ('$startdt' < end))";
+ $qh = doQuery($query, 101);
+ if($row = mysql_fetch_row($qh))
+ return true;
+ return false;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
/// \fn allocComputer($blockids, $currentids, $computerids, $start,
/// $nowfuture)
///
@@ -4715,6 +4866,27 @@ function unixToDatetime($timestamp) {
////////////////////////////////////////////////////////////////////////////////
///
+/// \fn numdatetimeToDatetime($numtime)
+///
+/// \param $numtime - date and time in YYYYMMDDHHMMSS format
+///
+/// \return a mysql datetime formatted string (YYYY-MM-DD HH:MM:SS)
+///
+/// \brief converts numeric date and time into datetime format
+///
+////////////////////////////////////////////////////////////////////////////////
+function numdatetimeToDatetime($numtime) {
+ $year = substr($numtime, 0, 4);
+ $month = substr($numtime, 4, 2);
+ $day = substr($numtime, 6, 2);
+ $hour = substr($numtime, 8, 2);
+ $min = substr($numtime, 10, 2);
+ $sec = substr($numtime, 12, 2);
+ return "$year-$month-$day $hour:$min:$sec";
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
/// \fn minuteOfDay($hour, $min)
///
/// \param $hour - hour of the day (0 - 23)
@@ -5313,6 +5485,7 @@ function getTimeSlots($compids, $end=0,
}
$blockData = getBlockTimeData($start, $endtime);
+ $maintItems = getMaintItemsForTimeTable($start, $endtime);
$reserveInfo = array(); // 0 = reserved, 1 = available
foreach($computerids as $id) {
$reserveInfo[$id] = array();
@@ -5330,11 +5503,17 @@ function getTimeSlots($compids, $end=0,
}
print "-----------------------------------------------------<br>\n";*/
$reserveInfo[$id][$current]['blockAllocation'] = 0;
+ $reserveInfo[$id][$current]["inmaintenance"] = 0;
if(scheduleClosed($id, $current, $schedules[$scheduleids[$id]])) {
$reserveInfo[$id][$current]["available"] = 0;
$reserveInfo[$id][$current]["scheduleclosed"] = 1;
continue;
}
+ if(checkInMaintenanceForTimeTable($current, $current + 900, $maintItems)) {
+ $reserveInfo[$id][$current]["available"] = 0;
+ $reserveInfo[$id][$current]["inmaintenance"] = 1;
+ continue;
+ }
if($blockid = isBlockAllocationTime($id, $current, $blockData)) {
$reserveInfo[$id][$current]['blockAllocation'] = 1;
$reserveInfo[$id][$current]['blockInfo']['groupid'] = $blockData[$blockid]['groupid'];
@@ -5672,8 +5851,13 @@ function showTimeTable($links) {
$computerData[$id]["stateid"] == 5)) {
continue;
}
+ # maintenance window
+ if($timeslots[$id][$stamp]["inmaintenance"] == 1) {
+ print " <TD bgcolor=\"#a0a0a0\"><img src=images/gray.jpg ";
+ print "alt=sitemaintenance border=0></TD>\n";
+ }
# computer's schedule is currently closed
- if($timeslots[$id][$stamp]["scheduleclosed"] == 1) {
+ elseif($timeslots[$id][$stamp]["scheduleclosed"] == 1) {
print " <TD bgcolor=\"#a0a0a0\"><img src=images/gray.jpg ";
print "alt=scheduleclosed border=0></TD>\n";
}
@@ -6705,6 +6889,29 @@ function scheduleClosed($computerid, $ti
////////////////////////////////////////////////////////////////////////////////
///
+/// \fn checkInMaintenanceForTimeTable($start, $end, $items)
+///
+/// \param $start - start time in unix timestamp format
+/// \param $end - end time in unix timestamp format
+/// \param $items - list of maintenance items as returned by
+/// getMaintItemsForTimeTable
+///
+/// \return 1 if specified time period falls in an maintenance window, 0 if not
+///
+/// \brief checks if the specified time period overlaps with a scheduled
+/// maintenance window
+///
+////////////////////////////////////////////////////////////////////////////////
+function checkInMaintenanceForTimeTable($start, $end, $items) {
+ foreach($items as $item) {
+ if($item['start'] < $end && $item['end'] > $start)
+ return 1;
+ }
+ return 0;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
/// \fn updateGroups($newusergroups, $userid)
///
/// \param $newusergroups - array of $userid's current set of user groups
@@ -6824,6 +7031,97 @@ function getUserGroupName($id, $incAffil
////////////////////////////////////////////////////////////////////////////////
///
+/// \fn getMaintItems($id)
+///
+/// \param $id (optional) - if specified, id of maintenance item to get info
+/// about
+///
+/// \return array of maintenance items where each id is a maintenance id and
+/// each element is an array with these keys:\n
+/// \b id - id of maintenance item\n
+/// \b start - start of maintenance item (datetime)\n
+/// \b end - end of maintenance item (datetime)\n
+/// \b ownerid - id from user table of owner of this maintenance item\n
+/// \b owner - unityid@affiliation of owner\n
+/// \b created - date/time entry was created (or last modified)\n
+/// \b reason - reason viewable by sysadmins for maintenance item\n
+/// \b usermessage - message viewable by all users for maintenance item\n
+/// \b informhoursahead - number of hours before start that a message will be
+/// displayed to all site users about the upcoming maintenance\n
+/// \b allowreservations - whether or not reservations can extend into this
+/// maintenance window (0 or 1)
+///
+/// \brief builds a list of current maintenance items and returns them
+///
+////////////////////////////////////////////////////////////////////////////////
+function getMaintItems($id=0) {
+ $key = getKey(array('getMaintItems', $id));
+ if(isset($_SESSION) && array_key_exists($key, $_SESSION['usersessiondata']))
+ return $_SESSION['usersessiondata'][$key];
+ $query = "SELECT m.id, "
+ . "m.start, "
+ . "m.end, "
+ . "m.ownerid, "
+ . "CONCAT(u.unityid, '@', a.name) AS owner, "
+ . "m.created, "
+ . "m.reason, "
+ . "m.usermessage, "
+ . "m.informhoursahead, "
+ . "m.allowreservations "
+ . "FROM sitemaintenance m, "
+ . "user u, "
+ . "affiliation a "
+ . "WHERE m.ownerid = u.id AND "
+ . "u.affiliationid = a.id AND "
+ . "m.end > NOW() ";
+ if($id)
+ $query .= "AND m.id = $id ";
+ $query .= "ORDER BY m.start";
+ $qh = doQuery($query, 101);
+ $data = array();
+ while($row = mysql_fetch_assoc($qh))
+ $data[$row['id']] = $row;
+ $_SESSION['usersessiondata'][$key] = $data;
+ return $data;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \fn getMaintItemsForTimeTable($start, $end)
+///
+/// \param $start - start time in unix timestamp format
+/// \param $end - end time in unix timestamp format
+///
+/// \return array of maintenance items that overlap with $start and $end where
+/// each item has 2 keys:\n
+/// \b start - start time in unix timestamp format\n
+/// \b end - end time in unix timestamp format
+///
+/// \brief builds a simple list of maintenance items and returns them
+///
+////////////////////////////////////////////////////////////////////////////////
+function getMaintItemsForTimeTable($start, $end) {
+ $key = getKey(array('getMaintItemsForTimeTable', $start, $end));
+ if(array_key_exists($key, $_SESSION['usersessiondata']))
+ return $_SESSION['usersessiondata'][$key];
+ $startdt = unixToDatetime($start);
+ $enddt = unixToDatetime($end);
+ $query = "SELECT UNIX_TIMESTAMP(start - INTERVAL 30 MINUTE) AS start, "
+ . "UNIX_TIMESTAMP(end) AS end "
+ . "FROM sitemaintenance "
+ . "WHERE end > '$startdt' AND "
+ . "start < '$enddt' "
+ . "ORDER BY start";
+ $qh = doQuery($query, 101);
+ $data = array();
+ while($row = mysql_fetch_assoc($qh))
+ $data[] = $row;
+ $_SESSION['usersessiondata'][$key] = $data;
+ return $data;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
/// \fn unset_by_val($needle, &$haystack)
///
/// \param $needle - value to remove from array
@@ -8527,6 +8825,8 @@ function printHTMLHeader() {
if(! in_array($mode, $noHTMLwrappers)) {
print $HTMLheader;
+ if($mode != 'inmaintenance')
+ print maintenanceNotice();
$printedHTMLheader = 1;
}
}
@@ -8624,6 +8924,11 @@ function getNavMenu($inclogout, $inchome
$rt .= "<a href=\"" . BASEURL . SCRIPT . "?mode=editVMInfo\">";
$rt .= "Virtual Hosts</a></li>\n";
}
+ if($viewmode == ADMIN_DEVELOPER) {
+ $rt .= menulistLI('sitemaintenance');
+ $rt .= "<a href=\"" . BASEURL . SCRIPT . "?mode=siteMaintenance\">";
+ $rt .= "Site Maintenance</a></li>\n";
+ }
$rt .= menulistLI('statistics');
$rt .= "<a href=\"" . BASEURL . SCRIPT . "?mode=selectstats\">";
$rt .= "Statistics</a></li>\n";
@@ -8673,6 +8978,7 @@ function getExtraCSS() {
case 'viewdocs':
return array('doxygen.css');
}
+ return array();
}
////////////////////////////////////////////////////////////////////////////////
@@ -8818,6 +9124,19 @@ function getDojoHTML($refresh) {
'dojo.data.ItemFileReadStore',
'dijit.Dialog');
break;
+ case 'siteMaintenance':
+ $dojoRequires = array('dojo.parser',
+ 'dijit.form.Button',
+ 'dijit.form.NumberSpinner',
+ 'dijit.form.DateTextBox',
+ 'dijit.form.TimeTextBox',
+ 'dijit.form.TextBox',
+ 'dijit.form.Select',
+ 'dijit.form.Textarea',
+ 'dojox.string.sprintf',
+ 'dijit.Tooltip',
+ 'dijit.Dialog');
+ break;
}
if(empty($dojoRequires))
return '';
@@ -9099,6 +9418,22 @@ function getDojoHTML($refresh) {
$rt .= " });\n";
$rt .= "</script>\n";
return $rt;
+ case "siteMaintenance":
+ $rt .= "<style type=\"text/css\">\n";
+ $rt .= " @import \"themes/$skin/css/dojo/$skin.css\";\n";
+ $rt .= "</style>\n";
+ $rt .= "<script type=\"text/javascript\" src=\"js/sitemaintenance.js\"></script>\n";
+ $rt .= "<script type=\"text/javascript\" src=\"dojo/dojo/dojo.js\"\n";
+ $rt .= " djConfig=\"parseOnLoad: true\">\n";
+ $rt .= "</script>\n";
+ $rt .= "<script type=\"text/javascript\">\n";
+ $rt .= " dojo.addOnLoad(function() {\n";
+ foreach($dojoRequires as $req) {
+ $rt .= " dojo.require(\"$req\");\n";
+ }
+ $rt .= " });\n";
+ $rt .= "</script>\n";
+ return $rt;
default:
$rt .= "<style type=\"text/css\">\n";
Modified: incubator/vcl/trunk/web/.ht-inc/xmlrpcWrappers.php
URL: http://svn.apache.org/viewvc/incubator/vcl/trunk/web/.ht-inc/xmlrpcWrappers.php?rev=990918&r1=990917&r2=990918&view=diff
==============================================================================
--- incubator/vcl/trunk/web/.ht-inc/xmlrpcWrappers.php (original)
+++ incubator/vcl/trunk/web/.ht-inc/xmlrpcWrappers.php Mon Aug 30 19:39:30 2010
@@ -593,8 +593,16 @@ function XMLRPCextendRequest($requestid,
}
$rc = isAvailable(getImages(), $request['reservations'][0]["imageid"],
$startts, $newendts, '', $requestid);
+ // conflicts with scheduled maintenance
+ if($rc == -2) {
+ addChangeLogEntry($request["logid"], NULL, unixToDatetime($newendts),
+ $request['start'], NULL, NULL, 0);
+ return array('status' => 'error',
+ 'errorcode' => 46,
+ 'errormsg' => 'requested time is during a maintenance window');
+ }
// concurrent license overlap
- if($rc == -1) {
+ elseif($rc == -1) {
addChangeLogEntry($request["logid"], NULL, unixToDatetime($newendts),
$request['start'], NULL, NULL, 0);
return array('status' => 'error',
@@ -716,8 +724,16 @@ function XMLRPCsetRequestEnding($request
}
$rc = isAvailable(getImages(), $request['reservations'][0]["imageid"],
$startts, $end, '', $requestid);
+ // conflicts with scheduled maintenance
+ if($rc == -2) {
+ addChangeLogEntry($request["logid"], NULL, unixToDatetime($end),
+ $request['start'], NULL, NULL, 0);
+ return array('status' => 'error',
+ 'errorcode' => 46,
+ 'errormsg' => 'requested time is during a maintenance window');
+ }
// concurrent license overlap
- if($rc == -1) {
+ elseif($rc == -1) {
addChangeLogEntry($request["logid"], NULL, unixToDatetime($end),
$request['start'], NULL, NULL, 0);
return array('status' => 'error',
Modified: incubator/vcl/trunk/web/css/vcl.css
URL: http://svn.apache.org/viewvc/incubator/vcl/trunk/web/css/vcl.css?rev=990918&r1=990917&r2=990918&view=diff
==============================================================================
--- incubator/vcl/trunk/web/css/vcl.css (original)
+++ incubator/vcl/trunk/web/css/vcl.css Mon Aug 30 19:39:30 2010
@@ -248,3 +248,11 @@
background-color: #678db2;
color: white;
}
+
+#maintenancenotice {
+ width: 450px;
+ padding: 3px;
+ margin: 5px;
+ border: 1px solid;
+ background-color: #f3f3f3;
+}
Modified: incubator/vcl/trunk/web/index.php
URL: http://svn.apache.org/viewvc/incubator/vcl/trunk/web/index.php?rev=990918&r1=990917&r2=990918&view=diff
==============================================================================
--- incubator/vcl/trunk/web/index.php (original)
+++ incubator/vcl/trunk/web/index.php Mon Aug 30 19:39:30 2010
@@ -48,6 +48,8 @@ require_once('.ht-inc/errors.php');
require_once('.ht-inc/utils.php');
+maintenanceCheck();
+
dbConnect();
initGlobals();
Added: incubator/vcl/trunk/web/js/sitemaintenance.js
URL: http://svn.apache.org/viewvc/incubator/vcl/trunk/web/js/sitemaintenance.js?rev=990918&view=auto
==============================================================================
--- incubator/vcl/trunk/web/js/sitemaintenance.js (added)
+++ incubator/vcl/trunk/web/js/sitemaintenance.js Mon Aug 30 19:39:30 2010
@@ -0,0 +1,180 @@
+function RPCwrapper(data, CB, dojson) {
+ if(dojson) {
+ dojo.xhrPost({
+ url: 'index.php',
+ load: CB,
+ handleAs: "json",
+ error: errorHandler,
+ content: data,
+ timeout: 15000
+ });
+ }
+ else {
+ dojo.xhrPost({
+ url: 'index.php',
+ load: CB,
+ error: errorHandler,
+ content: data,
+ timeout: 15000
+ });
+ }
+}
+
+function generalReqCB(data, ioArgs) {
+ eval(data);
+ document.body.style.cursor = 'default';
+}
+
+function showAddSiteMaintenance(cont) {
+ dijit.byId('editDialog').attr('title', 'Add Site Maintenance');
+ dojo.byId('editheader').innerHTML = 'Add Site Maintenance';
+ dojo.byId('edittext').innerHTML = 'Fill in the following items and click <b>Create Site Maintenance</b>';
+ dijit.byId('editsubmitbtn').attr('label', 'Create Site Maintenance');
+ dijit.byId('editsubmitbtn').attr('disable', 'false');
+ dijit.byId('hoursahead').attr('value', 168);
+ dojo.byId('submitcont').value = cont;
+ dijit.byId('editDialog').show();
+}
+
+function showEditSiteMaintenance(cont) {
+ document.body.style.cursor = 'wait';
+ RPCwrapper({continuation: cont}, showEditSiteMaintenanceCB, 1);
+}
+
+function showEditSiteMaintenanceCB(data, ioArgs) {
+ dijit.byId('editDialog').attr('title', 'Edit Site Maintenance Entry');
+ dojo.byId('editheader').innerHTML = 'Edit Site Maintenance Entry';
+ dojo.byId('edittext').innerHTML = 'Adjust in the following items and click <b>Save Changes</b>';
+ dijit.byId('editsubmitbtn').attr('label', 'Save Changes');
+ dijit.byId('editsubmitbtn').attr('disable', 'false');
+
+ var start = new Date(data.items.start);
+ var end = new Date(data.items.end);
+ dijit.byId('starttime').attr('value', start);
+ dijit.byId('startdate').attr('value', start);
+ dijit.byId('endtime').attr('value', end);
+ dijit.byId('enddate').attr('value', end);
+ dijit.byId('hoursahead').attr('value', data.items.hoursahead);
+ updateDaysHours(data.items.hoursahead);
+ dijit.byId('allowreservations').attr('value', data.items.allowreservations);
+ dijit.byId('reason').attr('value', data.items.reason);
+ dijit.byId('usermessage').attr('value', data.items.usermessage);
+ dojo.byId('submitcont').value = data.items.cont;
+
+ dijit.byId('editDialog').show();
+ document.body.style.cursor = 'default';
+}
+
+function updateDaysHours(val) {
+ var days = Math.floor(val / 24);
+ var hours = val % 24;
+ var text = days + " days, " + hours;
+ if(hours == 1)
+ text += " hour";
+ else
+ text += " hours";
+ dojo.byId('dayshours').innerHTML = text;
+ return val;
+}
+
+function editSubmit() {
+ if(! dijit.byId('starttime').isValid() || ! dijit.byId('startdate')) {
+ dijit.byId('starttime')._hasBeenBlurred = true;
+ dijit.byId('starttime').validate();
+ dijit.byId('startdate')._hasBeenBlurred = true;
+ dijit.byId('startdate').validate();
+ alert('Please specify a valid start time and date');
+ return;
+ }
+ if(! dijit.byId('endtime').isValid() || ! dijit.byId('enddate')) {
+ dijit.byId('endtime')._hasBeenBlurred = true;
+ dijit.byId('endtime').validate();
+ dijit.byId('enddate')._hasBeenBlurred = true;
+ dijit.byId('enddate').validate();
+ alert('Please specify a valid end time and date');
+ return;
+ }
+ if(! dijit.byId('hoursahead').isValid()) {
+ alert('Please specify a valid number of hours ahead');
+ return;
+ }
+ if(dijit.byId('usermessage').attr('value').length == 0) {
+ alert('Please fill in something for the User Message');
+ return;
+ }
+ var start = dijit.byId('startdate').value;
+ var tmp = dijit.byId('starttime').value;
+ start.setHours(tmp.getHours());
+ start.setMinutes(tmp.getMinutes());
+ start.setSeconds(tmp.getSeconds());
+ start.setMilliseconds(0);
+ var now = new Date();
+ if(start < now) {
+ alert('The start time and date must be later than the current time.');
+ return;
+ }
+ var end = dijit.byId('enddate').value;
+ var tmp = dijit.byId('endtime').value;
+ end.setHours(tmp.getHours());
+ end.setMinutes(tmp.getMinutes());
+ end.setSeconds(tmp.getSeconds());
+ end.setMilliseconds(0);
+ if(end <= start) {
+ alert('The end time and date must be later than the start time and date.');
+ return;
+ }
+ var numstart = dojox.string.sprintf('%04d%02d%02d%02d%02d', start.getFullYear(),
+ start.getMonth() + 1, start.getDate(),
+ start.getHours(), start.getMinutes());
+ var numend = dojox.string.sprintf('%04d%02d%02d%02d%02d', end.getFullYear(),
+ end.getMonth() + 1, end.getDate(),
+ end.getHours(), end.getMinutes());
+ var data = {continuation: dojo.byId('submitcont').value,
+ start: numstart,
+ end: numend,
+ hoursahead: dijit.byId('hoursahead').attr('value'),
+ allowreservations: dijit.byId('allowreservations').value,
+ reason: dijit.byId('reason').attr('value'),
+ usermessage: dijit.byId('usermessage').attr('value')};
+ document.body.style.cursor = 'wait';
+ dijit.byId('editsubmitbtn').attr('disable', 'true');
+ RPCwrapper(data, generalReqCB);
+}
+
+function clearEdit() {
+ dijit.byId('editDialog').hide();
+ dijit.byId('editDialog').attr('title', '');
+ dojo.byId('editheader').innerHTML = '';
+ dojo.byId('edittext').innerHTML = '';
+ dijit.byId('editsubmitbtn').attr('label', '');
+ dijit.byId('editsubmitbtn').attr('disable', 'false');
+ dijit.byId('hoursahead').attr('value', 168);
+ dojo.byId('dayshours').innerHTML = '';
+ dojo.byId('submitcont').value = '';
+}
+
+function confirmDeleteSiteMaintenance(cont) {
+ document.body.style.cursor = 'wait';
+ RPCwrapper({continuation: cont}, confirmDeleteSiteMaintenanceCB, 1);
+}
+
+function confirmDeleteSiteMaintenanceCB(data, ioArgs) {
+ dojo.byId('start').innerHTML = data.items.start;
+ dojo.byId('end').innerHTML = data.items.end;
+ dojo.byId('owner').innerHTML = data.items.owner;
+ dojo.byId('created').innerHTML = data.items.created;
+ dojo.byId('informhoursahead').innerHTML = data.items.hoursahead;
+ dojo.byId('delallowreservations').innerHTML = data.items.allowreservations;
+ dojo.byId('delreason').innerHTML = data.items.reason;
+ dojo.byId('delusermessage').innerHTML = data.items.usermessage;
+ dojo.byId('delsubmitcont').value = data.items.cont;
+
+ dijit.byId('confirmDialog').show();
+ document.body.style.cursor = 'default';
+}
+
+function deleteSiteMaintenance() {
+ var cont = dojo.byId('delsubmitcont').value;
+ document.body.style.cursor = 'wait';
+ RPCwrapper({continuation: cont}, generalReqCB);
+}
Modified: incubator/vcl/trunk/web/testsetup.php
URL: http://svn.apache.org/viewvc/incubator/vcl/trunk/web/testsetup.php?rev=990918&r1=990917&r2=990918&view=diff
==============================================================================
--- incubator/vcl/trunk/web/testsetup.php (original)
+++ incubator/vcl/trunk/web/testsetup.php Mon Aug 30 19:39:30 2010
@@ -230,6 +230,39 @@ if($includeconf && include('.ht-inc/conf
fail("SCRIPT does not appear to be set correctly");
}
print "</ul>\n";
+
+ # check for existance of maintenance directory
+ title("Checking that .ht-inc/maintenance directory exists");
+ print "<ul>\n";
+ $file = preg_replace('|/testsetup.php|', '', $_SERVER['SCRIPT_FILENAME']);
+ $file .= "/.ht-inc/maintenance";
+ if(! is_dir($file))
+ fail("/.ht-inc/maintenance directory does not exist. Please create it.");
+ else {
+ pass("/.ht-inc/maintenance directory exists");
+ print "</ul>\n";
+ # check that we can write files to maintenance directory
+ title("Checking that .ht-inc/maintenance directory is writable");
+ print "<ul>\n";
+ if(! is_writable("$file"))
+ fail("Maintenance directory is not writable");
+ else {
+ if(! $fh = @fopen("$file/testfile", 'w'))
+ fail("Failed to open file in maintenance directory");
+ else {
+ if(! fwrite($fh, 'test') || ! fclose($fh))
+ fail("Failed to write to file in maintenance directory");
+ else {
+ # check that we can remove files from maintenance directory
+ if(! unlink("$file/testfile"))
+ fail("Failed to remove file from maintenance directory");
+ else
+ pass("Maintenance directory is writable");
+ }
+ }
+ }
+ }
+ print "</ul>\n";
}
# required extentions