1<?php 2/* 3** Zabbix 4** Copyright (C) 2001-2021 Zabbix SIA 5** 6** This program is free software; you can redistribute it and/or modify 7** it under the terms of the GNU General Public License as published by 8** the Free Software Foundation; either version 2 of the License, or 9** (at your option) any later version. 10** 11** This program is distributed in the hope that it will be useful, 12** but WITHOUT ANY WARRANTY; without even the implied warranty of 13** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14** GNU General Public License for more details. 15** 16** You should have received a copy of the GNU General Public License 17** along with this program; if not, write to the Free Software 18** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19**/ 20 21 22/** 23 * A class to display discovery table as a screen element. 24 */ 25class CScreenDiscovery extends CScreenBase { 26 27 /** 28 * Data 29 * 30 * @var array 31 */ 32 protected $data = []; 33 34 /** 35 * Init screen data. 36 * 37 * @param array $options 38 * @param array $options['data'] 39 */ 40 public function __construct(array $options = []) { 41 parent::__construct($options); 42 43 $this->data = $options['data']; 44 } 45 46 /** 47 * Process screen. 48 * 49 * @return CDiv (screen inside container) 50 */ 51 public function get() { 52 $this->dataId = 'discovery'; 53 54 $sort_field = $this->data['sort']; 55 $sort_order = $this->data['sortorder']; 56 57 $drules = API::DRule()->get([ 58 'output' => ['druleid', 'name'], 59 'selectDHosts' => ['dhostid', 'status', 'lastup', 'lastdown'], 60 'druleids' => (array_key_exists('filter_druleids', $this->data) && $this->data['filter_druleids']) 61 ? $this->data['filter_druleids'] 62 : null, 63 'filter' => ['status' => DRULE_STATUS_ACTIVE], 64 'preservekeys' => true 65 ]); 66 67 order_result($drules, 'name'); 68 69 $dservices = API::DService()->get([ 70 'output' => ['dserviceid', 'port', 'status', 'lastup', 'lastdown', 'dcheckid', 'ip', 'dns'], 71 'selectHosts' => ['hostid', 'name', 'status'], 72 'druleids' => array_keys($drules), 73 'sortfield' => $sort_field, 74 'sortorder' => $sort_order, 75 'limitSelects' => 1, 76 'preservekeys' => true 77 ]); 78 79 // user macros 80 $macros = API::UserMacro()->get([ 81 'output' => ['macro', 'value'], 82 'globalmacro' => true 83 ]); 84 $macros = zbx_toHash($macros, 'macro'); 85 86 $dchecks = API::DCheck()->get([ 87 'output' => ['type', 'key_'], 88 'dserviceids' => array_keys($dservices), 89 'preservekeys' => true 90 ]); 91 92 // services 93 $services = []; 94 foreach ($dservices as $dservice) { 95 $key_ = $dchecks[$dservice['dcheckid']]['key_']; 96 if ($key_ !== '') { 97 if (array_key_exists($key_, $macros)) { 98 $key_ = $macros[$key_]['value']; 99 } 100 $key_ = ': '.$key_; 101 } 102 $service_name = discovery_check_type2str($dchecks[$dservice['dcheckid']]['type']). 103 discovery_port2str($dchecks[$dservice['dcheckid']]['type'], $dservice['port']).$key_; 104 $services[$service_name] = 1; 105 } 106 ksort($services); 107 108 $dhosts = API::DHost()->get([ 109 'output' => ['dhostid'], 110 'selectDServices' => ['dserviceid'], 111 'druleids' => array_keys($drules), 112 'preservekeys' => true 113 ]); 114 115 $header = [ 116 make_sorting_header(_('Discovered device'), 'ip', $sort_field, $sort_order, 117 'zabbix.php?action=discovery.view' 118 ), 119 _('Monitored host'), 120 _('Uptime').'/'._('Downtime') 121 ]; 122 123 foreach ($services as $name => $foo) { 124 $header[] = (new CColHeader($name)) 125 ->addClass('vertical_rotation') 126 ->setTitle($name); 127 } 128 129 // create table 130 $table = (new CTableInfo()) 131 ->makeVerticalRotation() 132 ->setHeader($header); 133 134 foreach ($drules as $drule) { 135 $discovery_info = []; 136 137 foreach ($drule['dhosts'] as $dhost) { 138 if ($dhost['status'] == DHOST_STATUS_DISABLED) { 139 $hclass = 'disabled'; 140 $htime = $dhost['lastdown']; 141 } 142 else { 143 $hclass = 'enabled'; 144 $htime = $dhost['lastup']; 145 } 146 147 // $primary_ip stores the primary host ip of the dhost 148 $primary_ip = ''; 149 150 foreach ($dhosts[$dhost['dhostid']]['dservices'] as $dservice) { 151 $dservice = $dservices[$dservice['dserviceid']]; 152 153 $hostName = ''; 154 155 $host = reset($dservices[$dservice['dserviceid']]['hosts']); 156 if ($host) { 157 $hostName = $host['name']; 158 } 159 160 if ($primary_ip !== '') { 161 if ($primary_ip === $dservice['ip']) { 162 $htype = 'primary'; 163 } 164 else { 165 $htype = 'slave'; 166 } 167 } 168 else { 169 $primary_ip = $dservice['ip']; 170 $htype = 'primary'; 171 } 172 173 if (!array_key_exists($dservice['ip'], $discovery_info)) { 174 $discovery_info[$dservice['ip']] = [ 175 'ip' => $dservice['ip'], 176 'dns' => $dservice['dns'], 177 'type' => $htype, 178 'class' => $hclass, 179 'host' => $hostName, 180 'time' => $htime 181 ]; 182 } 183 184 if ($dservice['status'] == DSVC_STATUS_DISABLED) { 185 $class = ZBX_STYLE_INACTIVE_BG; 186 $time = 'lastdown'; 187 } 188 else { 189 $class = null; 190 $time = 'lastup'; 191 } 192 193 $key_ = $dchecks[$dservice['dcheckid']]['key_']; 194 if ($key_ !== '') { 195 if (array_key_exists($key_, $macros)) { 196 $key_ = $macros[$key_]['value']; 197 } 198 $key_ = NAME_DELIMITER.$key_; 199 } 200 201 $service_name = discovery_check_type2str($dchecks[$dservice['dcheckid']]['type']). 202 discovery_port2str($dchecks[$dservice['dcheckid']]['type'], $dservice['port']).$key_; 203 204 $discovery_info[$dservice['ip']]['services'][$service_name] = [ 205 'class' => $class, 206 'time' => $dservice[$time] 207 ]; 208 } 209 } 210 211 if ($discovery_info) { 212 $col = new CCol( 213 [bold($drule['name']), SPACE.'('._n('%d device', '%d devices', count($discovery_info)).')'] 214 ); 215 $col->setColSpan(count($services) + 3); 216 217 $table->addRow($col); 218 } 219 order_result($discovery_info, $sort_field, $sort_order); 220 221 foreach ($discovery_info as $ip => $h_data) { 222 $dns = ($h_data['dns'] === '') ? '' : ' ('.$h_data['dns'].')'; 223 $row = [ 224 ($h_data['type'] === 'primary') 225 ? (new CSpan($ip.$dns))->addClass($h_data['class']) 226 : new CSpan(SPACE.SPACE.$ip.$dns), 227 new CSpan(array_key_exists('host', $h_data) ? $h_data['host'] : ''), 228 (new CSpan((($h_data['time'] == 0 || $h_data['type'] === 'slave') 229 ? '' 230 : convert_units(['value' => time() - $h_data['time'], 'units' => 'uptime']))) 231 ) 232 ->addClass($h_data['class']) 233 ]; 234 235 foreach ($services as $name => $foo) { 236 $row[] = array_key_exists($name, $h_data['services']) 237 ? (new CCol(zbx_date2age($h_data['services'][$name]['time']))) 238 ->addClass($h_data['services'][$name]['class']) 239 : ''; 240 } 241 $table->addRow($row); 242 } 243 } 244 245 return $this->getOutput($table, true, $this->data); 246 } 247} 248