"Fossies" - the Fresh Open Source Software Archive

Member "fogproject-1.5.9/packages/web/lib/service/multicastmanager.class.php" (13 Sep 2020, 25409 Bytes) of package /linux/misc/fogproject-1.5.9.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) PHP source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. See also the latest Fossies "Diffs" side-by-side code changes report for "multicastmanager.class.php": 1.5.8_vs_1.5.9.

    1 <?php
    2 /**
    3  * The multicast manager service
    4  *
    5  * PHP version 5
    6  *
    7  * @category MulticastManager
    8  * @package  FOGProject
    9  * @author   Tom Elliott <tommygunsster@gmail.com>
   10  * @license  http://opensource.org/licenses/gpl-3.0 GPLv3
   11  * @link     https://fogproject.org
   12  */
   13 /**
   14  * The multicast manager service
   15  *
   16  * @category MulticastManager
   17  * @package  FOGProject
   18  * @author   Tom Elliott <tommygunsster@gmail.com>
   19  * @license  http://opensource.org/licenses/gpl-3.0 GPLv3
   20  * @link     https://fogproject.org
   21  */
   22 class MulticastManager extends FOGService
   23 {
   24     /**
   25      * Is the host lookup/ping enabled
   26      *
   27      * @var int
   28      */
   29     private static $_mcOn = 0;
   30     /**
   31      * Where to get the services sleeptime
   32      *
   33      * @var string
   34      */
   35     public static $sleeptime = 'MULTICASTSLEEPTIME';
   36     /**
   37      * Alternate log -- the multicast running udpcast
   38      *
   39      * @var string
   40      */
   41     protected $altLog;
   42     /**
   43      * Initializes the MulticastManager class
   44      *
   45      * @return void
   46      */
   47     public function __construct()
   48     {
   49         parent::__construct();
   50         list(
   51             $dev,
   52             $log,
   53             $zzz
   54         ) = self::getSubObjectIDs(
   55             'Service',
   56             array(
   57                 'name' => array(
   58                     'MULTICASTDEVICEOUTPUT',
   59                     'MULTICASTLOGFILENAME',
   60                     self::$sleeptime
   61                 )
   62             ),
   63             'value',
   64             false,
   65             'AND',
   66             'name',
   67             false,
   68             ''
   69         );
   70         static::$log = sprintf(
   71             '%s%s',
   72             (
   73                 self::$logpath ?
   74                 self::$logpath :
   75                 '/opt/fog/log/'
   76             ),
   77             (
   78                 $log ?
   79                 $log :
   80                 'multicast.log'
   81             )
   82         );
   83         if (file_exists(static::$log)) {
   84             unlink(static::$log);
   85         }
   86         static::$dev = (
   87             $dev ?
   88             $dev :
   89             '/dev/tty2'
   90         );
   91         static::$zzz = (
   92             $zzz ?
   93             $zzz :
   94             10
   95         );
   96     }
   97     /**
   98      * Tests if the multicast task is new
   99      *
  100      * @param array $KnownTasks the known tasks
  101      * @param int   $id         test if the id is new
  102      *
  103      * @return bool
  104      */
  105     private static function _isMCTaskInList(
  106         $Tasks,
  107         $id
  108     ) {
  109         if (count($Tasks) < 1) {
  110             return false;
  111         }
  112         foreach ((array)$Tasks as &$Task) {
  113             if ($Task->getID() == $id) {
  114                 return true;
  115             }
  116             unset($Task);
  117         }
  118         return false;
  119     }
  120     /**
  121      * Gets the multicast task
  122      *
  123      * @param array $KnownTasks the known tasks
  124      * @param int   $id         the id to get
  125      *
  126      * @return object
  127      */
  128     private static function _getMCExistingTask(
  129         $KnownTasks,
  130         $curTask
  131     ) {
  132         foreach ((array)$KnownTasks as &$Known) {
  133             if ($Known->getID() == $curTask->getID()) {
  134                 // This is very important for MC session joins via PXE menu
  135                 $curTaskTaskIDs = $curTask->getTaskIDs();
  136                 if (count($curTaskTaskIDs) > count($Known->getTaskIDs())) {
  137                     $Known->setTaskIDs($curTaskTaskIDs);
  138                 }
  139                 return $Known;
  140             }
  141             unset($Known);
  142         }
  143         return false;
  144     }
  145     /**
  146      * Removes task from the known list
  147      *
  148      * @param array $KnownTasks the known tasks
  149      * @param int   $id         the id to removes
  150      *
  151      * @return array
  152      */
  153     private static function _removeFromKnownList(
  154         $KnownTasks,
  155         $id
  156     ) {
  157         $new = array();
  158         foreach ((array)$KnownTasks as &$Known) {
  159             if ($Known->getID() != $id) {
  160                 $new[] = $Known;
  161             }
  162             unset($Known);
  163         }
  164         unset($Known);
  165         return array_filter($new);
  166     }
  167     /**
  168      * Multicast tasks are a bit more than
  169      * the others, this is its service loop
  170      *
  171      * @return void
  172      */
  173     private function _serviceLoop()
  174     {
  175         $KnownTasks = [];
  176         $queueTasks = [];
  177         while (true) {
  178             // Ensure we have a fresh complete and cancel variable.
  179             $completeTasks = $cancelTasks = [];
  180 
  181             // Handles the sleep timer for us.
  182             $date = self::niceDate();
  183             if (!isset($nextrun)) {
  184                 $first = true;
  185                 $nextrun = clone $date;
  186             }
  187             // Actually holds and loops until the proper sleep time is met.
  188             if ($date < $nextrun && $first === false) {
  189                 usleep(100000);
  190                 continue;
  191             }
  192             // Check db connection and wait until db is ready.
  193             $this->waitDbReady();
  194 
  195             // Reset the next run time.
  196             $nextrun = self::niceDate();
  197             $nextrun->modify('+'.self::$zzz.' seconds');
  198 
  199             // Sets the queued States each iteration incase there is a change.
  200             $queuedStates = self::fastmerge(
  201                 self::getQueuedStates(),
  202                 (array)self::getProgressState()
  203             );
  204             // Sets the Done states each iteration incase there is a change.
  205             $doneStates = [
  206                 self::getCompleteState(),
  207                 self::getCancelledState()
  208             ];
  209 
  210             // Check if status changed.
  211             self::$_mcOn = self::getSetting('MULTICASTGLOBALENABLED');
  212 
  213             try {
  214                 // If disabled, state and restart loop.
  215                 if (self::$_mcOn < 1) {
  216                     throw new Exception(
  217                         _(' * Multicast service is globally disabled')
  218                     );
  219                 }
  220 
  221                 // Common string used for logging.
  222                 $startStr = ' | ' . _('Task ID') . ': %s '. _('Name') . ': %s %s';
  223 
  224                 foreach ($this->checkIfNodeMaster() as &$StorageNode) {
  225                     // Now that tasks are removed, lets check new/current tasks
  226                     $allTasks = MulticastTask::getAllMulticastTasks(
  227                         $StorageNode->get('path'),
  228                         $StorageNode->get('id'),
  229                         $queuedStates
  230                     );
  231                     $taskCount = count($allTasks ?: []);
  232                     if ($taskCount < 1) {
  233                         self::outall(
  234                             ' * ' . _('No new tasks found')
  235                         );
  236                         continue;
  237                     }
  238 
  239                     foreach ($allTasks as &$curTask) {
  240                         $totalSlots = $StorageNode->get('maxClients');
  241                         $usedSlots = $StorageNode->getUsedSlotCount();
  242                         $queuedSlots = $StorageNode->getQueuedSlotCount();
  243                         $groupOpenSlots = $totalSlots - $usedSlots;
  244 
  245                         $existing = self::_isMCTaskInList(
  246                             $KnownTasks,
  247                             $curTask->getID()
  248                         );
  249                         $queued = self::_isMCTaskInList(
  250                             $queueTasks,
  251                             $curTask->getID()
  252                         );
  253 
  254                         if (!$existing) {
  255                             if ($groupOpenSlots < 1) {
  256                                 if ($queued) {
  257                                     continue;
  258                                 }
  259                                 self::outall(
  260                                     sprintf(
  261                                         $startStr,
  262                                         $curTask->getID(),
  263                                         $curTask->getName(),
  264                                         _(' No open slots ')
  265                                     )
  266                                 );
  267                                 $curTask->getSess()->set('stateID', 1);
  268                                 if (!$curTask->getSess()->save()) {
  269                                     throw new Exception(_('Failed to update Task'));
  270                                 } else {
  271                                     self::outall(
  272                                         sprintf(
  273                                             $startStr,
  274                                             $curTask->getID(),
  275                                             $curTask->getName(),
  276                                             _(' Task state has been updated, now the task is queued!')
  277                                         )
  278                                     );
  279                                 }
  280                                 $queueTasks[] = $curTask;
  281                                 continue;
  282                             }
  283                             if (!file_exists($curTask->getImagePath())) {
  284                                 self::outall(
  285                                     sprintf(
  286                                         $startStr,
  287                                         $curTask->getID(),
  288                                         $curTask->getName(),
  289                                         _('failed to execute, image file: ')
  290                                         . $curTask->getImagePath()
  291                                         . _('not found on this node')
  292                                     )
  293                                 );
  294                                 continue;
  295                             }
  296                             if (!$curTask->getClientCount()) {
  297                                 self::outall(
  298                                     sprintf(
  299                                         $startStr,
  300                                         $curTask->getID(),
  301                                         $curTask->getName(),
  302                                         _('failed to execute, there are no clients included')
  303                                     )
  304                                 );
  305                                 continue;
  306                             }
  307                             if (!is_numeric($curTask->getPortBase())
  308                                 || !($curTask->getPortBase() % 2 == 0)
  309                             ) {
  310                                 self::outall(
  311                                     sprintf(
  312                                         $startStr,
  313                                         $curTask->getID(),
  314                                         $curTask->getName(),
  315                                         _('failed to execute, port must be even and numeric')
  316                                     )
  317                                 );
  318                                 continue;
  319                             }
  320 
  321                             if (!$curTask->startTask()) {
  322                                 self::outall(
  323                                     sprintf(
  324                                         $startStr,
  325                                         $curTask->getID(),
  326                                         $curTask->getName(),
  327                                         _('failed to start')
  328                                     )
  329                                 );
  330                                 if (!$curTask->killTask()) {
  331                                     self::outall(
  332                                         sprintf(
  333                                             $startStr,
  334                                             $curTask->getID(),
  335                                             $curTask->getName(),
  336                                             _('could not be killed')
  337                                         )
  338                                     );
  339                                 } else {
  340                                     self::outall(
  341                                         sprintf(
  342                                             $startStr,
  343                                             $curTask->getID(),
  344                                             $curTask->getName(),
  345                                             _('has been killed')
  346                                         )
  347                                     );
  348                                 }
  349                                 continue;
  350                             }
  351                             if ($queued) {
  352                                 $queueTasks = self::_removeFromKnownList(
  353                                     $queueTasks,
  354                                     $curTask->getID()
  355                                 );
  356                             }
  357                             $KnownTasks[] = $curTask;
  358                             self::outall(
  359                                 sprintf(
  360                                     $startStr,
  361                                     $curTask->getID(),
  362                                     $curTask->getName(),
  363                                     _('is new')
  364                                 )
  365                             );
  366                             $Session = $curTask->getSess();
  367                             $Session->set('stateID', self::getProgressState());
  368                             if (!$Session->save()) {
  369                                 self::outall(
  370                                     sprintf(
  371                                         $startStr,
  372                                         $curTask->getID(),
  373                                         $curTask->getName(),
  374                                         _('unable to be updated')
  375                                     )
  376                                 );
  377                                 continue;
  378                             }
  379                             self::outall(
  380                                 sprintf(
  381                                     $startStr,
  382                                     $curTask->getID(),
  383                                     $curTask->getName(),
  384                                     _('image file found, file: ')
  385                                     . $curTask->getImagePath()
  386                                 )
  387                             );
  388                             self::outall(
  389                                 sprintf(
  390                                     $startStr,
  391                                     $curTask->getID(),
  392                                     $curTask->getName(),
  393                                     $curTask->getClientCount()
  394                                     . ' '
  395                                     . (
  396                                         $curTask->getClientCount() == 1 ?
  397                                         _('client') :
  398                                         _('clients')
  399                                     )
  400                                     . ' '
  401                                     . _('found')
  402                                 )
  403                             );
  404                             self::outall(
  405                                 sprintf(
  406                                     $startStr,
  407                                     $curTask->getID(),
  408                                     $curTask->getName(),
  409                                     _('sending on base port ')
  410                                     . $curTask->getPortBase()
  411                                 )
  412                             );
  413                             self::outall(
  414                                 sprintf(
  415                                     " | %s: %s",
  416                                     _('Command'),
  417                                     $curTask->getCMD()
  418                                 )
  419                             );
  420                             self::outall(
  421                                 sprintf(
  422                                     $startStr,
  423                                     $curTask->getID(),
  424                                     $curTask->getName(),
  425                                     _('has started')
  426                                 )
  427                             );
  428                             continue;
  429                         }
  430                         $jobcancelled = $jobcompleted = false;
  431                         $runningTask = self::_getMCExistingTask(
  432                             $KnownTasks,
  433                             $curTask
  434                         );
  435 
  436                         $taskIDs = $runningTask->getTaskIDs();
  437                         $find = [];
  438                         $find['id'] = $taskIDs;
  439                         $find['stateID'] = self::getCancelledState();
  440                         Route::ids(
  441                             'task',
  442                             $find
  443                         );
  444                         $inTaskCancelledIDs = json_decode(Route::getData(), true);
  445                         $find['stateID'] = self::getCompleteState();
  446                         Route::ids(
  447                             'task',
  448                             $find
  449                         );
  450                         $inTaskCompletedIDs = json_decode(Route::getData(), true);
  451                         $Session = $runningTask->getSess();
  452 
  453                         if ($Session->get('stateID') != $curTask->getSess()->get('stateID')) {
  454                             $Session->set('stateID', $curTask->getSess()->get('stateID'));
  455                             if (!$Session->save()) {
  456                                 self::outall(
  457                                     sprintf(
  458                                         $startStr,
  459                                         $curTask->getID(),
  460                                         $curTask->getName(),
  461                                         _('unable to be updated')
  462                                     )
  463                                 );
  464                             }
  465                         }
  466 
  467                         $SessCancelled = $Session->get('stateID')
  468                             == self::getCancelledState();
  469                         $SessCompleted = $Session->get('stateID')
  470                             == self::getCompleteState();
  471                         if ($SessCancelled
  472                             || count($inTaskCancelledIDs) > 0
  473                         ) {
  474                             $jobcancelled = true;
  475                         }
  476                         if ($SessCompleted
  477                             || (count($inTaskCompletedIDs) > 0 && count($inTaskCompletedIDs) >= count($taskIDs))
  478                             || ($runningTask->isNamedSessionFinished())
  479                         ) {
  480                             $jobcompleted = true;
  481                         }
  482 
  483                         if (!$jobcancelled && !$jobcompleted) {
  484                             if ($runningTask->isRunning($runningTask->procRef)) {
  485                                 self::outall(
  486                                     sprintf(
  487                                         $startStr,
  488                                         $runningTask->getID(),
  489                                         $runningTask->getName(),
  490                                         _('is already running with pid: ')
  491                                         . $runningTask->getPID($runningTask->procRef)
  492                                     )
  493                                 );
  494 
  495                                 $runningTask->updateStats();
  496                             } else {
  497                                 self::outall(
  498                                     sprintf(
  499                                         $startStr,
  500                                         $runningTask->getID(),
  501                                         $runningTask->getName(),
  502                                         _('is no longer running')
  503                                     )
  504                                 );
  505                                 if (!$runningTask->killTask()) {
  506                                     self::outall(
  507                                         sprintf(
  508                                             $startStr,
  509                                             $runningTask->getID(),
  510                                             $runningTask->getName(),
  511                                             _('could not be killed')
  512                                         )
  513                                     );
  514                                 }
  515                                 // Set msClients to zero as a marker for a completed
  516                                 // multicast session with unregistered clients
  517                                 if (count($taskIDs) == 0) {
  518                                     $Session->set('clients', 0)->save();
  519                                 }
  520                             }
  521                         } else {
  522                             if ($jobcompleted) {
  523                                 self::outall(
  524                                     sprintf(
  525                                         $startStr,
  526                                         $runningTask->getID(),
  527                                         $runningTask->getName(),
  528                                         _('has been completed')
  529                                     )
  530                                 );
  531                                 $completeTasks[] = $runningTask;
  532                             }
  533                             if ($jobcancelled) {
  534                                 self::outall(
  535                                     sprintf(
  536                                         $startStr,
  537                                         $runningTask->getID(),
  538                                         $runningTask->getName(),
  539                                         _('has been cancelled')
  540                                     )
  541                                 );
  542                                 $cancelTasks[] = $runningTask;
  543                             } else {
  544                                 if (!$runningTask->killTask()) {
  545                                     self::outall(
  546                                         sprintf(
  547                                             $startStr,
  548                                             $runningTask->getID(),
  549                                             $runningTask->getName(),
  550                                             _('could not be killed')
  551                                         )
  552                                     );
  553                                 } else {
  554                                     self::outall(
  555                                         sprintf(
  556                                             $startStr,
  557                                             $runningTask->getID(),
  558                                             $runningTask->getName(),
  559                                             _('has been killed')
  560                                         )
  561                                     );
  562                                     $KnownTasks = self::_removeFromKnownList(
  563                                         $KnownTasks,
  564                                         $runningTask->getID()
  565                                     );
  566                                 }
  567                             }
  568                         }
  569                         unset($curTask);
  570                         unset($runningTask);
  571                     }
  572                     unset($StorageNode);
  573                 }
  574                 // We need to iterate the complete and cancelTasks
  575                 foreach ($cancelTasks as &$Task) {
  576                     $Session = $Task->getSess();
  577                     self::outall(
  578                         sprintf(
  579                             $startStr,
  580                             $Task->getID(),
  581                             $Task->getName(),
  582                             (
  583                                 $Session->cancel() ?
  584                                 _('is now cancelled') :
  585                                 _('could not be cancelled')
  586                             )
  587                         )
  588                     );
  589                     unset($Task);
  590                 }
  591                 foreach ($completeTasks as &$Task) {
  592                     $Session = $Task->getSess();
  593                     self::outall(
  594                         sprintf(
  595                             $startStr,
  596                             $Task->getID(),
  597                             $Task->getName(),
  598                             (
  599                                 $Session->complete() ?
  600                                 _('is now completed') :
  601                                 _('could not be completed')
  602                             )
  603                         )
  604                     );
  605                     unset($Task);
  606                 }
  607             } catch (Exception $e) {
  608                 self::outall($e->getMessage());
  609             }
  610             if ($first) {
  611                 $first = false;
  612             }
  613             $tmpTime = self::getSetting(self::$sleeptime);
  614             if ($tmpTime > 0 && static::$zzz != $tmpTime) {
  615                 static::$zzz = $tmpTime ?: 10;
  616                 self::outall(
  617                     sprintf(
  618                         ' | %s %s %s.',
  619                         _('Wait time has changed to'),
  620                         static::$zzz,
  621                         (
  622                             static::$zzz != 1 ?
  623                             _('seconds') :
  624                             _('second')
  625                         )
  626                     )
  627                 );
  628             }
  629         }
  630     }
  631     /**
  632      * This is what essentially "runs" the service
  633      *
  634      * @return void
  635      */
  636     public function serviceRun()
  637     {
  638         $this->_serviceLoop();
  639     }
  640 }