%PDF- %PDF-
| Direktori : /var/www/projetos/suporte.iigd.com.br/plugins/glpiinventory/inc/ |
| Current File : /var/www/projetos/suporte.iigd.com.br/plugins/glpiinventory/inc/networkinventory.class.php |
<?php
/**
* ---------------------------------------------------------------------
* GLPI Inventory Plugin
* Copyright (C) 2021 Teclib' and contributors.
*
* http://glpi-project.org
*
* based on FusionInventory for GLPI
* Copyright (C) 2010-2021 by the FusionInventory Development Team.
*
* ---------------------------------------------------------------------
*
* LICENSE
*
* This file is part of GLPI Inventory Plugin.
*
* GLPI Inventory Plugin is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GLPI Inventory Plugin is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with GLPI Inventory Plugin. If not, see <https://www.gnu.org/licenses/>.
* ---------------------------------------------------------------------
*/
if (!defined('GLPI_ROOT')) {
die("Sorry. You can't access this file directly");
}
/**
* Manage network inventory task jobs.
*/
class PluginGlpiinventoryNetworkinventory extends PluginGlpiinventoryCommunication
{
/**
* Get all devices and put in taskjobstate each task for each device for
* each agent
*
* @global object $DB
* @param integer $taskjobs_id
* @return string
*/
public function prepareRun($taskjobs_id)
{
global $DB;
$pfTask = new PluginGlpiinventoryTask();
$pfTaskjob = new PluginGlpiinventoryTaskjob();
$pfTaskjoblog = new PluginGlpiinventoryTaskjoblog();
$pfTaskjobstate = new PluginGlpiinventoryTaskjobstate();
$pfIPRange = new PluginGlpiinventoryIPRange();
$a_specificity = [];
$a_specificity['DEVICE'] = [];
$uniqid = uniqid();
$pfTaskjob->getFromDB($taskjobs_id);
$pfTask->getFromDB($pfTaskjob->fields['plugin_glpiinventory_tasks_id']);
$NetworkEquipment = new NetworkEquipment();
$NetworkPort = new NetworkPort();
/*
* * Different possibilities :
* IP RANGE
* NetworkEquipment
* Printer
*
* We will count total number of devices to query
*/
// get all snmpauth
$a_snmpauth = getAllDataFromTable(SNMPCredential::getTable());
// get items_id by type
$a_iprange = [];
$devices = [
NetworkEquipment::getType() => [],
Printer::getType() => []
];
$a_definition = importArrayFromDB($pfTaskjob->fields['definition']);
foreach ($a_definition as $datas) {
$itemtype = key($datas);
$items_id = current($datas);
switch ($itemtype) {
case 'PluginGlpiinventoryIPRange':
$a_iprange[] = $items_id;
break;
case 'NetworkEquipment':
case 'Printer':
$iterator = $DB->request([
'SELECT' => [
$itemtype::getTable() . '.id AS gID',
'glpi_ipaddresses.name AS gnifaddr',
'snmpcredentials_id'
],
'FROM' => $itemtype::getTable(),
'LEFT JOIN' => [
'glpi_networkports' => [
'ON' => [
'glpi_networkports' => 'items_id',
$itemtype::getTable() => 'id',[
'AND' => [
'glpi_networkports.itemtype' => $itemtype
]
]
]
],
'glpi_networknames' => [
'ON' => [
'glpi_networknames' => 'items_id',
'glpi_networkports' => 'id',[
'AND' => [
'glpi_networknames.itemtype' => 'NetworkPort'
]
]
]
],
'glpi_ipaddresses' => [
'ON' => [
'glpi_ipaddresses' => 'items_id',
'glpi_networknames' => 'id',[
'AND' => [
'glpi_ipaddresses.itemtype' => 'NetworkName'
]
]
]
]
],
'WHERE' => [
$itemtype::getTable() . '.is_deleted' => 0,
'snmpcredentials_id' => ['!=', 0],
$itemtype::getTable() . '.id' => $items_id,
'glpi_ipaddresses.name' => ['!=', '']
],
'LIMIT' => 1
]);
foreach ($iterator as $data) {
if (isset($a_snmpauth[$data['snmpcredentials_id']])) {
$input = [];
$input['TYPE'] = ($itemtype === NetworkEquipment::getType() ? 'NETWORKING' : 'PRINTER');
$input['ID'] = $data['gID'];
$input['IP'] = $data['gnifaddr'];
$input['AUTHSNMP_ID'] = $data['snmpcredentials_id'];
$a_specificity['DEVICE'][$itemtype . $data['gID']] = $input;
$devices[$itemtype][] = $items_id;
}
}
break;
}
}
// Get all devices on each iprange
foreach ($a_iprange as $items_id) {
$pfIPRange->getFromDB($items_id);
foreach ([NetworkEquipment::getType(), Printer::getType()] as $cur_itemtype) {
// Search NetworkEquipment
$criteria = [
'SELECT' => [
$cur_itemtype::getTable() . '.id AS gID',
'glpi_ipaddresses.name AS gnifaddr',
'snmpcredentials_id'
],
'FROM' => $cur_itemtype::getTable(),
'LEFT JOIN' => [
'glpi_networkports' => [
'ON' => [
'glpi_networkports' => 'items_id',
$cur_itemtype::getTable() => 'id',[
'AND' => [
'glpi_networkports.itemtype' => $cur_itemtype
]
]
]
],
'glpi_networknames' => [
'ON' => [
'glpi_networknames' => 'items_id',
'glpi_networkports' => 'id',[
'AND' => [
'glpi_networknames.itemtype' => 'NetworkPort'
]
]
]
],
'glpi_ipaddresses' => [
'ON' => [
'glpi_ipaddresses' => 'items_id',
'glpi_networknames' => 'id',[
'AND' => [
'glpi_ipaddresses.itemtype' => 'NetworkName'
]
]
]
]
],
'WHERE' => [
$cur_itemtype::getTable() . '.is_deleted' => 0,
'snmpcredentials_id' => ['!=', 0],
new \QueryExpression('inet_aton(' . $DB->quoteName('glpi_ipaddresses.name') . ') BETWEEN inet_aton(' . $DB->quote($pfIPRange->fields['ip_start']) . ') AND inet_aton(' . $DB->quote($pfIPRange->fields['ip_end']) . ')'),
],
'GROUPBY' => $cur_itemtype::getTable() . '.id'
];
if ($pfIPRange->fields['entities_id'] != '-1') {
$criteria['WHERE'][$cur_itemtype::getTable() . '.entities_id'] = array_merge(
[$pfIPRange->fields['entities_id']],
getAncestorsOf("glpi_entities", $pfIPRange->fields['entities_id'])
);
}
$iterator = $DB->request($criteria);
foreach ($iterator as $data) {
if (isset($a_snmpauth[$data['snmpcredentials_id']])) {
$input = [];
$input['TYPE'] = ($cur_itemtype === NetworkEquipment::getType() ? 'NETWORKING' : 'PRINTER');
$input['ID'] = $data['gID'];
$input['IP'] = $data['gnifaddr'];
$input['AUTHSNMP_ID'] = $data['snmpcredentials_id'];
$a_specificity['DEVICE'][$cur_itemtype . $data['gID']] = $input;
$devices[$cur_itemtype][] = $data['gID'];
}
}
}
}
// *** For dynamic agent same subnet, it's an another management ***
if (strstr($pfTaskjob->fields['action'], '".2"')) {
$a_subnet = [];
$a_devicesubnet = [];
foreach ($devices[NetworkEquipment::getType()] as $items_id) {
$NetworkEquipment->getFromDB($items_id);
$a_ip = explode(".", $NetworkEquipment->fields['ip']);
$ip_subnet = $a_ip[0] . "." . $a_ip[1] . "." . $a_ip[2] . ".";
if (!isset($a_subnet[$ip_subnet])) {
$a_subnet[$ip_subnet] = 0;
}
$a_subnet[$ip_subnet]++;
$a_devicesubnet[$ip_subnet]['NetworkEquipment'][$items_id] = 1;
}
foreach ($devices[Printer::getType()] as $items_id) {
$a_ports = $NetworkPort->find(
['itemtype' => 'Printer',
'items_id' => $items_id,
['ip'] => ['!=',
'127.0.0.1']]
);
foreach ($a_ports as $a_port) {
$a_ip = explode(".", $a_port['ip']);
$ip_subnet = $a_ip[0] . "." . $a_ip[1] . "." . $a_ip[2] . ".";
if (!isset($a_subnet[$ip_subnet])) {
$a_subnet[$ip_subnet] = 0;
}
$a_subnet[$ip_subnet]++;
$a_devicesubnet[$ip_subnet]['Printer'][$items_id] = 1;
}
}
$a_input = [];
$a_input['plugin_glpiinventory_taskjobs_id'] = $taskjobs_id;
$a_input['state'] = 1;
$a_input['agents_id'] = 0;
$a_input['itemtype'] = '';
$a_input['items_id'] = 0;
$a_input['uniqid'] = $uniqid;
$a_input['execution_id'] = $pfTask->fields['execution_id'];
$taskvalid = 0;
foreach (array_keys($a_subnet) as $subnet) {
// No agent available for this subnet
for ($i = 0; $i < 2; $i++) {
$itemtype = 'Printer';
if ($i == '0') {
$itemtype = 'NetworkEquipment';
}
if (isset($a_devicesubnet[$subnet][$itemtype])) {
foreach ($a_devicesubnet[$subnet][$itemtype] as $items_id => $num) {
$a_input['itemtype'] = $itemtype;
$a_input['items_id'] = $items_id;
$a_input['specificity'] = exportArrayToDB(
$a_specificity['DEVICE'][$itemtype . $items_id]
);
$Taskjobstates_id = $pfTaskjobstate->add($a_input);
//Add log of taskjob
$a_input['plugin_glpiinventory_taskjobstates_id'] = $Taskjobstates_id;
$a_input['state'] = 7;
$a_input['date'] = date("Y-m-d H:i:s");
$pfTaskjoblog->add($a_input);
$pfTaskjobstate->changeStatusFinish(
$Taskjobstates_id,
0,
'',
1,
"Unable to find agent to inventory " .
"this " . $itemtype
);
$a_input['state'] = 1;
}
}
}
}
if ($taskvalid == "0") {
$pfTaskjob->reinitializeTaskjobs($pfTaskjob->fields['plugin_glpiinventory_tasks_id']);
}
} else {
/**
* Manage agents
*/
$a_input = [];
$a_input['plugin_glpiinventory_taskjobs_id'] = $taskjobs_id;
$a_input['state'] = 1;
$a_input['agents_id'] = 0;
$a_input['itemtype'] = '';
$a_input['items_id'] = 0;
$a_input['uniqid'] = $uniqid;
$a_input['execution_id'] = $pfTask->fields['execution_id'];
$Taskjobstates_id = $pfTaskjobstate->add($a_input);
//Add log of taskjob
$a_input['plugin_glpiinventory_taskjobstates_id'] = $Taskjobstates_id;
$a_input['state'] = 7;
$a_input['date'] = date("Y-m-d H:i:s");
$pfTaskjoblog->add($a_input);
$pfTaskjobstate->changeStatusFinish(
$Taskjobstates_id,
0,
'',
1,
"Unable to find agent to run this job"
);
$input_taskjob = [];
$input_taskjob['id'] = $pfTaskjob->fields['id'];
//$input_taskjob['status'] = 0;
$pfTaskjob->update($input_taskjob);
}
return $uniqid;
}
/**
* When agent contact server, this function send datas to agent
*
* @param object $jobstate PluginGlpiinventoryTaskjobstate instance
* @return array
*/
public function run($jobstate)
{
$agent = new Agent();
$pfTaskjobstate = new PluginGlpiinventoryTaskjobstate();
$pfTaskjoblog = new PluginGlpiinventoryTaskjoblog();
$credentials = new SNMPCredential();
$pfToolbox = new PluginGlpiinventoryToolbox();
$pfConfig = new PluginGlpiinventoryConfig();
$current = $jobstate;
$agent->getFromDB($current->fields['agents_id']);
$ip = current(PluginGlpiinventoryToolbox::getIPforDevice(
$jobstate->fields['itemtype'],
$jobstate->fields['items_id']
));
$param_attrs = [];
$device_attrs = [];
$auth_nodes = [];
if ($ip == '') {
$pfTaskjobstate->changeStatusFinish(
$jobstate->fields['id'],
$jobstate->fields['items_id'],
$jobstate->fields['itemtype'],
1,
"Device have no ip"
);
// Return an empty list to avoid adding an option with no data in the joblist
return [];
} else {
// Use general config when threads number is set to 0 on the agent
$param_attrs['THREADS_QUERY'] = $agent->fields["threads_networkinventory"] == 0 ?
$pfConfig->getValue('threads_networkinventory') :
$agent->fields["threads_networkinventory"];
// Use general config when timeout is set to 0 on the agent
$param_attrs['TIMEOUT'] = $agent->fields["timeout_networkinventory"] == 0 ?
$pfConfig->getValue('timeout_networkinventory') :
$agent->fields["timeout_networkinventory"];
$param_attrs['PID'] = $current->fields['id'];
$changestate = 0;
$taskjobstatedatas = $jobstate->fields;
$a_extended = ['snmpcredentials_id' => 0];
if ($jobstate->fields['itemtype'] == 'Printer') {
$device_attrs['TYPE'] = 'PRINTER';
$printer = new Printer();
$a_extended = current($printer->find(['id' => $jobstate->fields['items_id']], [], 1));
} elseif ($jobstate->fields['itemtype'] == 'NetworkEquipment') {
$device_attrs['TYPE'] = 'NETWORKING';
$neteq = new NetworkEquipment();
$a_extended = current($neteq->find(['id' => $jobstate->fields['items_id']], [], 1));
}
$device_attrs['ID'] = $jobstate->fields['items_id'];
$device_attrs['IP'] = $ip;
$device_attrs['AUTHSNMP_ID'] = $a_extended['snmpcredentials_id'];
if ($changestate == '0') {
$pfTaskjobstate->changeStatus($taskjobstatedatas['id'], 1);
$pfTaskjoblog->addTaskjoblog(
$taskjobstatedatas['id'],
'0',
'Agent',
'1',
$param_attrs['THREADS_QUERY'] . ' threads ' .
$param_attrs['TIMEOUT'] . ' timeout'
);
$changestate = $pfTaskjobstate->fields['id'];
} else {
$pfTaskjobstate->changeStatusFinish(
$taskjobstatedatas['id'],
$taskjobstatedatas['items_id'],
$taskjobstatedatas['itemtype'],
0,
"Merged with " . $changestate
);
}
// Only keep required snmp credentials
$snmpauthlist = $credentials->find(['id' => $a_extended['snmpcredentials_id']]);
foreach ($snmpauthlist as $snmpauth) {
$auth_node = $pfToolbox->addAuth($snmpauth['id']);
if (count($auth_node)) {
$auth_nodes[] = $auth_node;
}
}
}
return [
'OPTION' => [
'NAME' => 'SNMPQUERY',
'PARAM' => [
'content' => '',
'attributes' => $param_attrs
],
'DEVICE' => [
'content' => '',
'attributes' => $device_attrs
]
] + $auth_nodes
];
}
/**
* Get the devices have an IP in the IP range
*
* @global object $DB
* @param integer $ipranges_id
* @return array
*/
public function getDevicesOfIPRange($ipranges_id, bool $restrict_entity = true)
{
global $DB;
$devicesList = [];
$pfIPRange = new PluginGlpiinventoryIPRange();
// get all snmpauth
$a_snmpauth = getAllDataFromTable(SNMPCredential::getTable());
$pfIPRange->getFromDB($ipranges_id);
foreach ([NetworkEquipment::getType(), Printer::getType()] as $itemtype) {
$criteria = [
'SELECT' => [
$itemtype::getTable() . '.id AS gID',
$itemtype::getTable() . '.name AS gNAME',
'glpi_ipaddresses.name AS gnifaddr',
'snmpcredentials_id'
],
'FROM' => $itemtype::getTable(),
'LEFT JOIN' => [
'glpi_networkports' => [
'ON' => [
'glpi_networkports' => 'items_id',
$itemtype::getTable() => 'id', [
'AND' => [
'glpi_networkports.itemtype' => $itemtype
]
]
]
],
'glpi_networknames' => [
'ON' => [
'glpi_networknames' => 'items_id',
'glpi_networkports' => 'id', [
'AND' => [
'glpi_networknames.itemtype' => 'NetworkPort'
]
]
]
],
'glpi_ipaddresses' => [
'ON' => [
'glpi_ipaddresses' => 'items_id',
'glpi_networknames' => 'id',[
'AND' => [
'glpi_ipaddresses.itemtype' => 'NetworkName'
]
]
]
]
],
'WHERE' => [
$itemtype::getTable() . '.is_deleted' => 0,
'snmpcredentials_id' => ['!=', '0'],
new \QueryExpression(
'inet_aton(' . $DB->quoteName('glpi_ipaddresses.name') . ') BETWEEN ' .
'inet_aton(' . $DB->quote($pfIPRange->fields['ip_start']) . ') AND inet_aton(' .
$DB->quote($pfIPRange->fields['ip_end']) . ')'
)
],
'GROUPBY' => 'gID'
];
if ($pfIPRange->fields['entities_id'] != '-1' && $restrict_entity) {
$criteria['WHERE'][$itemtype::getTable() . '.entities_id'] = array_merge(
[$pfIPRange->fields['entities_id']],
getAncestorsOf("glpi_entities", $pfIPRange->fields['entities_id'])
);
}
$iterator = $DB->request($criteria);
foreach ($iterator as $data) {
if (isset($a_snmpauth[$data['snmpcredentials_id']])) {
$devicesList[] = [
$itemtype => $data['gID']
];
}
}
}
return $devicesList;
}
}