Страница 1 из 2

ISP Блокируем пользователей за перерасход CPU

Добавлено: 2012-07-16 18:16:06
rootden
Сделал сегодня системную задачу в биллинге которая проверяет все заказы хостинга на предмет перерасхода cpu основываясь на данных от системного аккаунтинга в isp, sa в ос.

Раньше это были отдельные самостоятельные скрипты, а теперь все в биллинге штатно, кому надо берите.

1. sql

Код: Выделить всё


INSERT INTO `Tasks` (`UserID`,`TypeID`,`Params`,`IsActive`) VALUES (1,'CPUusage','[]','yes');

ALTER TABLE `HostingSchemes` ADD `ISPCPUusage` VARCHAR(255) NOT NULL ;

ALTER TABLE `HostingOrders` ADD `Cpucount` INT(12) NOT NULL;

DROP VIEW IF EXISTS `HostingOrdersOwners`;
DROP TABLE IF EXISTS `HostingOrdersOwners`;
CREATE
  VIEW `HostingOrdersOwners` AS
SELECT
  `HostingOrders`.*,
  (SELECT `DaysRemainded` FROM `OrdersOwners` WHERE `HostingOrders`.`OrderID` = `OrdersOwners`.`ID`) AS `DaysRemainded`,
  `OrdersOwners`.`OrderDate`,
  `OrdersOwners`.`UserID`,
  `OrdersOwners`.`ContractID`
FROM
  `HostingOrders`
LEFT JOIN `OrdersOwners`
ON (`HostingOrders`.`OrderID` = `OrdersOwners`.`ID`);


/www/domen/hosts/hosting/config/Config.xml

в секцию Tasks допишите задачу

Код: Выделить всё

  <CPUusage>
   <Name>Учет статистики по cpu ispmanager</Name>
   <Params type="array" />
   <IsActive>1</IsActive>
  </CPUusage>


в секцию Notifies

Код: Выделить всё

<HostingNoticeCPUusage>
<Name>Уведомление о превышение CPU</Name>
<GroupID>1</GroupID>
</HostingNoticeCPUusage>


/hosts/hosting/templates/Notifies/Email

кидаем HostingNoticeCPUusage.tpl

Код: Выделить всё

{*
 *  Copyright © 2012 Rootden for Dgrad-host.com
 *}
{assign var=Theme value="Превышение использования CPU" scope=global}
Здравствуйте, {$User.Name|default:'$User.Name'}!

Предупреждение №{$HostingOrder.UsageCount|default:'$HostingOrder.UsageCount'}

Уведомляем Вас о том, что ваш аккаунт {$HostingOrder.Login|default:'$HostingOrder.Login'} заказ хостинга №{$HostingOrder.OrderID|string_format:"%05u"}, израсходовал все ресурсы по CPU согласно вашему тарифу {$HostingOrder.Tarif|default:'$HostingOrder.Tarif'}.

Вы использовали: {$HostingOrder.CpuUsage|default:'$HostingOrder.CpuUsage'} часа/часов процессорного времени за текущий месяц из {$HostingOrder.CpuUsageMax|default:'$HostingOrder.CpuUsageMax'}ч положенных по тарифу.

Просим вас решить эту проблему и сообщить о принятых мерах или повысить тариф, иначе аккаунт заблокируется автоматически после 3-го предупреждения.

За более детальной информацией обращайтесь в единый центр поддержки по адресу:

http://billing.dgrad-host.com/Tickets

{$From.Sign|default:'$From.Sign'}


HostingNoticeCPUusageMax.tpl

Код: Выделить всё

{*
 *  Copyright © 2012 Rootden for Dgrad-host.com
 *}
{assign var=Theme value="Превышение использования CPU" scope=global}
Здравствуйте, {$User.Name|default:'$User.Name'}!

Ваш аккаунт заблокирован!

Уведомляем Вас о том, что вы получили 3 предупреждения и не отреагировали, ваш аккаунт {$HostingOrder.Login|default:'$HostingOrder.Login'} заказ хостинга №{$HostingOrder.OrderID|string_format:"%05u"} приостановлен.

Для разблокировки обращайтесь в единый центр поддержки по адресу:

http://billing.dgrad-host.com/Tickets

{$From.Sign|default:'$From.Sign'}


/hosts/hosting/comp/Tasks

CPUusage.comp.php

Код: Выделить всё

<?php
#-------------------------------------------------------------------------------
/** @author Rootden for Dgrad-host.com */
/******************************************************************************/
Eval(COMP_INIT);
if(Is_Error(System_Load('libs/Http.php')))
  return ERROR | @Trigger_Error(500);
/******************************************************************************/

$Hostings = DB_Select('HostingOrdersOwners',Array('ID','OrderID','SchemeID','ServerID','Login','Cpucount','UserID'),Array('Where'=>"`StatusID` = 'Active'"));

#-------------------------------------------------------------------------------
switch(ValueOf($Hostings)){
  case 'error':
    return ERROR | @Trigger_Error(500);
  case 'exception':
    # No more..
  break;
  case 'array':
    #---------------------------------------------------------------------------
     foreach($Hostings as $Hosting){
     
     #-----------------------------------------------------------------------------
     # выборка HostingSchemes нужно забрать cpu tarif
     $CH = DB_Select('HostingSchemes',Array('Name','ISPCPUusage'),Array('Where'=>"`ID` = '$Hosting[SchemeID]'"));

     Debug("USER_LOGIN = " . $Hosting['Login']);
     #Debug("HOSTING_ID  = " . $Hosting['ID']);
     #Debug("SCHEME_ID = " . $Hosting['SchemeID']);
      Debug("CH_TARIF = " . $CH[0]['ISPCPUusage']);
      #Debug("CPU_COUNT = " . $Hosting['Cpucount']);
    
     #-----------------------------------------------------------------------------
     # Если CP isp то работаем, получаем totalresourceusage
    
     $SRV = DB_Select('HostingServers',Array('SystemID','Address','Port','Protocol','Login','Password'),Array('Where'=>"`ID` = '$Hosting[ServerID]'"));
     $SRV= $SRV[0];
     if ( 'IspManager' == $SRV['SystemID'] ){
    
               Debug("ISPMANAGER > = YES");
    
            $authinfo = SPrintF('%s:%s',$SRV['Login'],$SRV['Password']);
            $Http = Array(
            'Address'  => $SRV['Address'],
            'Port'     => $SRV['Port'],
            'Host'     => $SRV['Address'],
            'Protocol' => $SRV['Protocol'],
            'Hidden'   => $authinfo,
            'IsLoggin' => FALSE
            );
            
            $Response = Http_Send('/manager/ispmgr',$Http,Array('authinfo'=>$authinfo,'out'=>'xml','func'=>'totalresourceusage','elid'=>'ok'));
            if(Is_Error($Response))
             return ERROR | @Trigger_Error(500);

               
              $Response = Trim($Response['Body']);
              $XML = String_XML_Parse($Response);
              $XML = $XML->ToArray('elem');
                  $Result = $XML['doc'];
             
              #Debug(print_r($Result, true));
            
               $found = false;
               foreach ($Result as $key => $value) {
                  if ($value['account']==$Hosting['Login']) {
                     $found = $key;
                     $CPUusage = $value['utime'] + $value['stime'];
                     break;
                  }
               }

              #Debug("Key = " . $found);
             
              #("CPUSUM_SEC = " . $CPUusage);
             
              $cpumount = ceil($CPUusage/3600);
             
                  Debug("CPUSUM_CH = " . $cpumount);
      #-----------------------------------------------------------------------------
     # сравниваем и блокируем аккаунты
    
                  #if (1 == 1) {
                 if ($cpumount >= $CH[0]['ISPCPUusage']) {
               Debug("Detect > = YES");
               
               switch ($Hosting['Cpucount']){
                  case "0":
                            $IsUpdate = DB_Update('HostingOrders',Array('Cpucount'=>'1'),Array('ID'=>$Hosting['ID']));
                            if(Is_Error($IsUpdate))
                            return ERROR | @Trigger_Error(500);
                     
                      $HostingO = Array('UsageCount' => '1', 'Login' => $Hosting['Login'], 'OrderID' => $Hosting['ID'], 'Tarif' => $CH[0]['Name'], 'CpuUsage'  => $cpumount, 'CpuUsageMax' => $CH[0]['ISPCPUusage']);
                       $IsSend = NotificationManager::sendMsg(new Message('HostingNoticeCPUusage',$Hosting['UserID'],Array('HostingOrder'=>$HostingO)));

                     $Event = Array(
                              'UserID'   => $Hosting['UserID'],
                              'PriorityID'=> 'Hosting',
                              'Text'   => SPrintF('Превышение использования CPU, заказ хостинга %s, уведомление №1',$Hosting['Login'])
                             );
                        $Event = Comp_Load('Events/EventInsert',$Event);
                        if(!$Event)
                          return ERROR | @Trigger_Error(500);
                     
                     
                     break;
                  case "1":
                     $IsUpdate = DB_Update('HostingOrders',Array('Cpucount'=>'2'),Array('ID'=>$Hosting['ID']));
                            if(Is_Error($IsUpdate))
                            return ERROR | @Trigger_Error(500);
                     
                     $HostingO = Array('UsageCount' => '2', 'Login' => $Hosting['Login'], 'OrderID' => $Hosting['ID'], 'Tarif' => $CH[0]['Name'], 'CpuUsage'  => $cpumount, 'CpuUsageMax' => $CH[0]['ISPCPUusage']);
                       $IsSend = NotificationManager::sendMsg(new Message('HostingNoticeCPUusage',$Hosting['UserID'],Array('HostingOrder'=>$HostingO)));
                     
                     $Event = Array(
                              'UserID'   => $Hosting['UserID'],
                              'PriorityID'=> 'Hosting',
                              'Text'   => SPrintF('Превышение использования CPU, заказ хостинга %s, уведомление №2',$Hosting['Login'])
                             );
                        $Event = Comp_Load('Events/EventInsert',$Event);
                        if(!$Event)
                          return ERROR | @Trigger_Error(500);
                     
                     
                     break;
                  case "2":
                     $IsUpdate = DB_Update('HostingOrders',Array('Cpucount'=>'3'),Array('ID'=>$Hosting['ID']));
                            if(Is_Error($IsUpdate))
                            return ERROR | @Trigger_Error(500);
                     
                     $HostingO = Array('UsageCount' => '3', 'Login' => $Hosting['Login'], 'OrderID' => $Hosting['ID'], 'Tarif' => $CH[0]['Name'], 'CpuUsage'  => $cpumount, 'CpuUsageMax' => $CH[0]['ISPCPUusage']);
                       $IsSend = NotificationManager::sendMsg(new Message('HostingNoticeCPUusage',$Hosting['UserID'],Array('HostingOrder'=>$HostingO)));
                     
                     $Event = Array(
                              'UserID'   => $Hosting['UserID'],
                              'PriorityID'=> 'Hosting',
                              'Text'   => SPrintF('Превышение использования CPU, заказ хостинга %s, уведомление №3',$Hosting['Login'])
                             );
                        $Event = Comp_Load('Events/EventInsert',$Event);
                        if(!$Event)
                          return ERROR | @Trigger_Error(500);
                     
                     
                     break;
                  case "3":
                     $IsUpdate = DB_Update('HostingOrders',Array('Cpucount'=>'0'),Array('ID'=>$Hosting['ID']));
                            if(Is_Error($IsUpdate))
                            return ERROR | @Trigger_Error(500);
                     
                     $HostingO = Array('UsageCount' => '1', 'Login' => $Hosting['Login'], 'OrderID' => $Hosting['ID'], 'Tarif' => $CH[0]['Name'], 'CpuUsage'  => $cpumount, 'CpuUsageMax' => $CH[0]['ISPCPUusage']);
                       $IsSend = NotificationManager::sendMsg(new Message('HostingNoticeCPUusageMax',$Hosting['UserID'],Array('HostingOrder'=>$HostingO)));
                     
                      $Comp = Comp_Load('www/API/StatusSet',Array('ModeID'=>'HostingOrders','StatusID'=>'Suspended','RowsIDs'=> $Hosting['OrderID'],'Comment'=> SPrintF('Перерасход CPU %s > тариф %s',$cpumount,$CH[0]['ISPCPUusage'])));

                     switch(ValueOf($Comp)){
                       case 'error':
                        return ERROR | @Trigger_Error(500);
                       case 'exception':
                        return ERROR | @Trigger_Error(400);
                       case 'array':
                        # No more...
                       break;
                       default:
                        return ERROR | @Trigger_Error(101);
                     } # end set staus
                           
                       $Event = Array(
                              'UserID'   => $Hosting['UserID'],
                              'PriorityID'=> 'Hosting',
                              'Text'   => SPrintF('Превышение использования CPU, заказ хостинга %s, уведомление №%s',$Hosting['Login'],$Hosting['Cpucount'])
                             );
                        $Event = Comp_Load('Events/EventInsert',$Event);
                        if(!$Event)
                          return ERROR | @Trigger_Error(500);
                     
                     break;
                  default:
                  Debug("Cpucount > 3");
                  return ERROR | @Trigger_Error(500);
               }

               } else Debug("DETECT > = NO");
            }else Debug("ISPMANAGER > = NO");
}

  break;
  default:
    return ERROR | @Trigger_Error(500);
}
#-------------------------------------------------------------------------------
return MkTime(1,30,0,Date('n'),Date('j')+1,Date('Y'));
#-------------------------------------------------------------------------------

?>

Re: ISP Блокируем пользователей за перерасход CPU

Добавлено: 2012-07-16 18:22:51
rootden
и еще пару файликов заменить, в архиве найдете.

работает только с isp, ост панели игнорятся, в isp должен быть активирован системный аккаунтинг.

задание будет выполнятся каждый день в 01.30 ночи, в свойствах тарифа задаются часы процессорного времени (сумма - user + sistem), если юзер все израсходует и будет игнорить предупреждения то после 3-го предупреждения акк блокируется.

Re: ISP Блокируем пользователей за перерасход CPU

Добавлено: 2012-08-09 9:35:28
Alex Keda
хорошая фенька, но до нормального использования надо допиливать...
сервера могут быть разные, и час на оптероне != часу на третьем пне

Re: ISP Блокируем пользователей за перерасход CPU

Добавлено: 2012-08-15 4:05:41
rootden
Alex Keda писал(а):хорошая фенька, но до нормального использования надо допиливать...
сервера могут быть разные, и час на оптероне != часу на третьем пне


пока думаю, тут еще идеи появились учитывать и дневной расход а не только месячный, разрешить 3х кратное превышение в день. + кол запросов в день суммарно у вирт хостов юзера но это отдельным заданием.

по поводу проца тут момент такой что единица измерения часы а не проценты, корректировку не знаю как делать но с этим проблем лично у меня пока нету, вроде все справедливо просто более слабый сервер вместит меньше клиентов.

при созд тарифов за эталон брали самый старый сервер q8200, новые сейчас i7 там конечно расход по меньше будет ибо шустрее, но еще зависит от нагрузки, так что как не крути разброс будет полюбому в силу специфики шареда.

Re: ISP Блокируем пользователей за перерасход CPU

Добавлено: 2012-08-15 4:20:13
rootden
еще нужно будет добавить cpu mysql ибо он вообще не контролируется.

смотрел Percona MySQL можно снимать стату.

http://www.percona.com/doc/percona-serv ... userstatv2

Re: ISP Блокируем пользователей за перерасход CPU

Добавлено: 2013-02-21 9:21:26
Alex Keda
включил у себя штатный сбор статистики, буду впиливать фичу в биллинг.
правда, пока ещё не знаю в каком виде =))

Re: ISP Блокируем пользователей за перерасход CPU

Добавлено: 2013-03-08 18:45:40
Alex Keda
реализовал

Re: ISP Блокируем пользователей за перерасход CPU

Добавлено: 2013-03-12 6:45:11
rootden
гляну как выйдет,

я тут решил все подругому сделать более грамотно,

будем учитывать все что накапало не суммарно за месяц а ежедневно.

1 процессорное время общее cpu.
2 процессорное время mysql.
3 суммарное количество http запросов.

будет 2 лимита:

1 мягкий по тарифу - если превышение периодическое то блокировать, если не регулярное то не трогать.
2 лимит жесткий - если превышен то немедленно блокировать.

Еще нужно проверять процессы пользователя и завершать их если они жрут cpu более X процентов за Y времени, если переодически то блокировать.

Re: ISP Блокируем пользователей за перерасход CPU

Добавлено: 2013-03-12 11:49:09
Alex Keda
rootden писал(а):гляну как выйдет,

я тут решил все подругому сделать более грамотно,

будем учитывать все что накапало не суммарно за месяц а ежедневно.

1 процессорное время общее cpu.
2 процессорное время mysql.
3 суммарное количество http запросов.

будет 2 лимита:

1 мягкий по тарифу - если превышение периодическое то блокировать, если не регулярное то не трогать.
2 лимит жесткий - если превышен то немедленно блокировать.

Еще нужно проверять процессы пользователя и завершать их если они жрут cpu более X процентов за Y времени, если переодически то блокировать.

у меня логика, такая
смотрим предыдущий день, если есть превышения, смотрим неделю.
если есть превышения и там и там, - лочим.
настривается практически всё, щас ещё впиливаю создание тикетов, при блокировке...
--
а как 2 и 3 штатно считаешь? или нештаттно?

Re: ISP Блокируем пользователей за перерасход CPU

Добавлено: 2013-03-16 7:18:13
rootden
штатно не выйдет,вместо mysql будем ставить Percona и делать базу со статистикой.

http статистика в новых версиях isp появилась, но она я так понимаю тока apache логи смотрит, а нада полные логи запросов, так что тоже не штатно.