Automated installation
The installation of iTop is generally performed interactively using the “setup” page. However once information about the desired configuration has been collected by the setup page, the actual installation process is fully unattended and therefore can be automated.
In order to automate the iTop installation you'll need:
-
An XML response file containing the desired configuration options
-
The unattened_install.php script (see below)
Response file
The response file is an XML file containing all the answers / choices to configure the application.
An example of the response file is the following:
- default-params.xml
-
<?xml version="1.0" encoding="UTF-8"?> <installation> <mode>install</mode> <preinstall> <copies type="array"> <copy> <source>C:\inetpub\wwwroot\setup20\datamodel</source> <destination>test_copy</destination> </copy> </copies> <backup> <configuration_file>../conf/production/config-itop.php</configuration_file> <destination>../backups/__DB__-%Y-%m-%d.zip</destination> </backup> </preinstall> <source_dir>datamodel</source_dir> <source_env>production</source_env> <target_env>production</target_env> <workspace_dir/> <database> <server>localhost</server> <user>root</user> <pwd>root</pwd> <name>setup20</name> <prefix></prefix> </database> <url>http://localhost/setup20/</url> <admin_account> <user>admin</user> <pwd>admin</pwd> <language>FR FR</language> </admin_account> <language>IT IT</language> <selected_modules type="array"> <module>authent-local</module> <module>itop-attachments</module> <module>itop-welcome-itil</module> <module>itop-profiles-itil</module> <module>itop-config-mgmt</module> <module>itop-service-mgmt</module> <module>itop-tickets</module> </selected_modules> <sample_data>1</sample_data> <options> <symlinks>1</symlinks> <mysql_bin_dir></mysql_bin_dir> </options> </installation>
Generating the reponse file
The response file can be created manually using a text editor or
generated by running the interactive setup with the additional
parameter option[generate_config]=1
.
This is achieved by adding
?option[generate_config]=1
at the end of the
URL to specify this
extra parameter. This gives the following sample URL:
http://localhost/itop/setup/?option[generate_config]=1
Then run the setup as usual, but instead of launching the installation, stop at the “summary” step, and click on “XML config file” to open this section of the summary. You can then copy/paste the response file:
Another way to get a response file is to retrieve the
installation.xml
file from an existing iTop
installation. Each time the iTop installation completes, it creates
a file install-<date>-<revision>.xml
in
the log
directory of an existing iTop installation.
You can use this file for automatically installing another instance
of iTop with the exact same parameters.
Unattended installation script
The following PHP script can be used to automated the installation of iTop:
- unattended_install.php
-
<?php <?php require_once('../approot.inc.php'); require_once(APPROOT.'/application/utils.inc.php'); require_once(APPROOT.'/application/clipage.class.inc.php'); require_once(APPROOT.'/core/config.class.inc.php'); require_once(APPROOT.'/core/log.class.inc.php'); require_once(APPROOT.'/core/kpi.class.inc.php'); require_once(APPROOT.'/core/cmdbsource.class.inc.php'); require_once(APPROOT.'/setup/setuppage.class.inc.php'); require_once(APPROOT.'/setup/wizardcontroller.class.inc.php'); require_once(APPROOT.'/setup/wizardsteps.class.inc.php'); require_once(APPROOT.'/setup/applicationinstaller.class.inc.php'); ///////////////////////////////////////////////// $sParamFile = utils::ReadParam('response_file', 'default-params.xml', true /* CLI allowed */, 'raw_data'); $bCheckConsistency = (utils::ReadParam('check_consistency', '0', true /* CLI allowed */) == '1'); $oParams = new XMLParameters($sParamFile); $sMode = $oParams->Get('mode'); if ($sMode == 'install') { echo "Installation mode detected.\n"; $bClean = utils::ReadParam('clean', false, true /* CLI allowed */); if ($bClean) { echo "Cleanup mode detected.\n"; $sTargetEnvironment = $oParams->Get('target_env', ''); if ($sTargetEnvironment == '') { $sTargetEnvironment = 'production'; } $sTargetDir = APPROOT.'env-'.$sTargetEnvironment; // Configuration file $sConfigFile = APPCONF.$sTargetEnvironment.'/'.ITOP_CONFIG_FILE; if (file_exists($sConfigFile)) { echo "Trying to delete the configuration file: '$sConfigFile'.\n"; @chmod($sConfigFile, 0770); // RWX for owner and group, nothing for others unlink($sConfigFile); } else { echo "No config file to delete ($sConfigFile does not exist).\n"; } // env-xxx directory if (file_exists($sTargetDir)) { if (is_dir($sTargetDir)) { echo "Emptying the target directory '$sTargetDir'.\n"; SetupUtils::tidydir($sTargetDir); } else { die("ERROR the target dir '$sTargetDir' exists, but is NOT a directory !!!\nExiting.\n"); } } else { echo "No target directory to delete ($sTargetDir does not exist).\n"; } // Database $aDBSettings = $oParams->Get('database', array()); $sDBServer = $aDBSettings['server']; $sDBUser = $aDBSettings['user']; $sDBPwd = $aDBSettings['pwd']; $sDBName = $aDBSettings['name']; $sDBPrefix = $aDBSettings['prefix']; if ($sDBPrefix != '') { die("Cleanup not implemented for a partial database (prefix= '$sDBPrefix')\nExiting."); } $oMysqli = new mysqli($sDBServer, $sDBUser, $sDBPwd); if ($oMysqli->connect_errno) { die("Cannot connect to the MySQL server (".$mysqli->connect_errno . ") ".$mysqli->connect_error."\nExiting"); } else { if ($oMysqli->select_db($sDBName)) { echo "Deleting database '$sDBName'\n"; $oMysqli->query("DROP DATABASE `$sDBName`"); } else { echo "The database '$sDBName' does not seem to exist. Nothing to cleanup.\n"; } } } } else { $aDBSettings = $oParams->Get('database', array()); $sDBServer = $aDBSettings['server']; $sDBUser = $aDBSettings['user']; $sDBPwd = $aDBSettings['pwd']; $sDBName = $aDBSettings['name']; $sDBPrefix = $aDBSettings['prefix']; $sTargetEnvironment = $oParams->Get('target_env', ''); if ($sTargetEnvironment == '') { $sTargetEnvironment = 'production'; } $sTargetDir = APPROOT.'env-'.$sTargetEnvironment; } $bHasErrors = false; $aChecks = SetupUtils::CheckBackupPrerequisites(APPROOT.'data'); // mmm should be the backup destination dir $aSelectedModules = $oParams->Get('selected_modules'); $sSourceDir = $oParams->Get('source_dir', 'datamodels/latest'); $sExtensionDir = $oParams->Get('extensions_dir', 'extensions'); $aChecks = array_merge($aChecks, SetupUtils::CheckSelectedModules($sSourceDir, $sExtensionDir, $aSelectedModules)); foreach($aChecks as $oCheckResult) { switch($oCheckResult->iSeverity) { case CheckResult::ERROR: $bHasErrors = true; $sHeader = "Error"; break; case CheckResult::WARNING: $sHeader = "Warning"; break; case CheckResult::INFO: default: $sHeader = "Info"; break; } echo $sHeader.": ".$oCheckResult->sLabel; if (strlen($oCheckResult->sDescription)) { echo ' - '.$oCheckResult->sDescription; } echo "\n"; } if ($bHasErrors) { echo "Encountered stopper issues. Aborting...\n"; die; } $bFoundIssues = false; $bInstall = utils::ReadParam('install', true, true /* CLI allowed */); if ($bInstall) { echo "Starting the unattended installation...\n"; $oWizard = new ApplicationInstaller($oParams); $bRes = $oWizard->ExecuteAllSteps(); if (!$bRes) { echo "\nencountered installation issues!"; $bFoundIssues = true; } else { $oMysqli = new mysqli($sDBServer, $sDBUser, $sDBPwd); if (!$oMysqli->connect_errno) { if ($oMysqli->select_db($sDBName)) { // Check the presence of a table to record information about the MTP (from the Designer) $sDesignerUpdatesTable = $sDBPrefix.'priv_designer_update'; $sSQL = "SELECT id FROM `$sDesignerUpdatesTable`"; if ($oMysqli->query($sSQL) !== false) { // Record the Designer Udpates in the priv_designer_update table $sDeltaFile = APPROOT.'data/'.$sTargetEnvironment.'.delta.xml'; if (is_readable($sDeltaFile)) { // Retrieve the revision $oDoc = new DOMDocument(); $oDoc->load($sDeltaFile); $iRevision = 0; $iRevision = $oDoc->firstChild->getAttribute('revision_id'); if ($iRevision > 0) // Safety net, just in case... { $sDate = date('Y-m-d H:i:s'); $sSQL = "INSERT INTO `$sDesignerUpdatesTable` (revision_id, compilation_date, comment) VALUES ($iRevision, '$sDate', 'Deployed using unattended.php.')"; if ($oMysqli->query($sSQL) !== false) { echo "\nDesigner update (MTP at revision $iRevision) successfully recorded.\n"; } else { echo "\nFailed to record designer updates(".$oMysqli->error.").\n"; } } else { echo "\nFailed to read the revision from $sDeltaFile file. No designer update information will be recorded.\n"; } } else { echo "\nNo $sDeltaFile file (or the file is not accessible). No designer update information to record.\n"; } } } } } } else { echo "No installation requested.\n"; } if (!$bFoundIssues && $bCheckConsistency) { echo "Checking data model consistency.\n"; ob_start(); $sCheckRes = ''; try { MetaModel::CheckDefinitions(false); $sCheckRes = ob_get_clean(); } catch(Exception $e) { $sCheckRes = ob_get_clean()."\nException: ".$e->getMessage(); } if (strlen($sCheckRes) > 0) { echo $sCheckRes; echo "\nfound consistency issues!"; $bFoundIssues = true; } } if (!$bFoundIssues) { // last line: used to check the install // the only way to track issues in case of Fatal error or even parsing error! echo "\ninstalled!"; exit; }
Execution of the unattended installation
Copy the unattended_install.php
script in a
toolkit
directory at the root of iTop files. Then
launch the script with the following command:
php unattended_install.php default-params.xml
Where:
-
default-params.xml
is the reponse file containing your desired settings for the installation