1<?php
2/*****************************************************************************
3 *
4 * CoreBackendMgmt.php - class for handling all backends
5 *
6 * Copyright (c) 2004-2016 NagVis Project (Contact: info@nagvis.org)
7 *
8 * License:
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 *
23 *****************************************************************************/
24
25/**
26 * @author	Lars Michelsen <lm@larsmichelsen.com>
27 */
28class CoreBackendMgmt {
29    public $BACKENDS = Array();
30    private $aInitialized = Array();
31    private $aQueue = Array();
32    private $aError = Array();
33    private $countQueries = Array(
34        'serviceState'            => '',
35        'hostState'               => '',
36        'hostMemberState'         => '',
37        'hostgroupMemberState'    => '',
38        'servicegroupMemberState' => '',
39        'DYN_GROUP_MEMBER_STATE'  => '',
40    );
41
42
43    /**
44     * Constructor
45     *
46     * Initializes all backends
47     *
48     * @param   config  $MAINCFG
49     * @author  Lars Michelsen <lm@larsmichelsen.com>
50     */
51    public function __construct() {
52        $this->loadBackends();
53    }
54
55    public function getBackend($id) {
56        // Only try to initialize once per request
57        if(!isset($this->aInitialized[$id]) && !isset($this->aError[$id]))
58            $this->initializeBackend($id);
59
60        // Re-throw the stored backend exception for this request
61        if(isset($this->aError[$id]))
62            throw $this->aError[$id];
63
64        return $this->BACKENDS[$id];
65    }
66
67    /**
68     * PUBLIC queue()
69     *
70     * Add a backend query to the queue
71     *
72     * @param   Array   Queries to be added to the queue
73     * @param   Object  Map object to fetch the informations for
74     * @author  Lars Michelsen <lm@larsmichelsen.com>
75     */
76    public function queue($query, $OBJ) {
77        $backendIds = $OBJ->getBackendIds();
78        foreach($backendIds as $backendId)
79            if(!isset($this->aQueue[$backendId]))
80                $this->aQueue[$backendId] = Array();
81
82        foreach($query AS $query => $_unused) {
83            foreach($backendIds as $backendId)
84                if(!isset($this->aQueue[$backendId][$query]))
85                    $this->aQueue[$backendId][$query] = Array();
86
87            // Gather the object name
88            if($query == 'serviceState')
89                $name = $OBJ->getName().'~~'.$OBJ->getServiceDescription();
90            else
91                $name = $OBJ->getName();
92
93            // Options is a mask which tells the backend how to handle this object
94            $options = $this->parseOptions($OBJ);
95
96            // Each object can have individual filter options. For example the
97            // member filters
98            $objFilters = $this->parseObjFilters($query, $OBJ);
99
100            // Only query the backend once per object+options+filter
101            // If the object is queued several times with the same options+filters
102            // add it to the list of objects. The backend result will be added to
103            // all objects in that list later
104            foreach($backendIds as $backendId)
105                if(!isset($this->aQueue[$backendId][$query][$options][$objFilters]))
106                    $this->aQueue[$backendId][$query][$options][$objFilters] = Array($name => Array($OBJ));
107                elseif(!isset($this->aQueue[$backendId][$query][$options][$objFilters][$name]))
108                    $this->aQueue[$backendId][$query][$options][$objFilters][$name] = Array($OBJ);
109                else
110                    $this->aQueue[$backendId][$query][$options][$objFilters][$name][] = $OBJ;
111        }
112    }
113
114    private function parseObjFilters($query, $OBJ) {
115        $isMemberQuery = $query != 'serviceState' && $query != 'hostState';
116        $isCountQuery = isset($this->countQueries[$query]);
117
118        if(!$isMemberQuery || !$OBJ->hasExcludeFilters($isCountQuery))
119            return '';
120
121        return $OBJ->getExcludeFilterKey($isCountQuery).'~~'.$OBJ->getExcludeFilter($isCountQuery);
122    }
123
124    private function parseOptions($OBJ) {
125        $options = 0;
126        if($OBJ->getOnlyHardStates())
127            $options |= 1;
128        if(!$OBJ->getRecognizeServices())
129            $options |= 2;
130        /*FIXME: Implement as optional filter: "Filter: in_notification_period = 1\n" .*/
131
132        return $options;
133    }
134
135    /**
136     * PUBLIC clearQueue()
137     *
138     * Resets the backend queue
139     *
140     * @author  Lars Michelsen <lm@larsmichelsen.com>
141     */
142    public function clearQueue() {
143        $this->aQueue = Array();
144    }
145
146    /**
147     * PUBLIC execute()
148     *
149     * Executes all backend queries and assigns the gathered information
150     * to the objects
151     *
152     * @author  Lars Michelsen <lm@larsmichelsen.com>
153     */
154    public function execute() {
155        // Loop all backends
156        foreach($this->aQueue AS $backendId => $types) {
157            // Loop all different query types
158            foreach($types AS $type => $options) {
159                // Now loop the different options (Splitting by only_hard_state options etc.)
160                foreach($options AS $option => $filters) {
161                    foreach($filters AS $filter => $aObjs) {
162                        switch($type) {
163                            case 'serviceState':
164                            case 'hostState':
165                            case 'hostMemberState':
166                            case 'hostgroupMemberState':
167                            case 'servicegroupMemberState':
168                            case 'AGGR_MEMBER_STATE':
169                                $this->fetchStateCounts($backendId, $type, $option, $aObjs);
170                            break;
171                            case 'DYN_GROUP_MEMBER_STATE':
172                                // Can not use the generic fetchStateCounts() method. It uses summarized queries
173                                // to reduce the number of backend queries, but this is not possible for member
174                                // states as this makes use of individual filter queries per objects.
175                                $this->fetchDynGroupMemberCounts($backendId, $option, $aObjs);
176                            break;
177
178                            case 'hostMemberDetails':
179                                $this->fetchHostMemberDetails($backendId, $option, $aObjs);
180                            break;
181                            case 'hostgroupMemberDetails':
182                                $this->fetchHostgroupMemberDetails($backendId, $option, $aObjs);
183                            break;
184                            case 'servicegroupMemberDetails':
185                                $this->fetchServicegroupMemberDetails($backendId, $option, $aObjs);
186                            break;
187                            case 'DYN_GROUP_MEMBER_DETAILS':
188                                $this->fetchDynGroupMemberDetails($backendId, $option, $aObjs);
189                            break;
190                            case 'AGGR_MEMBER_DETAILS':
191                                $this->fetchAggrMemberDetails($backendId, $option, $aObjs);
192                            break;
193                        }
194                    }
195                }
196            }
197        }
198
199        // Clear the queue after processing
200        $this->clearQueue();
201    }
202
203    /**
204     * Loops all queued aggregation and executes the queries for each group.
205     * Gets all members of the aggregation and saves them to the members array
206     *
207     * This is trimmed to reduce the number of queries to the backend:
208     * 1.) fetch states for all objects
209     * 2.) fetch state counts for all objects
210     */
211    private function fetchAggrMemberDetails($backendId, $options, $aObjs) {
212        foreach($aObjs AS $name => $OBJS) {
213            foreach($OBJS AS $OBJ) {
214                try {
215                    $filters = Array(Array('key' => 'aggr_name', 'op' => '>=', 'val' => 'name'));
216                    $aServices = $this->getBackend($backendId)->getServiceState(Array($OBJ->getName() => Array($OBJ)), $options, $filters, MEMBER_QUERY);
217                } catch(BackendException $e) {
218                    $aServices = Array();
219                    $OBJ->setBackendProblem(l('Connection Problem (Backend: [BACKENDID]): [MSG]',
220                              Array('BACKENDID' => $backendId, 'MSG' => $e->getMessage())), $backendId);
221                }
222
223                // Regular member adding loop
224                $members = Array();
225                foreach($aServices AS $host => $serviceList) {
226                    foreach($serviceList AS $aService) {
227                        $members[] = $this->createServiceObject($backendId, $host, $aService[DESCRIPTION],
228                                                                $aService, $OBJ->getObjectConfiguration());
229                    }
230                }
231                $OBJ->addMembers($members);
232            }
233        }
234    }
235
236    private function fetchDynGroupMemberCounts($backendId, $options, $aObjs) {
237        foreach($aObjs AS $name => $OBJS) {
238            foreach($OBJS AS $OBJ) {
239                try {
240                    if($OBJ->object_types == 'service') {
241                        if (!$this->checkBackendFeature($backendId, 'getServiceListCounts', false)) {
242                            $counts = array();
243                            $OBJ->setBackendProblem(l('This type of object is not supportd by this backend ([BACKENDID]).',
244                                  Array('BACKENDID' => $backendId)), $backendId);
245                        }
246                        else {
247                            $counts = $this->getBackend($backendId)->getServiceListCounts(
248                                    $options, $OBJ->getObjectFilter());
249                        }
250                    } else {
251                        if (!$this->checkBackendFeature($backendId, 'getHostAndServiceCounts', false)) {
252                            $counts = array();
253                            $OBJ->setBackendProblem(l('This type of object is not supportd by this backend ([BACKENDID]).',
254                                  Array('BACKENDID' => $backendId)), $backendId);
255                        }
256                        else {
257                            $counts = $this->getBackend($backendId)->getHostAndServiceCounts(
258                                    $options, $OBJ->getObjectFilter(), $OBJ->getObjectFilter(), false);
259                        }
260                    }
261                } catch(BackendException $e) {
262                    $counts = Array();
263                    $OBJ->setBackendProblem(l('Connection Problem (Backend: [BACKENDID]): [MSG]',
264                              Array('BACKENDID' => $backendId, 'MSG' => $e->getMessage())), $backendId);
265                }
266
267                $OBJ->addStateCounts($counts);
268            }
269        }
270    }
271
272    /**
273     * Fetches details for all given dynamic groups
274     * Sending "array()" as filter construct to the backend since the backend uses the filters which are
275     * already compiled in the object and ignores the given array() parameter
276     */
277    private function fetchDynGroupMemberDetails($backendId, $options, $aObjs) {
278        foreach($aObjs AS $name => $OBJS) {
279            foreach($OBJS AS $OBJ) {
280                $members = Array();
281                if ($OBJ->object_types == 'service') {
282                    // Fist get the states for all the members
283                    try {
284                        $aServices = $this->getBackend($backendId)->getServiceState(
285                            Array($OBJ->getName() => Array($OBJ)), $options, array(), MEMBER_QUERY);
286                    } catch(BackendException $e) {
287                        $aServices = Array();
288                        $OBJ->setBackendProblem(l('Connection Problem (Backend: [BACKENDID]): [MSG]',
289                                  Array('BACKENDID' => $backendId, 'MSG' => $e->getMessage())), $backendId);
290                    }
291
292                    // Regular member adding loop
293                    foreach($aServices AS $host => $serviceList) {
294                        foreach($serviceList AS $aService) {
295                            $members[] = $this->createServiceObject($backendId, $host, $aService[DESCRIPTION],
296                                                                    $aService, $OBJ->getObjectConfiguration());
297                        }
298                    }
299
300                } else {
301                    // First get the host states
302                    try {
303                        $aHosts = $this->getBackend($backendId)->getHostState(Array($OBJ->getName() => Array($OBJ)),
304                                                                              $options, array(), MEMBER_QUERY);
305                    } catch(BackendException $e) {
306                        $aHosts = Array();
307                        $OBJ->setBackendProblem(l('Connection Problem (Backend: [BACKENDID]): [MSG]',
308                                               Array('BACKENDID' => $backendId, 'MSG' => $e->getMessage())), $backendId);
309                    }
310
311                    // Now fetch the service state counts for all hosts
312                    $aServiceState = Array();
313                    if($OBJ->getRecognizeServices()) {
314                        try {
315                            $aServiceStateCounts = $this->getBackend($backendId)->getHostMemberCounts(
316                                               Array($OBJ->getName() => Array($OBJ)), $options, array());
317                        } catch(BackendException $e) {}
318                    }
319
320                    $members = Array();
321                    foreach($aHosts AS $name => $aHost) {
322                        if(isset($aServiceStateCounts[$name]) && isset($aServiceStateCounts[$name]['counts']))
323                            $service_states = $aServiceStateCounts[$name]['counts'];
324                        else
325                            $service_states = null;
326                        $members[] = $this->createHostObject($backendId, $name, $aHost,
327                                                             $OBJ->getObjectConfiguration(), $service_states);
328                    }
329
330                }
331                $OBJ->addMembers($members);
332            }
333        }
334    }
335
336    private function createServiceObject($backendId, $host, $descr, $state, $config) {
337        $OBJ = new NagVisService($backendId, $host, $state[DESCRIPTION]);
338        $OBJ->setState($state);
339
340        // The services have to know how they should handle hard/soft
341        // states. This is a little dirty but the simplest way to do this
342        // until the hard/soft state handling has moved from backend to the
343        // object classes.
344        $OBJ->setConfiguration($config);
345        return $OBJ;
346    }
347
348    private function createHostObject($backendId, $name, $state, $config, $service_states) {
349        $OBJ = new NagVisHost($backendId, $name);
350        $OBJ->setState($state);
351
352        // The services have to know how they should handle hard/soft
353        // states. This is a little dirty but the simplest way to do this
354        // until the hard/soft state handling has moved from backend to the
355        // object classes.
356        $OBJ->setConfiguration($config);
357
358        // Put state counts to the object
359        if ($service_states !== null) {
360            $OBJ->addStateCounts($service_states);
361        }
362
363        // Fetch summary state and output
364        $OBJ->fetchSummariesFromCounts();
365
366        return $OBJ;
367    }
368
369    /**
370     * PRIVATE fetchServicegroupMemberDetails()
371     *
372     * Loops all queued servicegroups and executes the queries for each group.
373     * Gets all services of the servicegroup and saves them to the members array
374     *
375     * This is trimmed to reduce the number of queries to the backend:
376     * 1.) fetch states for all services
377     * 2.) fetch state counts for all services
378     *
379     * @author	Lars Michelsen <lm@larsmichelsen.com>
380     */
381    private function fetchServicegroupMemberDetails($backendId, $options, $aObjs) {
382        foreach($aObjs AS $name => $OBJS) {
383            foreach($OBJS AS $OBJ) {
384                // Fist get the host states for all the servicegroup members
385                try {
386                    $filters = Array(Array('key' => 'service_groups', 'op' => '>=', 'val' => 'name'));
387                    $aServices = $this->getBackend($backendId)->getServiceState(Array($OBJ->getName() => Array($OBJ)), $options, $filters, MEMBER_QUERY);
388                } catch(BackendException $e) {
389                    $aServices = Array();
390                    $OBJ->setBackendProblem(l('Connection Problem (Backend: [BACKENDID]): [MSG]',
391                              Array('BACKENDID' => $backendId, 'MSG' => $e->getMessage())), $backendId);
392                }
393
394                // Regular member adding loop
395                $members = Array();
396                foreach($aServices AS $host => $serviceList) {
397                    foreach($serviceList AS $aService) {
398                        $members[] = $this->createServiceObject($backendId, $host, $aService[DESCRIPTION],
399                                                                $aService, $OBJ->getObjectConfiguration());
400                    }
401                }
402                $OBJ->addMembers($members);
403            }
404        }
405    }
406
407    /**
408     * PRIVATE fetchHostgroupMemberDetails()
409     *
410     * Loops all queued objects.
411     * Gets all hosts of the hostgroup and saves them to the members array
412     *
413     * This is trimmed to reduce the number of queries to the backend:
414     * 1.) fetch states for all hosts
415     * 2.) fetch state counts for all hosts
416     *
417     * @author	Lars Michelsen <lm@larsmichelsen.com>
418     */
419    private function fetchHostgroupMemberDetails($backendId, $options, $aObjs) {
420        // And then apply them to the objects
421        foreach($aObjs AS $name => $OBJS) {
422            foreach($OBJS AS $OBJ) {
423                // First get the host states for all the hostgroup members
424                try {
425                    $filters = Array(Array('key' => 'host_groups', 'op' => '>=', 'val' => 'name'));
426                    $aHosts = $this->getBackend($backendId)->getHostState(Array($OBJ->getName() => Array($OBJ)), $options, $filters, MEMBER_QUERY);
427                } catch(BackendException $e) {
428                    $aHosts = Array();
429                    $OBJ->setBackendProblem(l('Connection Problem (Backend: [BACKENDID]): [MSG]',
430                                           Array('BACKENDID' => $backendId, 'MSG' => $e->getMessage())), $backendId);
431                }
432
433                // Now fetch the service state counts for all hostgroup members
434                $aServiceState = Array();
435                if($OBJ->getRecognizeServices()) {
436                    try {
437                        $filters = Array(Array('key' => 'host_groups', 'op' => '>=', 'val' => 'name'));
438                        $aServiceStateCounts = $this->getBackend($backendId)->getHostMemberCounts(
439                                           Array($OBJ->getName() => Array($OBJ)), $options, $filters);
440                    } catch(BackendException $e) {}
441                }
442
443                $members = Array();
444                foreach($aHosts AS $name => $aHost) {
445                    if(isset($aServiceStateCounts[$name]) && isset($aServiceStateCounts[$name]['counts']))
446                        $service_states = $aServiceStateCounts[$name]['counts'];
447                    else
448                        $service_states = null;
449                    $members[] = $this->createHostObject($backendId, $name, $aHost,
450                                                         $OBJ->getObjectConfiguration(), $service_states);
451                }
452
453                $OBJ->addMembers($members);
454            }
455        }
456    }
457
458    private function fetchStateCounts($backendId, $type, $options, $aObjs) {
459        try {
460            switch($type) {
461                case 'servicegroupMemberState':
462                    $filters = Array(Array('key' => 'groups', 'op' => '>=', 'val' => 'name'));
463                    $aResult = $this->getBackend($backendId)->getServicegroupStateCounts($aObjs, $options, $filters);
464                break;
465                case 'hostgroupMemberState':
466                    $filters = Array(Array('key' => 'groups', 'op' => '>=', 'val' => 'name'));
467                    $aResult = $this->getBackend($backendId)->getHostgroupStateCounts($aObjs, $options, $filters);
468                break;
469                case 'serviceState':
470                    $filters = Array(
471                        Array('key' => 'host_name', 'op' => '=', 'val' => 'name'),
472                        Array('key' => 'service_description', 'op' => '=', 'service_description')
473                    );
474                    $aResult = $this->getBackend($backendId)->getServiceState($aObjs, $options, $filters);
475                break;
476                case 'hostState':
477                    $filters = Array(Array('key' => 'host_name', 'op' => '=', 'val' => 'name'));
478                    $aResult = $this->getBackend($backendId)->getHostState($aObjs, $options, $filters);
479                break;
480                case 'hostMemberState':
481                    $filters = Array(Array('key' => 'host_name', 'op' => '=', 'val' => 'name'));
482                    $aResult = $this->getBackend($backendId)->getHostMemberCounts($aObjs, $options, $filters);
483                break;
484                case 'AGGR_MEMBER_STATE':
485                    if (!$this->checkBackendFeature($backendId, 'getAggrStateCounts', false)) {
486                        throw new BackendException(l('This type of object is not supported by this backend ([BACKENDID]).',
487                              Array('BACKENDID' => $backendId)), $backendId);
488                    } else {
489                        $filters = Array(Array('key' => 'aggr_name', 'op' => '=', 'val' => 'name'));
490                        $aResult = $this->getBackend($backendId)->getAggrStateCounts($aObjs, $options, $filters);
491                    }
492                break;
493            }
494        } catch(BackendException $e) {
495            $aResult = Array();
496            $msg = $e->getMessage();
497        }
498
499        foreach($aObjs AS $name => $OBJS) {
500            if(isset($aResult[$name])) {
501                if($type == 'serviceState' || $type == 'hostState')
502                    foreach($OBJS AS $OBJ)
503                        $OBJ->setState($aResult[$name]);
504                else
505                    foreach($OBJS AS $OBJ) {
506                        if(isset($aResult[$name]['details']))
507                            $OBJ->setState($aResult[$name]['details']);
508                        if(isset($aResult[$name]['attrs']))
509                            $OBJ->setObjectInformation($aResult[$name]['attrs']);
510                        if(isset($aResult[$name]['counts']))
511                            $OBJ->addStateCounts($aResult[$name]['counts']);
512                    }
513            } else {
514                if($type != 'hostMemberState')
515                    foreach($OBJS AS $OBJ)
516                        if(isset($msg))
517                            $OBJ->setBackendProblem($msg, $backendId);
518                        else
519                            $OBJ->setBackendProblem(l('The object "[OBJ]" does not exist ([TYPE]).',
520                                                    Array('OBJ' => $name, 'TYPE' => $OBJ->getType())), $backendId);
521            }
522        }
523    }
524
525    private function fetchHostMemberDetails($backendId, $options, $aObjs) {
526        try {
527            $filters = Array(Array('key' => 'host_name', 'op' => '=', 'val' => 'name'));
528            $aMembers = $this->getBackend($backendId)->getServiceState($aObjs, $options, $filters, MEMBER_QUERY);
529        } catch(BackendException $e) {
530            $aMembers = Array();
531        }
532
533        foreach($aObjs AS $name => $OBJS) {
534            if(isset($aMembers[$name])) {
535                foreach($OBJS AS $OBJ) {
536                    $members = Array();
537                    foreach($aMembers[$name] AS $service => $details) {
538                        $MOBJ = new NagVisService($backendId, $OBJ->getName(), $details[DESCRIPTION]);
539                        $MOBJ->setState($details);
540                        $members[] = $MOBJ;
541                    }
542                    $OBJ->addMembers($members);
543                }
544            }
545        }
546    }
547
548    /**
549     * Loads all backends and prints an error when no backend defined
550     *
551     * @author 	Lars Michelsen <lm@larsmichelsen.com>
552     */
553    private function loadBackends() {
554        global $CORE;
555        $aBackends = $CORE->getDefinedBackends();
556
557        if(!count($aBackends))
558            throw new NagVisException(l('noBackendDefined'));
559    }
560
561    /**
562     * Checks for existing backend file
563     *
564     * @param	Boolean $printErr
565     * @return	Boolean	Is Successful?
566     * @author 	Lars Michelsen <lm@larsmichelsen.com>
567     */
568    public function checkBackendExists($backendId, $printErr) {
569        global $CORE;
570        if($CORE->checkExisting(cfg('paths','class').'GlobalBackend'.cfg('backend_'.$backendId,'backendtype').'.php', false))
571            return true;
572
573        if($printErr == 1)
574            throw new NagVisException(l('backendNotExists', Array('BACKENDID'   => $backendId,
575                                                                  'BACKENDTYPE' => cfg('backend_'.$backendId,'backendtype'))));
576        return false;
577    }
578
579    /**
580     * Checks if a backend host is status using status
581   * information from another backend
582     *
583     * @author 	Lars Michelsen <lm@larsmichelsen.com>
584     */
585    private function backendAlive($backendId, $statusHost) {
586        list($statusBackend, $statusHost) = explode(':', $statusHost, 2);
587
588        if($statusBackend == $backendId)
589            $this->aError[$backendId] = new BackendConnectionProblem(l('Configuration Error: The statusHost ([STATUSHOST]) is in same backend as the one to check.', Array('STATUSHOST' => $statusHost)));
590
591        try {
592            $filters = Array(Array('key' => 'host_name', 'op' => '=', 'val' => 'name'));
593            $aObjs = Array($statusHost => Array(new NagVisHost($statusBackend, $statusHost)));
594            $aCounts = $this->getBackend($statusBackend)->getHostState($aObjs, 1, $filters);
595        } catch(BackendException $e) {
596            return true;
597        }
598
599        if($aCounts[$statusHost][STATE] == UP)
600            return true;
601        else
602            return false;
603    }
604
605    /**
606     * Initializes a backend
607     *
608     * @return	Boolean	Is Successful?
609     * @author 	Lars Michelsen <lm@larsmichelsen.com>
610     */
611    private function initializeBackend($backendId) {
612        if(!$this->checkBackendExists($backendId, false)) {
613            $this->aError[$backendId] = new BackendConnectionProblem(l('backendNotDefined',
614                                            Array('BACKENDID'   => $backendId)));
615            return false;
616        }
617        /**
618         * The status host can be used to prevent annoying timeouts when a backend is not
619         * reachable. This is only useful in multi backend setups.
620         *
621         * It works as follows: The assumption is that there is a "local" backend which
622         * monitors the host of the "remote" backend. When the remote backend host is
623         * reported as UP the backend is queried as normal.
624         * When the remote backend host is reported as "DOWN" or "UNREACHABLE" NagVis won't
625         * try to connect to the backend anymore until the backend host gets available again.
626         */
627        $statusHost = cfg('backend_' . $backendId, 'statushost');
628        if($statusHost != '' && !$this->backendAlive($backendId, $statusHost)) {
629            $this->aError[$backendId] = new BackendConnectionProblem(l('The backend is reported as dead by the statusHost ([STATUSHOST]).', Array('STATUSHOST' => $statusHost)));
630            return false;
631        }
632
633        try {
634            $backendClass = 'GlobalBackend' . cfg('backend_' . $backendId, 'backendtype');
635            $this->BACKENDS[$backendId] = new $backendClass($backendId);
636
637            // Mark backend as initialized
638            $this->aInitialized[$backendId] = true;
639
640            return true;
641        } catch(BackendException $e) {
642            $this->aError[$backendId] = $e;
643            return false;
644        }
645    }
646
647    /**
648     * Checks for an initialized backend
649     *
650     * @param	Boolean $printErr
651     * @return	Boolean	Is Successful?
652     * @author 	Lars Michelsen <lm@larsmichelsen.com>
653     * @deprecated Please don't use this function anymore
654     */
655    public function checkBackendInitialized($backendId, $printErr) {
656        if(isset($this->aInitialized[$backendId])) {
657            return true;
658        } else {
659            if($printErr == 1) {
660                throw new NagVisException(l('backendNotInitialized', Array('BACKENDID' => $backendId,
661                    'BACKENDTYPE' => cfg('backend_'.$backendId,'backendtype'))));
662            }
663            return false;
664        }
665    }
666
667    /**
668     * Checks if the given feature is provided by the given backend
669     *
670     * @param	Boolean $printErr
671     * @return	Boolean	Is Successful?
672     * @author 	Lars Michelsen <lm@larsmichelsen.com>
673     */
674    public function checkBackendFeature($backendId, $feature, $printErr = 1) {
675        $backendClass = 'GlobalBackend'.cfg('backend_'.$backendId, 'backendtype');
676        if(method_exists($backendClass, $feature)) {
677            return true;
678        } else {
679            if($printErr == 1) {
680                throw new NagVisException(l('The requested feature [FEATURE] is not provided by the backend (Backend-ID: [BACKENDID], Backend-Type: [BACKENDTYPE]). The requested view may not be available using this backend.',
681                                          Array('FEATURE'     => htmlentities($feature, ENT_COMPAT, 'UTF-8'),
682                                                'BACKENDID'   => $backendId,
683                                                'BACKENDTYPE' => cfg('backend_'.$backendId,'backendtype'))));
684            }
685            return false;
686        }
687    }
688}
689?>
690