diff options
author | Simon Rettberg | 2016-05-25 18:12:12 +0200 |
---|---|---|
committer | Simon Rettberg | 2016-05-25 18:12:12 +0200 |
commit | 1e37a2fd1d3263ad894e1d985569772b5d3fc856 (patch) | |
tree | 6ab591991b1d2f99f46d55d8db5a3146e1e7de71 | |
parent | [locations] Add machine count to each location (diff) | |
download | slx-admin-1e37a2fd1d3263ad894e1d985569772b5d3fc856.tar.gz slx-admin-1e37a2fd1d3263ad894e1d985569772b5d3fc856.tar.xz slx-admin-1e37a2fd1d3263ad894e1d985569772b5d3fc856.zip |
[statistics] Show lspci info in machine details
-rw-r--r-- | apis/update.inc.php | 3 | ||||
-rw-r--r-- | modules-available/statistics/page.inc.php | 142 | ||||
-rw-r--r-- | modules-available/statistics/templates/machine-main.html | 28 |
3 files changed, 165 insertions, 8 deletions
diff --git a/apis/update.inc.php b/apis/update.inc.php index fb5af7d6..e7ecc6bd 100644 --- a/apis/update.inc.php +++ b/apis/update.inc.php @@ -328,4 +328,5 @@ function update_11() } // TODO: Remove setting_distro, setting, cat_setting -// TODO: Add toggle column to setting_global
\ No newline at end of file +// TODO: Add toggle column to setting_global +// TODO: Add pciid table
\ No newline at end of file diff --git a/modules-available/statistics/page.inc.php b/modules-available/statistics/page.inc.php index a896b7a6..266c4277 100644 --- a/modules-available/statistics/page.inc.php +++ b/modules-available/statistics/page.inc.php @@ -322,9 +322,15 @@ class Page_Statistics extends Page return; } } elseif ($filter === 'location') { - $where = "subnet.locationid = :lid OR machine.locationid = :lid"; - $join = " INNER JOIN subnet ON (INET_ATON(clientip) BETWEEN startaddr AND endaddr) "; - $args = array('lid' => (int)$argument); + settype($argument, 'int'); + if ($argument === 0) { + $where = "machine.locationid IS NULL AND s.locationid IS NULL"; + $join = "LEFT JOIN subnet s ON (INET_ATON(machine.clientip) BETWEEN s.startaddr AND s.endaddr)"; + } else { + $where = "subnet.locationid = :lid OR machine.locationid = :lid"; + $join = " INNER JOIN subnet ON (INET_ATON(clientip) BETWEEN startaddr AND endaddr) "; + $args = array('lid' => $argument); + } } else { Message::addError('invalid-filter'); return; @@ -428,10 +434,10 @@ class Page_Statistics extends Page $row['username'] = $session['username']; } } - + private function showMachine($uuid) - { - $client = Database::queryFirst("SELECT machineuuid, macaddr, clientip, firstseen, lastseen, logintime, lastboot," + { + $client = Database::queryFirst("SELECT machineuuid, locationid, macaddr, clientip, firstseen, lastseen, logintime, lastboot," . " mbram, kvmstate, cpumodel, id44mb, data, hostname, notes FROM machine WHERE machineuuid = :uuid", array('uuid' => $uuid)); // Mangle fields @@ -439,7 +445,7 @@ class Page_Statistics extends Page if ($NOW - $client['lastseen'] > 610) { $client['state_off'] = true; } elseif ($client['logintime'] == 0) { - $client['state_idle'] = true; + $client['state_idle'] = true; } else { $client['state_occupied'] = true; $this->fillSessionInfo($client); @@ -467,6 +473,10 @@ class Page_Statistics extends Page if ($section[1] === 'Partition tables') { $this->parseHdd($hdds, $section[2]); } + if ($section[1] === 'PCI ID') { + $client['lspci1'] = $client['lspci2'] = array(); + $this->parsePci($client['lspci1'], $client['lspci2'], $section[2]); + } if (isset($hdds['hdds']) && $section[1] === 'smartctl') { // This currently required that the partition table section comes first... $this->parseSmartctl($hdds['hdds'], $section[2]); @@ -474,6 +484,20 @@ class Page_Statistics extends Page } } unset($client['data']); + // Get locations + if (Module::isAvailable('locations')) { + if (is_null($client['locationid'])) { + $client['locationid'] = Location::getFromIp($client['clientip']); + } + $locs = Location::getLocationsAssoc(); + $next = (int)$client['locationid']; + $output = array(); + while (isset($locs[$next])) { + array_unshift($output, $locs[$next]); + $next = $locs[$next]['parentlocationid']; + } + $client['locations'] = $output; + } // Throw output at user Render::addTemplate('machine-main', $client); // Sessions @@ -745,6 +769,50 @@ class Page_Statistics extends Page unset($hdd); $row['hdds'] = &$hdds; } + + private function parsePci(&$pci1, &$pci2, $data) + { + preg_match_all('/[a-f0-9\:\.]{7}\s+"(Class\s*)?(?<class>[a-f0-9]{4})"\s+"(?<ven>[a-f0-9]{4})"\s+"(?<dev>[a-f0-9]{4})"/is', $data, $out, PREG_SET_ORDER); + $NOW = time(); + $pci = array(); + foreach ($out as $entry) { + if (!isset($pci[$entry['class']])) { + $class = 'c.' . $entry['class']; + $res = $this->getPciId('CLASS', $class); + if ($res === false || $res['dateline'] < $NOW) { + $pci[$entry['class']]['lookupClass'] = 'do-lookup'; + $pci[$entry['class']]['class'] = $class; + } else { + $pci[$entry['class']]['class'] = $res['value']; + } + } + $new = array( + 'ven' => $entry['ven'], + 'dev' => $entry['ven'] . ':' . $entry['dev'], + ); + $res = $this->getPciId('VENDOR', $new['ven']); + if ($res === false || $res['dateline'] < $NOW) { + $new['lookupVen'] = 'do-lookup'; + } else { + $new['ven'] = $res['value']; + } + $res = $this->getPciId('DEVICE', $new['ven'] . ':' . $new['dev']); + if ($res === false || $res['dateline'] < $NOW) { + $new['lookupDev'] = 'do-lookup'; + } else { + $new['dev'] = $res['value']; + } + $pci[$entry['class']]['entries'][] = $new; + } + ksort($pci); + foreach ($pci as $class => $entry) { + if ($class === '0300' || $class === '0200' || $class === '0403') { + $pci1[] = $entry; + } else { + $pci2[] = $entry; + } + } + } private function parseSmartctl(&$hdds, $data) { @@ -787,4 +855,64 @@ class Page_Statistics extends Page } } + protected function doAjax() + { + $param = Request::any('lookup', false, 'string'); + if ($param === false) + die('No lookup given'); + $add = ''; + if (preg_match('/^([a-f0-9]{4}):([a-f0-9]{4})$/', $param, $out)) { + $cat = 'DEVICE'; + $host = $out[2] . '.' . $out[1]; + $add = ' (' . $param . ')'; + } elseif (preg_match('/^([a-f0-9]{4})$/', $param, $out)) { + $cat = 'VENDOR'; + $host = $out[1]; + } elseif (preg_match('/^c\.([a-f0-9]{2})([a-f0-9]{2})$/', $param, $out)) { + $cat = 'CLASS'; + $host = $out[2] . '.' . $out[1] . '.c'; + } else { + die('Invalid format requested'); + } + $cached = $this->getPciId($cat, $param); + if ($cached !== false && $cached['dateline'] > time()) { + echo $cached['value'], $add; + exit; + } + $res = dns_get_record($host . '.pci.id.ucw.cz', DNS_TXT); + if (is_array($res)) { + foreach ($res as $entry) { + if (isset($entry['txt']) && substr($entry['txt'], 0, 2) === 'i=') { + $string = substr($entry['txt'], 2); + $this->setPciId($cat, $param, $string); + echo $string, $add; + exit; + } + } + } + if ($cached !== false) { + echo $cached['value'], $add; + exit; + } + die('Not found'); + } + + private function getPciId($cat, $id) + { + return Database::queryFirst("SELECT value, dateline FROM pciid WHERE category = :cat AND id = :id LIMIT 1", + array('cat' => $cat, 'id' => $id)); + } + + private function setPciId($cat, $id, $value) + { + Database::exec("INSERT INTO pciid (category, id, value, dateline) VALUES (:cat, :id, :value, :timeout)" + . " ON DUPLICATE KEY UPDATE value = VALUES(value), dateline = VALUES(dateline)", + array( + 'cat' => $cat, + 'id' => $id, + 'value' => $value, + 'timeout' => time() + mt_rand(10, 30) * 86400 + ), true); + } + } diff --git a/modules-available/statistics/templates/machine-main.html b/modules-available/statistics/templates/machine-main.html index 8071416a..daff724e 100644 --- a/modules-available/statistics/templates/machine-main.html +++ b/modules-available/statistics/templates/machine-main.html @@ -2,6 +2,11 @@ {{hostname}} {{#hostname}}–{{/hostname}} {{clientip}} {{#notes}}<a href="#usernotes"><span class="glyphicon glyphicon-exclamation-sign"></span></a>{{/notes}} </h1> +<div> + {{#locations}} + » <a href="?do=statistics&filter=location&argument={{locationid}}">{{locationname}}</a> + {{/locations}} +</div> <div class="row"> <div class="col-md-6"> @@ -118,7 +123,30 @@ <td>{{kvmstate}}</td> </tr> </table> + <h4>{{lang_devices}}</h4> + {{#lspci1}} + <div><span class="{{lookupClass}}">{{class}}</span></div> + {{#entries}} + <div class="small"> └ <span class="{{lookupVen}}">{{ven}}</span> <span class="{{lookupDev}}">{{dev}}</span></div> + {{/entries}} + {{/lspci1}} + <div id="lspci" class="collapse"> + {{#lspci2}} + <div><span class="{{lookupClass}}">{{class}}</span></div> + {{#entries}} + <div class="small"> └ <span class="{{lookupVen}}">{{ven}}</span> <span class="{{lookupDev}}">{{dev}}</span></div> + {{/entries}} + {{/lspci2}} + </div> + <div><button class="btn btn-xs btn-default" data-toggle="collapse" data-target="#lspci">{{lang_more}}</button></div> </div> </div> </div> </div> +<script type="application/javascript"><!-- +document.addEventListener("DOMContentLoaded", function () { + $('span.do-lookup').each(function () { + $(this).load('?do=statistics&lookup=' + $(this).text()); + }); +}, false); +// --></script>
\ No newline at end of file |