"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 }