. * --------------------------------------------------------------------- */ /** * Virtual machine management */ if (!defined('GLPI_ROOT')) { die("Sorry. You can't access this file directly"); } /** * ComputerVirtualMachine Class * * Class to manage virtual machines **/ class ComputerVirtualMachine extends CommonDBChild { // From CommonDBChild static public $itemtype = 'Computer'; static public $items_id = 'computers_id'; public $dohistory = true; static function getTypeName($nb = 0) { return __('Virtualization'); } function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) { if (!$withtemplate && ($item->getType() == 'Computer') && Computer::canView()) { $nb = 0; if ($_SESSION['glpishow_count_on_tabs']) { $nb = countElementsInTable(self::getTable(), ['computers_id' => $item->getID(), 'is_deleted' => 0 ]); } return self::createTabEntry(self::getTypeName(), $nb); } return ''; } function defineTabs($options = []) { $ong = []; $this->addDefaultFormTab($ong); return $ong; } static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) { self::showForVirtualMachine($item); self::showForComputer($item); return true; } function post_getEmpty() { $this->fields["vcpu"] = '0'; $this->fields["ram"] = '0'; } /** * Print the version form * * @param $ID integer ID of the item * @param $options array * - target for the Form * - computers_id ID of the computer for add process * * @return true if displayed false if item not found or not right to display **/ function showForm($ID, $options = []) { if (!Session::haveRight("computer", UPDATE)) { return false; } $comp = new Computer(); if ($ID > 0) { $this->check($ID, READ); $comp->getFromDB($this->fields['computers_id']); } else { // Create item $this->check(-1, CREATE, $options); $comp->getFromDB($options['computers_id']); } $this->showFormHeader($options); if ($this->isNewID($ID)) { echo ""; } echo ""; echo "".Computer::getTypeName(1).""; echo "".$comp->getLink().""; if (Plugin::haveImport()) { echo "".__('Automatic inventory').""; echo ""; if ($ID && $this->fields['is_dynamic']) { Plugin::doHook("autoinventory_information", $this); } else { echo __('No'); } echo ""; } else { echo ""; } echo "\n"; echo ""; echo "".__('Name').""; echo ""; Html::autocompletionTextField($this, "name"); echo "".__('Comments').""; echo ""; echo ""; echo ""; echo ""; echo "".VirtualMachineType::getTypeName(1).""; echo ""; VirtualMachineType::dropdown(['value' => $this->fields['virtualmachinetypes_id']]); echo ""; echo ""; echo "".VirtualMachineSystem::getTypeName(1).""; echo ""; VirtualMachineSystem::dropdown(['value' => $this->fields['virtualmachinesystems_id']]); echo ""; echo "".VirtualMachineState::getTypeName(1).""; echo ""; VirtualMachineState::dropdown(['value' => $this->fields['virtualmachinestates_id']]); echo ""; echo ""; echo "".__('UUID').""; echo ""; Html::autocompletionTextField($this, "uuid"); echo ""; echo "".__('Machine').""; echo ""; if ($link_computer = self::findVirtualMachine($this->fields)) { $computer = new Computer(); if ($computer->getFromDB($link_computer)) { echo $computer->getLink(['comments' => true]); } else { echo NOT_AVAILABLE; } } echo ""; echo ""; echo ""; echo "".sprintf(__('%1$s (%2$s)'), _n('Memory', 'Memories', 1), __('Mio')).""; echo ""; Html::autocompletionTextField( $this, 'ram', [ 'type' => 'number', 'attrs' => [ 'min' => 0 ] ] ); echo ""; echo ""._x('quantity', 'Processors number').""; echo ""; Html::autocompletionTextField( $this, 'vcpu', [ 'type' => 'number', 'attrs' => [ 'min' => 0 ] ] ); echo ""; $this->showFormButtons($options); return true; } /** * Show hosts for a virtualmachine * * @param $comp Computer object that represents the virtual machine * * @return void **/ static function showForVirtualMachine(Computer $comp) { $ID = $comp->fields['id']; if (!$comp->getFromDB($ID) || !$comp->can($ID, READ)) { return; } echo "
"; if (isset($comp->fields['uuid']) && ($comp->fields['uuid'] != '')) { $hosts = getAllDataFromTable( self::getTable(), [ 'RAW' => [ 'LOWER(uuid)' => self::getUUIDRestrictCriteria($comp->fields['uuid']) ] ] ); if (!empty($hosts)) { echo ""; echo ""; $header = ""; $header .= ""; $header .= ""; echo $header; $computer = new Computer(); foreach ($hosts as $host) { echo ""; echo ""; echo ""; } echo $header; echo "
".__('List of virtualized environments')."
".__('Name')."".Entity::getTypeName(1)."
"; if ($computer->can($host['computers_id'], READ)) { echo ""; echo $computer->fields['name'].""; $tooltip = "'; $tooltip.= "'; $tooltip.= "
".__('Name')."".$computer->fields['name']. '
".__('Serial number')."".$computer->fields['serial']. '
".__('Comments')."".$computer->fields['comment']. '
'; echo "  ".Html::showToolTip($tooltip, ['display' => false]); } else { echo $computer->fields['name']; } echo "
"; echo Dropdown::getDropdownName('glpi_entities', $computer->fields['entities_id']); echo "
"; } } echo "
"; if (!empty($hosts)) { echo "
"; } } /** * Print the computers disks * * @param $comp Computer object * * @return void **/ static function showForComputer(Computer $comp) { $ID = $comp->fields['id']; if (!$comp->getFromDB($ID) || !$comp->can($ID, READ)) { return false; } $canedit = $comp->canEdit($ID); if ($canedit) { echo "
". ""; echo __('Add a virtual machine'); echo "
\n"; } echo "
"; $virtualmachines = getAllDataFromTable( self::getTable(), [ 'WHERE' => [ 'computers_id' => $ID, 'is_deleted' => 0 ], 'ORDER' => 'name' ] ); echo ""; Session::initNavigateListItems('ComputerVirtualMachine', sprintf(__('%1$s = %2$s'), Computer::getTypeName(1), (empty($comp->fields['name']) ? "($ID)" : $comp->fields['name']))); if (empty($virtualmachines)) { echo ""; } else { echo ""; $header = ""; $header .= ""; if (Plugin::haveImport()) { $header .= ""; } $header .= ""; $header .= ""; $header .= ""; $header .= ""; $header .= ""; $header .= ""; $header .= ""; $header .= ""; echo $header; $vm = new self(); foreach ($virtualmachines as $virtualmachine) { $vm->getFromDB($virtualmachine['id']); echo ""; echo ""; echo ""; if (Plugin::haveImport()) { echo ""; } echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; Session::addToNavigateListItems('ComputerVirtualMachine', $virtualmachine['id']); } echo $header; } echo "
".__('No virtualized environment associated with the computer')."
".__('List of virtualized environments')."
".__('Name').""._n('Comment', 'Comments', 1)."".__('Automatic inventory')."".VirtualMachineType::getTypeName(1)."".VirtualMachineSystem::getTypeName(1)."".__('State')."".__('UUID').""._x('quantity', 'Processors number')."".sprintf(__('%1$s (%2$s)'), _n('Memory', 'Memories', 1), __('Mio'))."".__('Machine')."
".$vm->getLink()."".$virtualmachine['comment']."".Dropdown::getYesNo($vm->isDynamic()).""; echo Dropdown::getDropdownName('glpi_virtualmachinetypes', $virtualmachine['virtualmachinetypes_id']); echo ""; echo Dropdown::getDropdownName('glpi_virtualmachinesystems', $virtualmachine['virtualmachinesystems_id']); echo ""; echo Dropdown::getDropdownName('glpi_virtualmachinestates', $virtualmachine['virtualmachinestates_id']); echo "".$virtualmachine['uuid']."".$virtualmachine['vcpu']."".$virtualmachine['ram'].""; if ($link_computer = self::findVirtualMachine($virtualmachine)) { $computer = new Computer(); if ($computer->can($link_computer, READ)) { $url = ""; $url .= $computer->fields["name"].""; $tooltip = "'; $tooltip.= "'; $tooltip.= "
".__('Name')."".$computer->fields['name']. '
".__('Serial number')."".$computer->fields['serial']. '
".__('Comments')."".$computer->fields['comment']. '
'; $url .= "  ".Html::showToolTip($tooltip, ['display' => false]); } else { $url = $computer->fields['name']; } echo $url; } echo "
"; echo "
"; } /** * Get correct uuid sql search for virtualmachines * * @since 9.3.1 * * @param string $uuid the uuid given * * @return array the restrict SQL clause which contains uuid, uuid with first block flipped, * uuid with 3 first block flipped **/ static function getUUIDRestrictCriteria($uuid) { //More infos about uuid, please see wikipedia : //http://en.wikipedia.org/wiki/Universally_unique_identifier //Some uuid are not conform, so preprocessing is necessary //A good uuid likes lik : 550e8400-e29b-41d4-a716-446655440000 //Case one : for example some uuid are like that : //56 4d 77 d0 6b ef 3d da-4d 67 5c 80 a9 52 e2 c9 $pattern = "/([\w]{2})\ ([\w]{2})\ ([\w]{2})\ ([\w]{2})\ "; $pattern .= "([\w]{2})\ ([\w]{2})\ ([\w]{2})\ ([\w]{2})-"; $pattern .= "([\w]{2})\ ([\w]{2})\ ([\w]{2})\ ([\w]{2})\ "; $pattern .= "([\w]{2})\ ([\w]{2})\ ([\w]{2})\ ([\w]{2})/"; if (preg_match($pattern, $uuid)) { $uuid = preg_replace($pattern, "$1$2$3$4-$5$6-$7$8-$9$10-$11$12$13$14$15$16", $uuid); } //Case two : why this code ? Because some dmidecode < 2.10 is buggy. //On unix is flips first block of uuid and on windows flips 3 first blocks... $in = [strtolower($uuid)]; $regexes = [ "/([\w]{2})([\w]{2})([\w]{2})([\w]{2})(.*)/" => "$4$3$2$1$5", "/([\w]{2})([\w]{2})([\w]{2})([\w]{2})-([\w]{2})([\w]{2})-([\w]{2})([\w]{2})(.*)/" => "$4$3$2$1-$6$5-$8$7$9" ]; foreach ($regexes as $pattern => $replace) { $reverse_uuid = preg_replace($pattern, $replace, $uuid); if ($reverse_uuid) { $in[] = strtolower($reverse_uuid); } } return $in; } /** * Find a virtual machine by uuid * * @param fields array of virtualmachine fields * * @return integer|boolean ID of the computer that have this uuid or false otherwise **/ static function findVirtualMachine($fields = []) { global $DB; if (!isset($fields['uuid']) || empty($fields['uuid'])) { return false; } $iterator = $DB->request([ 'SELECT' => 'id', 'FROM' => 'glpi_computers', 'WHERE' => [ 'RAW' => [ 'LOWER(uuid)' => self::getUUIDRestrictCriteria($fields['uuid']) ] ] ]); //Virtual machine found, return ID if (count($iterator) == 1) { $result = $iterator->next(); return $result['id']; } else if (count($iterator) > 1) { Toolbox::logWarning( sprintf( 'findVirtualMachine expects to get one result, %1$s found!', count($iterator) ) ); } return false; } function rawSearchOptions() { $tab = []; $tab[] = [ 'id' => 'common', 'name' => __('Characteristics') ]; $tab[] = [ 'id' => '1', 'table' => $this->getTable(), 'field' => 'name', 'name' => __('Name'), 'datatype' => 'itemlink', 'massiveaction' => false, 'autocomplete' => true, ]; $tab[] = [ 'id' => '2', 'table' => $this->getTable(), 'field' => 'uuid', 'name' => __('UUID'), 'datatype' => 'string', 'massiveaction' => false, 'autocomplete' => true, ]; $tab[] = [ 'id' => '3', 'table' => $this->getTable(), 'field' => 'ram', 'name' => _n('Memory', 'Memories', 1), 'datatype' => 'string', 'massiveaction' => false, 'autocomplete' => true, ]; $tab[] = [ 'id' => '4', 'table' => $this->getTable(), 'field' => 'vcpu', 'name' => __('processor number'), 'datatype' => 'string', 'massiveaction' => false, 'autocomplete' => true, ]; return $tab; } public static function rawSearchOptionsToAdd($itemtype) { $tab = []; $name = _n('Virtual machine', 'Virtual machines', Session::getPluralNumber()); $tab[] = [ 'id' => 'virtualmachine', 'name' => $name ]; $tab[] = [ 'id' => '160', 'table' => self::getTable(), 'field' => 'name', 'name' => __('Name'), 'forcegroupby' => true, 'massiveaction' => false, 'datatype' => 'dropdown', 'joinparams' => [ 'jointype' => 'child' ] ]; $tab[] = [ 'id' => '161', 'table' => 'glpi_virtualmachinestates', 'field' => 'name', 'name' => __('State'), 'forcegroupby' => true, 'massiveaction' => false, 'datatype' => 'dropdown', 'joinparams' => [ 'beforejoin' => [ 'table' => self::getTable(), 'joinparams' => [ 'jointype' => 'child' ] ] ] ]; $tab[] = [ 'id' => '162', 'table' => 'glpi_virtualmachinesystems', 'field' => 'name', 'name' => VirtualMachineSystem::getTypeName(1), 'forcegroupby' => true, 'massiveaction' => false, 'datatype' => 'dropdown', 'joinparams' => [ 'beforejoin' => [ 'table' => self::getTable(), 'joinparams' => [ 'jointype' => 'child' ] ] ] ]; $tab[] = [ 'id' => '163', 'table' => 'glpi_virtualmachinetypes', 'field' => 'name', 'name' => VirtualMachineType::getTypeName(1), 'datatype' => 'dropdown', 'forcegroupby' => true, 'massiveaction' => false, 'joinparams' => [ 'beforejoin' => [ 'table' => self::getTable(), 'joinparams' => [ 'jointype' => 'child' ] ] ] ]; $tab[] = [ 'id' => '164', 'table' => self::getTable(), 'field' => 'vcpu', 'name' => __('processor number'), 'datatype' => 'number', 'forcegroupby' => true, 'massiveaction' => false, 'joinparams' => [ 'jointype' => 'child' ] ]; $tab[] = [ 'id' => '165', 'table' => self::getTable(), 'field' => 'ram', 'name' => _n('Memory', 'Memories', 1), 'datatype' => 'string', 'unit' => 'auto', 'forcegroupby' => true, 'massiveaction' => false, 'joinparams' => [ 'jointype' => 'child' ] ]; $tab[] = [ 'id' => '166', 'table' => self::getTable(), 'field' => 'uuid', 'name' => __('UUID'), 'forcegroupby' => true, 'massiveaction' => false, 'joinparams' => [ 'jointype' => 'child' ] ]; $tab[] = [ 'id' => '179', 'table' => self::getTable(), 'field' => 'comment', 'name' => __('Virtual machine Comment'), 'forcegroupby' => true, 'datatype' => 'string', 'massiveaction' => false, 'joinparams' => [ 'jointype' => 'child' ] ]; return $tab; } }