Opsi – Création d’un produit

Présentation

Opsi

Opsi (Open PC Server Integration) est un outil de gestion de clients Windows basé sur un serveur Linux et sous licence AGPLv3 (hors code des modules cofinancés), version modifiée et orientée serveurs de la licence GPLv3. Son code source est la propriété de la société uib gmgh et son représentant en France/Belgique est la société Opensides.

uibopensides

Ses fonctionnalités principales sont :

  • Installation automatisée via PXE de systèmes d’exploitation clients Windows par le biais d’une image
  • Distribution automatique des logiciels via une connexion agent/serveur
  • Intégration automatique des drivers en se basant sur l’ID de ceux-ci
  • Inventaires matériels et logiciels
  • Dépôts logiciels multiples et décentralisés

 

Objectif

 
L’objectif de cet article est la création pas-à-pas d’un nouveau produit Opsi à déployer sur un parc informatique.
Nous prendrons ici l’exemple de Mozilla Firefox en version 45.7 ESR 32 bits.
Son exécutable portera pour nom Firefox Setup 45.7.0esr.exe.

 

Réalisation

 

1. Adaptation des scripts Opsi Winst

Il faut, dans un premier temps, créer les 3 scripts Opsi Winst setup32.ins, uninstall32.ins et delsub32.ins à partir des templates et les adapter au produit à générer, ici Mozilla Firefox 45.7.0 ESR 32 bits. Ils seront nécessaires à l’étape 3.

1.1. Fichier setup32.ins adapté

[Actions]
requiredWinstVersion >= "4.11.4.6"
ScriptErrorMessages=off

DefVar $MsiId$
DefVar $UninstallProgram$
DefVar $LogDir$
DefVar $ProductId$
DefVar $MinimumSpace$
DefVar $InstallDir$
DefVar $ExitCode$
DefVar $LicenseRequired$
DefVar $LicenseKey$
DefVar $LicensePool$
DefVar $myProperty$

Set $LogDir$ = "%opsiLogDir%"
Set $ProductId$       = "firefox"  
Set $MinimumSpace$    = "100 MB"  
Set $InstallDir$      = "%ProgramFiles32Dir%\Mozilla Firefox"  
Set $LicenseRequired$ = "false"
Set $LicensePool$     = "p_" + $ProductId$

if not(HasMinimumSpace ("%SystemDrive%", $MinimumSpace$))
	LogError "Not enough space on %SystemDrive%, " + $MinimumSpace$ + " on drive %SystemDrive% needed for " + $ProductId$
	isFatalError "No Space"
else
	comment "Show product picture"
	ShowBitmap "%ScriptPath%\" + $ProductId$ + ".png" $ProductId$
	comment "get property value ....."
	set $myProperty$ = getProductProperty("dummy_prop", "yes")
	if $myProperty$ = "yes"
		comment "myproperty value is yes"
	else
		if $myProperty$ = "no"
			comment "myproperty value is no"
		else
			comment "myproperty value must be may_be"
		endif
	endif
	
	if FileExists("%ScriptPath%\delsub32.ins")
		comment "Start uninstall sub section"
		Sub "%ScriptPath%\delsub32.ins"
	endif
	
	Message "Installing " + $ProductId$ + " ..."
	
	if $LicenseRequired$ = "true"
		comment "Licensing required, reserve license and get license key"
		Sub_get_licensekey
	endif
	
	comment "Start setup program"
	ChangeDirectory "%SCRIPTPATH%"
	Winbatch_install
	Sub_check_exitcode
	
	comment "Copy files"
	Files_install /32Bit
	
	comment "Patch Registry"
	Registry_install /32Bit
	
	comment "Create shortcuts"
	LinkFolder_install
	
endif

[Winbatch_install]
"%ScriptPath%\Firefox Setup 45.7.0esr.exe" -ms -ira  

[Files_install]

[Registry_install]

[LinkFolder_install]

[Sub_get_licensekey]
if opsiLicenseManagementEnabled
	comment "License management is enabled and will be used"

	comment "Trying to get a license key"
	Set $LicenseKey$ = demandLicenseKey ($LicensePool$)
	DefVar $ServiceErrorClass$
	set $ServiceErrorClass$ = getLastServiceErrorClass
	comment "Error class: " + $ServiceErrorClass$
	
	if $ServiceErrorClass$ = "None"
		comment "Everything fine, we got the license key '" + $LicenseKey$ + "'"
	else
		if $ServiceErrorClass$ = "LicenseConfigurationError"
			LogError "Fatal: license configuration must be corrected"
			LogError getLastServiceErrorMessage
			isFatalError
		else 
			if $ServiceErrorClass$ = "LicenseMissingError"
				LogError "Fatal: required license is not supplied"
				isFatalError
			endif
		endif
	endif
else
	LogError "Fatal: license required, but license management not enabled"
	isFatalError
endif

[Sub_check_exitcode]
comment "Test for installation success via exit code"
set $ExitCode$ = getLastExitCode

if ($ExitCode$ = "0")
	comment "Looks good: setup program gives exitcode zero"
else
	comment "Setup program gives a exitcode unequal zero: " + $ExitCode$
	if ($ExitCode$ = "1605")
		comment "ERROR_UNKNOWN_PRODUCT	1605	This action is only valid for products that are currently installed."
		comment "Uninstall of a not installed product failed - no problem"
	else
		if ($ExitCode$ = "1641")
			comment "looks good: setup program gives exitcode 1641"
			comment "ERROR_SUCCESS_REBOOT_INITIATED	1641	The installer has initiated a restart. This message is indicative of a success."
		else
			if ($ExitCode$ = "3010")
				comment "looks good: setup program gives exitcode 3010"
				comment "ERROR_SUCCESS_REBOOT_REQUIRED	3010	A restart is required to complete the install. This message is indicative of a success."
			else
				logError "Fatal: Setup program gives an unknown exitcode unequal zero: " + $ExitCode$
				isFatalError
			endif
		endif
	endif
endif

 

1.2. Fichier uninstall32.ins adapté

[Actions]
requiredWinstVersion >= "4.11.4.6"
ScriptErrorMessages=off

DefVar $MsiId$
DefVar $UninstallProgram$
DefVar $LogDir$
DefVar $ExitCode$
DefVar $ProductId$
DefVar $InstallDir$
DefVar $LicenseRequired$
DefVar $LicensePool$

Set $LogDir$ = "%opsiLogDir%"

Set $ProductId$       = "firefox"  
Set $InstallDir$      = "%ProgramFiles32Dir%\Mozilla Firefox"  
Set $LicenseRequired$ = "false"
Set $LicensePool$     = "p_" + $ProductId$

comment "Show product picture"
ShowBitmap "%ScriptPath%\" + $ProductId$ + ".png" $ProductId$

Message "Uninstalling " + $ProductId$ + " ..."

if FileExists("%ScriptPath%\delsub32.ins")
	comment "Start uninstall sub section"
	Sub "%ScriptPath%\delsub32.ins"
endif

if $LicenseRequired$ = "true"
	comment "Licensing required, free license used"
	Sub_free_license
endif

[Sub_free_license]
comment "License management is enabled and will be used"

comment "Trying to free license used for the product"
DefVar $result$
Set $result$ = FreeLicense($LicensePool$)

 

1.3. Fichier delsub32.ins adapté

Set $MsiId$ = '{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}'
Set $UninstallProgram$ = $InstallDir$ + "\uninstall\helper.exe"  

Message "Uninstalling " + $ProductId$ + " ..."

if FileExists($UninstallProgram$)
	comment "Uninstall program found, starting uninstall"
	Winbatch_uninstall
	sub_check_exitcode
endif
if not (GetRegistryStringValue32("[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\" + $MsiId$ + "] DisplayName") = "")
	comment "MSI id " + $MsiId$ + " found in registry, starting msiexec to uninstall"
	Winbatch_uninstall_msi
	sub_check_exitcode
endif

comment "Delete files"
Files_uninstall /32Bit

comment "Cleanup registry"
Registry_uninstall /32Bit

comment "Delete program shortcuts"
LinkFolder_uninstall

[Winbatch_uninstall]
"$UninstallProgram$"   /S

[Winbatch_uninstall_msi]
msiexec /x $MsiId$ /qb-! REBOOT=ReallySuppress

[Files_uninstall]

[Registry_uninstall]

[LinkFolder_uninstall]

[Sub_check_exitcode]
comment "Test for installation success via exit code"
set $ExitCode$ = getLastExitCode

if ($ExitCode$ = "0")
	comment "Looks good: setup program gives exitcode zero"
else
	comment "Setup program gives a exitcode unequal zero: " + $ExitCode$
	if ($ExitCode$ = "1605")
		comment "ERROR_UNKNOWN_PRODUCT	1605	This action is only valid for products that are currently installed."
		comment "Uninstall of a not installed product failed - no problem"
	else
		if ($ExitCode$ = "1641")
			comment "looks good: setup program gives exitcode 1641"
			comment "ERROR_SUCCESS_REBOOT_INITIATED	1641	The installer has initiated a restart. This message is indicative of a success."
		else
			if ($ExitCode$ = "3010")
				comment "looks good: setup program gives exitcode 3010"
				comment "ERROR_SUCCESS_REBOOT_REQUIRED	3010	A restart is required to complete the install. This message is indicative of a success."
			else
				logError "Fatal: Setup program gives an unknown exitcode unequal zero: " + $ExitCode$
				isFatalError
			endif
		endif
	endif
endif

 

2. Génération du nouveau produit vierge

Sur le serveur Opsi, suivre la procédure suivante :

# cd /home/opsiproducts/
# opsi-newprod

Sélectionner le type de produit localboot pour spécifier qu’il s’agit d’un logiciel à déployer (un produit netboot correspond à un système d’exploitation à déployer).

Renseigner les champs indispensables comme l’ID du produit (caractères alphanumériques minuscules et tirets éventuels, mais sans espaces), le Nom du produit (nom complet, espaces acceptés), la version du produit et la version du paquet (1 pour un nouveau paquet). On peut laisser les autres champs avec leurs valeurs par défaut et modifier éventuellement la description.

Spécifier le nom du futur Script de configuration, c’est-à-dire le script d’installation, et le nom du futur Script de désinstallation.

Notre script ne dépendra d’aucun autre produit.

Aucune propriété spécifique au produit ne sera définie.

Renseigner le nom du créateur du produit et son adresse e-mail.

Notre produit a été créé et ajouté dans /home/opsiproducts/, son répertoire source porte le nom de l’ID du produit spécifié plus haut.

Le nouveau produit généré comporte 3 dossiers et 3 fichiers :

# tree firefox/
firefox/
├── CLIENT_DATA/
├── OPSI/
│   ├── control
│   ├── postinst
│   └── preinst
└── SERVER_DATA/

3 directories, 3 files

Tous sont vides sauf le fichier firefox/OPSI/control qui contient les informations spécifiées plus haut lors de la génération du produit.

[Package]
version: 1
depends: 
incremental: False

[Product]
type: localboot
id: firefox
name: Firefox ESR
description: Mozilla Firefox Extended Support Release
advice: 
version: 45.7.0
priority: 0
licenseRequired: False
productClasses: 
setupScript: setup32.ins
uninstallScript: uninstall32.ins
updateScript: 
alwaysScript: 
onceScript: 
customScript: 
userLoginScript: 

[Changelog]
firefox (45.7.0-1) testing; urgency=low

  * Initial package

 -- admin   Fri, 24 Feb 2017 15:46:20 +0000

Il faut ensuite corriger d’éventuels problèmes de propriétaires et de droits sur l’arborescence du produit généré.

# opsi-setup --set-rights firefox/
[5] [Feb 24 15:50:26] Setting rights on directory u'/home/opsiproducts/firefox' (Rights.py|121)

Notre paquet n’apparait pas encore dans la liste des paquets déployables via l’interface de gestion Opsi Configed :

# opsi-package-manager -l firefox
------------------------------
- opsi-test.opensharing.priv -
------------------------------
   Product ID                Version                   Name                   
   ===========================================================================

De même, il n’apparait pas encore dans le répertoire /var/lib/opsi/depot/ sur lequel pointent les partages [opsi_depot] (RO) et [opsi_depot_rw] (RW).
 

3. Création des fichiers constituant le produit

Tout d’abord, il faut déposer les scripts Opsi Winst setup32.ins, uninstall32.ins et delsub32.ins, vus plus haut, dans le répertoire CLIENT_DATA relatif au produit firefox.
Déposer également le fichier image firefox.png (qui s’affichera lors de l’installation du produit) et l’exécutable Firefox Setup 45.7.0esr.exe.
Pour cela, il y a deux possibilités :

  • Déposer les fichiers directement dans /home/opsiproducts/firefox/CLIENT_DATA/
  • Avec l’utilisateur adminuser, membre du groupe pcpatch, monter un lecteur réseau temporaire pointant sur le partage [opsi_workbench] et accéder à firefox/CLIENT_DATA/






Une fois ceci fait, on peut générer le paquet qui sera déployé sur le client.
La commande opsi-makeproductfile crée un fichier respectant la nomenclature IDproduit_versionproduit_versionpaquet.opsi
Il s’agit d’une archive cpio contenant deux autres archives cpio compressées au format gzip : CLIENT_DATA.cpio.gz et OPSI.cpio.gz créées à partir des fichiers inclus dans les répertoires de même nom.

# cd /home/opsiproducts/firefox/
# opsi-makeproductfile

Verrouillage du paquet

Information sur le paquet
----------------------------------------------------------------------------
   version              : 1
   custom package name  : 
   incremental package  : False
   package dependencies : 

Information sur le produit
----------------------------------------------------------------------------
   product id           : firefox
   product type         : localboot
   version              : 45.7.0
   name                 : Firefox ESR
   description          : Mozilla Firefox Extended Support Release
   advice               : 
   priority             : 0
   licenseRequired      : False
   product classes      : 
   windows software ids : 

Scripts du produit
----------------------------------------------------------------------------
   setup                : setup32.ins
   uninstall            : uninstall32.ins
   update               : 
   always               : 
   once                 : 
   custom               : 
   user login           : 

Création du fichier pour le paquet '/home/opsiproducts/firefox/firefox_45.7.0-1.opsi'

Creating archive CLIENT_DATA.cpio.gz
  100.00% [==================================================]
Creating archive OPSI.cpio.gz
  100.00% [==================================================]
Creating archive firefox_45.7.0-1.opsi
  100.00% [==================================================]

Nettoyage
Déverrouillage du paquet

 
L’arborescence finale du répertoire CLIENT_DATA est la suivante :

  • 3 fichiers de script
  • 1 fichier image
  • 1 exécutable
  • 1 archive cpio à déployer
# tree /home/opsiproducts/firefox/
/home/opsiproducts/firefox/
├── CLIENT_DATA/
│   ├── delsub32.ins
│   ├── firefox.png
│   ├── Firefox Setup 45.7.0esr.exe
│   ├── setup32.ins
│   └── uninstall32.ins
├── firefox_45.7.0-1.opsi
├── OPSI/
│   ├── control
│   ├── postinst
│   └── preinst
└── SERVER_DATA/

3 directories, 9 files

 

4. Intégration du produit à l’interface Opsi Configed

# opsi-package-manager -i firefox_45.7.0-1.opsi

 
Ceci a pour effet de générer le fichier /var/lib/opsi/config/products/firefox_45.7.0-1.localboot, copie du fichier control du paquet.
 
Notre produit est bien listé parmi les produits déployables :

# opsi-package-manager -l firefox
------------------------------
- opsi-test.opensharing.priv -
------------------------------
   Product ID                Version                   Name                   
   ===========================================================================
   firefox                   45.7.0-1                  Firefox ESR            

 
Il apparait sur l’interface Opsi Configed avec les informations renseignées lors de la génération du produit.

Et c’est lors de cette intégration à Opsi Configed que notre paquet apparait désarchivé et décompressé dans /var/lib/opsi/depot/. Les partages [opsi_depot] (RO) et [opsi_depot_rw] (RW) pointent sur ce dossier et le partage [opsi_depot], donc en lecture seule, sera monté sur le client avec l’utilisateur adminuser (membre du groupe pcpatch) et un montage temporaire sur la lettre P: afin de procéder à l’installation ou la désinstallation du produit.

smb://opsi-test/opsi_depot P:

 

# ls -lA /var/lib/opsi/depot/firefox/
total 43148
-rw-rw----  1 opsiconfd pcpatch     2051 févr. 25 14:27 delsub32.ins
-rw-rw----  1 opsiconfd pcpatch      296 févr. 25 14:42 firefox.files
-rw-rw----  1 opsiconfd pcpatch    40428 mai   23  2013 firefox.png
-rw-rw----  1 opsiconfd pcpatch 44124744 févr. 25 14:29 Firefox Setup 45.7.0esr.exe
-rw-rw----  1 opsiconfd pcpatch     3890 févr. 25 14:26 setup32.ins
-rw-rw----  1 opsiconfd pcpatch     1034 févr. 25 14:27 uninstall32.ins

On y retrouve le contenu du dossier /home/opsiproducts/firefox/CLIENT_DATA/ mais aussi un fichier portant le nom de l’ID du produit avec l’extension .files, firefox.files, contenant la liste des fichiers requis pour le paquet :

f 'Firefox Setup 45.7.0esr.exe' 44124744 ef87a5ac0012a13e223481507fd75e6c
f 'delsub32.ins' 2051 cf14f019f077e57e118bc16ea2eb9dbe
f 'firefox.png' 40428 c638484624813ccb10e141e98a5a50db
f 'setup32.ins' 3890 fc4fe9fb5eaa3d22ff655067912d5127
f 'uninstall32.ins' 1034 f21b6cc8255192b338683f0a6d3a26d8

 

5. Déploiement du nouveau produit sur un client

Pour installer le produit Firefox sur notre client, il faut tout d’abord définir le champs Action sur setup (clic gauche).

Puis enregistrer la configuration modifiée avec un clic droit et Sauver.

  • Si l’on souhaiter déployer immédiatement le produit, il suffit de faire un nouveau clic droit et sélectionner Exécuter maintenant ("on_demand").
  • Si l’on souhaite que l’installation se fasse au prochain redémarrage/démarrage du client, il n’y a rien d’autre à faire.


 
Comme il s’agit d’une première installation, la désinstallation préalable n’a pas lieu car le fichier C:\Program Files\Mozilla Firefox\uninstall\helper.exe n’existe pas encore, comme nous pouvons le voir dans les logs (côté client et côté serveur).

(20819)   [6] [févr. 24 16:20:09:379] [firefox]     If
(20820)   [5] [févr. 24 16:20:09:379] [firefox]       Starting query if file exist ...
(20821)   [5] [févr. 24 16:20:09:379] [firefox]         "C:\Program Files\Mozilla Firefox\uninstall\helper.exe": 
(20822)   [5] [févr. 24 16:20:09:379] [firefox]       FileExists($UninstallProgram$)   <<< result false
(20823)   [6] [févr. 24 16:20:09:379] [firefox]     Then
(20824)   [6] [févr. 24 16:20:09:379] [firefox]     EndIf

 
La procédure de désinstallation est identique, il suffit de programmer un uninstall sur Opsi Configed, de sauver, puis d'exécuter à la demande ou attendre le prochain redémarrage.

 

Aller plus loin

 

Opsi - Installation du serveur Part1 Opsi - Installation du serveur Part2
Opsi - Creation d'une image Windows 7 Opsi - Installation d'un client Windows 7
Opsi - Creation d'une image Windows 10 Opsi - Installation d'un client Windows 10
Opsi - Creation d'une image Windows XP Opsi - Installation d'un client Windows XP
Opsi - Pour aller plus loin Opsi - Fonctionnement des scripts
Opsi - Exemples de scripts Opsi - Script de test local
Opsi - Scripts avancés Opsi - Création d'un produit
Opsi - Commandes utiles Opsi - Package activate-win Officiel
Opsi - Package windomain Officiel

 

Fermer le menu
%d blogueurs aiment cette page :