From 7a28108475c0107769bf5e3886df8f2740424ded Mon Sep 17 00:00:00 2001 From: "Florian Aders (EleRas)" Date: Sat, 18 Jun 2011 19:42:01 +0200 Subject: [PATCH] Added usage of filesystem - quota to diskusage - calculation and added a new task to cron_tasks.php for setting the quota, refs #814 Signed-off-by: Florian Aders (EleRas) --- lng/english.lng.php | 7 +++ lng/german.lng.php | 7 +++ scripts/jobs/cron_tasks.php | 97 +++++++++++++++++++++++++++++------ scripts/jobs/cron_traffic.php | 79 ++++++++++++++++++++-------- 4 files changed, 155 insertions(+), 35 deletions(-) diff --git a/lng/english.lng.php b/lng/english.lng.php index 42cc1ece..d3fd6b87 100644 --- a/lng/english.lng.php +++ b/lng/english.lng.php @@ -1877,3 +1877,10 @@ $lng['country']['EH'] = "Western Sahara"; $lng['country']['YE'] = "Yemen"; $lng['country']['ZM'] = "Zambia"; $lng['country']['ZW'] = "Zimbabwe"; + +// ADDED IN FROXLOR 0.9.22-svn1 +$lng['diskquota'] = 'Quota'; +$lng['serversettings']['diskquota_enabled'] = 'Quota activated?'; +$lng['serversettings']['diskquota_repquota_path']['description'] = 'Path to the repquota - tool'; +$lng['serversettings']['diskquota_quotatool_path']['description'] = 'Path to quotatool'; +$lng['serversettings']['diskquota_customer_partition']['description'] = 'Partition, on which the customer files are stored'; \ No newline at end of file diff --git a/lng/german.lng.php b/lng/german.lng.php index b5c46ced..50ce1386 100644 --- a/lng/german.lng.php +++ b/lng/german.lng.php @@ -1608,3 +1608,10 @@ $lng['gender']['female'] = 'Frau'; $lng['gender']['undef'] = ''; $lng['serversettings']['backup_ftp_passive_mode'] = 'Passiven Übertragungsmodus verwenden'; $lng['serversettings']['backup_bigfile'] = 'Backup von Kundenverzeichnissen und Datenbanken in eine Datei speichern, statt zu splitten?'; + +// ADDED IN FROXLOR 0.9.22-svn1 +$lng['diskquota'] = 'Quota'; +$lng['serversettings']['diskquota_enabled'] = 'Quota aktiviert?'; +$lng['serversettings']['diskquota_repquota_path']['description'] = 'Pfad zu dem repquota - Tool'; +$lng['serversettings']['diskquota_quotatool_path']['description'] = 'Pfad zu quotatool'; +$lng['serversettings']['diskquota_customer_partition']['description'] = 'Partition, auf welcher die Kundendaten liegen'; \ No newline at end of file diff --git a/scripts/jobs/cron_tasks.php b/scripts/jobs/cron_tasks.php index b1dc7ab0..7bd1e055 100644 --- a/scripts/jobs/cron_tasks.php +++ b/scripts/jobs/cron_tasks.php @@ -64,7 +64,7 @@ while($row = $db->fetch_array($result_tasks)) * (e.g. awstats not installed yet or whatever) * fixes #45 */ - if (is_dir($awstatsclean['path'])) + if (is_dir($awstatsclean['path'])) { $awstatsclean['dir'] = dir($awstatsclean['path']); while($awstatsclean['entry'] = $awstatsclean['dir']->read()) { @@ -98,7 +98,7 @@ while($row = $db->fetch_array($result_tasks)) { $configdir = makeCorrectDir($settings['system']['mod_fcgid_configdir']); - if (is_dir($configdir)) + if (is_dir($configdir)) { $its = new RecursiveIteratorIterator( new RecursiveDirectoryIterator($configdir) @@ -108,14 +108,14 @@ while($row = $db->fetch_array($result_tasks)) // look for php-fcgi-starter files // and take immutable-flag away from them // so we can delete them :) - foreach ($its as $fullFileName => $it ) + foreach ($its as $fullFileName => $it ) { - if ($it->isFile() && $it->getFilename() == 'php-fcgi-starter') + if ($it->isFile() && $it->getFilename() == 'php-fcgi-starter') { removeImmutable($its->getPathname()); } } - // now get rid of old stuff + // now get rid of old stuff //(but append /* so we don't delete the directory) $configdir.='/*'; safe_exec('rm -rf '. makeCorrectFile($configdir)); @@ -127,9 +127,9 @@ while($row = $db->fetch_array($result_tasks)) { $configdir = makeCorrectDir($settings['phpfpm']['configdir']); - if (is_dir($configdir)) + if (is_dir($configdir)) { - // now get rid of old stuff + // now get rid of old stuff //(but append /* so we don't delete the directory) $configdir.='/*'; safe_exec('rm -rf '. makeCorrectFile($configdir)); @@ -211,7 +211,7 @@ while($row = $db->fetch_array($result_tasks)) $cronlog->logAction(CRON_ACTION, LOG_NOTICE, 'Running: mkdir -p ' . escapeshellarg($userhomedir . 'webalizer')); safe_exec('mkdir -p ' . escapeshellarg($userhomedir . 'webalizer')); } - + // maildir $cronlog->logAction(CRON_ACTION, LOG_NOTICE, 'Running: mkdir -p ' . escapeshellarg($usermaildir)); safe_exec('mkdir -p ' . escapeshellarg($usermaildir)); @@ -318,8 +318,8 @@ while($row = $db->fetch_array($result_tasks)) { // e.g. /var/www/php-fcgi-starter/web1/ $configdir = makeCorrectDir($settings['system']['mod_fcgid_configdir'] . '/' . $row['data']['loginname'] . '/'); - - if (is_dir($configdir)) + + if (is_dir($configdir)) { $its = new RecursiveIteratorIterator( new RecursiveDirectoryIterator($configdir) @@ -329,16 +329,16 @@ while($row = $db->fetch_array($result_tasks)) // look for php-fcgi-starter files // and take immutable-flag away from them // so we can delete them :) - foreach ($its as $fullFileName => $it ) + foreach ($its as $fullFileName => $it ) { - if ($it->isFile() && $it->getFilename() == 'php-fcgi-starter') + if ($it->isFile() && $it->getFilename() == 'php-fcgi-starter') { removeImmutable($its->getPathname()); } } // now get rid of old stuff safe_exec('rm -rf '. escapeshellarg($configdir)); - } + } } } } @@ -409,7 +409,7 @@ while($row = $db->fetch_array($result_tasks)) */ elseif ($row['type'] == '9') { - + fwrite($debugHandler, ' cron_tasks: Task9 started - creating backup dir protection' . "\n"); $cronlog->logAction(CRON_ACTION, LOG_INFO, 'Task9 started - creating backup dir protection'); @@ -457,7 +457,74 @@ while($row = $db->fetch_array($result_tasks)) } } } - + + } + } + + /** + * TYPE=10 Set the filesystem - quota + */ + elseif ($row['type'] == '10') + { + if ($settings['system']['diskquota_enabled']) + { + fwrite($debugHandler, ' cron_tasks: Task10 started - setting filesystem quota' . "\n"); + $cronlog->logAction(CRON_ACTION, LOG_INFO, 'Task10 started - setting filesystem quota'); + + # Fetch all quota in the desired partition + exec($settings['system']['diskquota_repquota_path'] . " -n " . escapeshellarg($settings['system']['diskquota_customer_partition']), $repquota); + + $usedquota = array(); + foreach ($repquota as $tmpquota) + { + # Let's see if the line matches a quota - line + if (preg_match('/^#([0-9]+)\s*[+-]{2}\s*(\d+)\s*(\d+)\s*(\d+)\s*(\ddays)?\s*(\d+)\s*(\d+)\s*(\d+)/i', $tmpquota, $matches)) + { + # It matches - put it into an array with userid as key (for easy lookup later) + $usedquota[$matches[1]] = array( + 'block' => array( + 'used' => $matches[2], + 'soft' => $matches[3], + 'hard' => $matches[4], + 'grace' => $matches[5] + ), + 'file' => array( + 'used' => $matches[6], + 'soft' => $matches[7], + 'hard' => $matches[8], + 'grace' => $matches[9] + ), + ); + } + } + + # Select all customers Froxlor knows about + $result = $db->query("SELECT `guid`, `loginname`, `diskspace` FROM `" . TABLE_PANEL_CUSTOMERS . "`;"); + while($row = $db->fetch_array($result)) + { + # We do not want to set a quota for root by accident + if ($row['guid'] != 0) + { + # The user has no quota in Froxlor, but on the filesystem + if (($row['diskspace'] == 0 || $row['diskspace'] == -1024) && $usedquota[$row['guid']]['block']['hard'] != 0) + { + $cronlog->logAction(CRON_ACTION, LOG_NOTICE, "Disabling quota for " . $row['loginname']); + safe_exec($settings['system']['diskquota_quotatool_path'] . " -u " . $row['guid'] . " -bl 0 -q 0 " . escapeshellarg($settings['system']['diskquota_customer_partition'])); + } + + # The user quota in Froxlor is different than on the filesystem + elseif($row['diskspace'] != $usedquota[$row['guid']]['block']['hard'] && $row['diskspace'] != -1024) + { + $cronlog->logAction(CRON_ACTION, LOG_NOTICE, "Setting quota for " . $row['loginname'] . " from " . $usedquota[$row['guid']]['block']['hard'] . " to " . $row['diskspace']); + safe_exec($settings['system']['diskquota_quotatool_path'] . " -u " . $row['guid'] . " -bl " . $row['diskspace'] . " -q " . $row['diskspace'] . " " . escapeshellarg($settings['system']['diskquota_customer_partition'])); + } + } + } + } + else + { + fwrite($debugHandler, ' cron_tasks: Task10 skipped - filesystem quota not enabled' . "\n"); + $cronlog->logAction(CRON_ACTION, LOG_INFO, 'Task10 skipped - filesystem quota not enabled'); } } } diff --git a/scripts/jobs/cron_traffic.php b/scripts/jobs/cron_traffic.php index abd6f68f..c6505751 100644 --- a/scripts/jobs/cron_traffic.php +++ b/scripts/jobs/cron_traffic.php @@ -80,7 +80,7 @@ while($row_database = $db->fetch_array($databases)) $databases_list[] = strtolower($databases_list_row['Database']); } } - + if(in_array(strtolower($row_database['databasename']), $databases_list)) { $mysql_usage_result = $db_root->query("SHOW TABLE STATUS FROM `" . $db_root->escape($row_database['databasename']) . "`"); @@ -102,7 +102,36 @@ while($row_database = $db->fetch_array($databases)) $db_root->close(); +# We are using the file-system quota, this will speed up the diskusage - collection +if ($settings['system']['diskquota_enabled']) +{ + # Fetch all quota in the desired partition + exec("repquota -n " . $settings['system']['diskquota_customer_partition'], $repquota); + $usedquota = array(); + foreach ($repquota as $tmpquota) + { + # Let's see if the line matches a quota - line + if (preg_match('/^#([0-9]+)\s*[+-]{2}\s*(\d+)\s*(\d+)\s*(\d+)\s*(\ddays)?\s*(\d+)\s*(\d+)\s*(\d+)/i', $tmpquota, $matches)) + { + # It matches - put it into an array with userid as key (for easy lookup later) + $usedquota[$matches[1]] = array( + 'block' => array( + 'used' => $matches[2], + 'soft' => $matches[3], + 'hard' => $matches[4], + 'grace' => $matches[5] + ), + 'file' => array( + 'used' => $matches[6], + 'soft' => $matches[7], + 'hard' => $matches[8], + 'grace' => $matches[9] + ), + ); + } + } +} $result = $db->query("SELECT * FROM `" . TABLE_PANEL_CUSTOMERS . "` ORDER BY `customerid` ASC"); while($row = $db->fetch_array($result)) @@ -179,7 +208,7 @@ while($row = $db->fetch_array($result)) safeSQLLogfile($domainlist[$row['customerid']], $row['loginname']); } - // callAwstatsGetTraffic is called ONLY HERE and + // callAwstatsGetTraffic is called ONLY HERE and // *not* also in the special-logfiles-loop, because the function // will iterate through all customer-domains and the awstats-configs // know the logfile-name, #246 @@ -191,7 +220,7 @@ while($row = $db->fetch_array($result)) { $httptraffic+= floatval(callWebalizerGetTraffic($row['loginname'], $row['documentroot'] . '/webalizer/', $caption, $domainlist[$row['customerid']])); } - + // make the stuff readable for the customer, #258 makeChownWithNewStats($row); @@ -207,7 +236,7 @@ while($row = $db->fetch_array($result)) $db->close(); require_once ($pathtophpfiles . '/lib/userdata.inc.php'); $db = new db($sql['host'], $sql['user'], $sql['password'], $sql['db']); - + if ($db->link_id == 0) { fclose($debugHandler); unlink($lockfile); @@ -285,23 +314,33 @@ while($row = $db->fetch_array($result)) fwrite($debugHandler, 'calculating webspace usage for ' . $row['loginname'] . "\n"); $webspaceusage = 0; - - if(file_exists($row['documentroot']) && is_dir($row['documentroot'])) + + # Using repquota, it's faster using this tool than using du traversing the complete directory + if ($settings['system']['diskquota_enabled']) { - $back = safe_exec('du -sk ' . escapeshellarg($row['documentroot']) . ''); - foreach($back as $backrow) - { - $webspaceusage = explode(' ', $backrow); - } - - $webspaceusage = floatval($webspaceusage['0']); - unset($back); + # We may use the array we created earlier, the used diskspace is stored in [][block][used] + $webspaceusage = floatval($usedquota[$row['guid']]['block']['used']); } else { - fwrite($debugHandler, 'documentroot ' . $row['documentroot'] . ' does not exist' . "\n"); + # Use the old fashioned way with "du" + if(file_exists($row['documentroot']) && is_dir($row['documentroot'])) + { + $back = safe_exec('du -sk ' . escapeshellarg($row['documentroot']) . ''); + foreach($back as $backrow) + { + $webspaceusage = explode(' ', $backrow); + } + + $webspaceusage = floatval($webspaceusage['0']); + unset($back); + } + else + { + fwrite($debugHandler, 'documentroot ' . $row['documentroot'] . ' does not exist' . "\n"); + } } - + /** * MailSpace-Usage */ @@ -317,7 +356,7 @@ while($row = $db->fetch_array($result)) { $emailusage = explode(' ', $backrow); } - + $emailusage = floatval($emailusage['0']); unset($back); } @@ -380,11 +419,11 @@ while($row = $db->fetch_array($result)) */ $db->query("UPDATE `" . TABLE_FTP_QUOTATALLIES . "` SET `bytes_in_used`='" . (float)$current_diskspace['all'] . "'*1024 WHERE `name` = '" . $row['loginname'] . "' OR `name` LIKE '" . $row['loginname'] . $settings['customer']['ftpprefix'] . "%'"); - + /** * Pureftpd Quota */ - + if($settings['system']['ftpserver'] == "pureftpd") { $result_quota = $db->query("SELECT homedir FROM `" . TABLE_FTP_USERS . "` WHERE customerid = '" . $row['customerid'] . "'"); @@ -400,7 +439,7 @@ while($row = $db->fetch_array($result)) $user = $row['guid']; $group = $row['guid']; } - + while($row_quota = $db->fetch_array($result_quota)) { $quotafile = "" . $row_quota['homedir'] . ".ftpquota";