Ou comment séparer la définition de l’affichage des tâches.
Voici un problème qui m’a été posé par un de nos clients : comment réutiliser des tâches définies dans un premier Management Pack dans un ou plusieurs autres MP, sans avoir à les recoder à chaque fois ? Après recherche, voici la solution qui a été retenue.
Prenons un exemple simple : via la console Authoring, créons dans un nouveau management pack une tâche console qui lance la calculatrice Windows.
Une fois enregistré non-scellé, le code xml de ce management pack très basique est le suivant :
<ManagementPack ContentReadable="true" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<Manifest>
<Identity>
<ID>MP_ExempleTask</ID>
<Version>1.0.0.0</Version>
</Identity>
<Name>MP_ExempleTask</Name>
<References>
<Reference Alias="Windows">
<ID>Microsoft.Windows.Library</ID>
<Version>6.1.7221.0</Version>
<PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
</Reference>
<Reference Alias="System">
<ID>System.Library</ID>
<Version>6.1.7221.0</Version>
<PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
</Reference>
</References>
</Manifest>
<TypeDefinitions>
<ModuleTypes>
<ProbeActionModuleType ID="calcType" Accessibility="Public" Batching="false" PassThrough="false">
<Configuration />
<ModuleImplementation Isolation="Any">
<Composite>
<MemberModules>
<ProbeAction ID="PA" TypeID="System!System.CommandExecuterProbe">
<ApplicationName><![CDATA[%WINDIR%\System32\calc.EXE]]></ApplicationName>
<WorkingDirectory />
<CommandLine>/ALL</CommandLine>
<TimeoutSeconds>30</TimeoutSeconds>
<RequireOutput>true</RequireOutput>
<Files />
</ProbeAction>
</MemberModules>
<Composition>
<Node ID="PA" />
</Composition>
</Composite>
</ModuleImplementation>
<OutputType>System!System.PropertyBagData</OutputType>
<InputType>System!System.BaseData</InputType>
</ProbeActionModuleType>
</ModuleTypes>
</TypeDefinitions>
<Presentation>
<ConsoleTasks>
<ConsoleTask ID="Task.LocalCalc" Accessibility="Internal" Enabled="true" Target="System!System.Entity" RequireOutput="true" Category="MonitoringObject">
<Application>%systemroot%\system32\calc.exe</Application>
<WorkingDirectory />
</ConsoleTask>
</ConsoleTasks>
</Presentation>
<LanguagePacks>
<LanguagePack ID="FRA" IsDefault="false">
<DisplayStrings>
<DisplayString ElementID="MP_ExempleTask">
<Name>MP Exemple Task</Name>
</DisplayString>
</DisplayStrings>
</LanguagePack>
<LanguagePack ID="ENU" IsDefault="true">
<DisplayStrings>
<DisplayString ElementID="Task.LocalCalc">
<Name>Ouvrir Calculatrice</Name>
<Description />
</DisplayString>
<DisplayString ElementID="MP_ExempleTask">
<Name>MP Exemple Task</Name>
</DisplayString>
</DisplayStrings>
</LanguagePack>
</LanguagePacks>
</ManagementPack>
La suite de la manœuvre implique d’utiliser un éditeur de texte : il va falloir séparer les parties « manifest », « défintion » et « affichage » de votre management pack.
Le manifest est le code compris entre les balises <Manifest></Manifest> (surligné plus haut en vert) :
<Manifest>
<Identity>
<ID>MP_ExempleTask</ID>
<Version>1.0.0.0</Version>
</Identity>
<Name>MP_ExempleTask</Name>
<References>
<Reference Alias="Windows">
<ID>Microsoft.Windows.Library</ID>
<Version>6.1.7221.0</Version>
<PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
</Reference>
<Reference Alias="System">
<ID>System.Library</ID>
<Version>6.1.7221.0</Version>
<PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
</Reference>
</References>
</Manifest>
La partie définition est l’ensemble du code compris entre les balises <TypeDefinitions>[…]</TypeDefinitions> (surligné plus haut en bleu). C’est cette partie qui contient le code de « ce que font » les tâches à proprement parler :
<TypeDefinitions>
<ModuleTypes>
<ProbeActionModuleType ID="calcType" Accessibility="Public" Batching="false" PassThrough="false">
<Configuration />
<ModuleImplementation Isolation="Any">
<Composite>
<MemberModules>
<ProbeAction ID="PA" TypeID="System!System.CommandExecuterProbe">
<ApplicationName><![CDATA[%WINDIR%\System32\calc.EXE]]></ApplicationName>
<WorkingDirectory />
<CommandLine>/ALL</CommandLine>
<TimeoutSeconds>30</TimeoutSeconds>
<RequireOutput>true</RequireOutput>
<Files />
</ProbeAction>
</MemberModules>
<Composition>
<Node ID="PA" />
</Composition>
</Composite>
</ModuleImplementation>
<OutputType>System!System.PropertyBagData</OutputType>
<InputType>System!System.BaseData</InputType>
</ProbeActionModuleType>
</ModuleTypes>
</TypeDefinitions>
La partie “affichage” est quant à elle celle qui est comprise entre les balises <Presentation>[…]</LanguagePacks> (surlignée plus haut en rouge). C’est cette partie qui se charge de faire apparaitre les tâches dans la console SCOM :
<Presentation>
<ConsoleTasks>
<ConsoleTask ID="Task.LocalCalc" Accessibility="Internal" Enabled="true" Target="System!System.Entity" RequireOutput="true" Category="MonitoringObject">
<Application>%systemroot%\system32\calc.exe</Application>
<WorkingDirectory />
</ConsoleTask>
</ConsoleTasks>
</Presentation>
<LanguagePacks>
<LanguagePack ID="FRA" IsDefault="false">
<DisplayStrings>
<DisplayString ElementID="MP_ExempleTask">
<Name>MP Exemple Task</Name>
</DisplayString>
</DisplayStrings>
</LanguagePack>
<LanguagePack ID="ENU" IsDefault="true">
<DisplayStrings>
<DisplayString ElementID="Task.LocalCalc">
<Name>Ouvrir Calculatrice</Name>
<Description />
</DisplayString>
<DisplayString ElementID="MP_ExempleTask">
<Name>MP Exemple Task</Name>
</DisplayString>
</DisplayStrings>
</LanguagePack>
</LanguagePacks>
Vous avez isolé ces deux parties? Bien, nous allons pouvoir passer à la suite : il faut maintenant construire deux management packs séparés, et ce toujours à l’aide d’un éditeur de texte.
En toute logique, le premier contiendra la partie définitions et le second la partie affichage… ainsi que quelques subtilités :
Pour le premier, c’est assez simple. Créons un fichier texte que nous nommerons par exemple mp1.xml et copions-y la partie « définition » préalablement extraite, précédée du manifest, le tout encadré par les balises <ManagementPack> nécessaires à la conformité de tout MP :
<ManagementPack ContentReadable="true" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<Manifest>
<Identity>
<ID>MP1</ID>
<Version>1.0.0.0</Version>
</Identity>
<Name>MP1</Name>
<References>
<Reference Alias="Windows">
<ID>Microsoft.Windows.Library</ID>
<Version>6.1.7221.0</Version>
<PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
</Reference>
<Reference Alias="System">
<ID>System.Library</ID>
<Version>6.1.7221.0</Version>
<PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
</Reference>
</References>
</Manifest>
<TypeDefinitions>
<ModuleTypes>
<ProbeActionModuleType ID="calcType" Accessibility="Public" Batching="false" PassThrough="false">
<Configuration />
<ModuleImplementation Isolation="Any">
<Composite>
<MemberModules>
<ProbeAction ID="PA" TypeID="System!System.CommandExecuterProbe">
<ApplicationName><![CDATA[%WINDIR%\System32\calc.EXE]]></ApplicationName>
<WorkingDirectory />
<CommandLine>/ALL</CommandLine>
<TimeoutSeconds>30</TimeoutSeconds>
<RequireOutput>true</RequireOutput>
<Files />
</ProbeAction>
</MemberModules>
<Composition>
<Node ID="PA" />
</Composition>
</Composite>
</ModuleImplementation>
<OutputType>System!System.PropertyBagData</OutputType>
<InputType>System!System.BaseData</InputType>
</ProbeActionModuleType>
</ModuleTypes>
</TypeDefinitions>
</ManagementPack>
Notez que j’ai également modifié l’ID et le Nom de ce MP, qui s’appelle désormais “MP1”.
Une fois ce fichier XML achevé, il faudra le sauvegarder en tant que Management Pack scellé et noter sa clé publique ; autrement il ne sera pas possible de l’importer dans les MP qui devront y faire appel, puisqu’on ne peut pas hériter d’un MP non scellé.
Passons ensuite au MP2 : il contient également le Manifest (auquel j’ai apporté quelques modifications, détaillées plus bas), suivi cette fois uniquement de la partie affichage :
<ManagementPack ContentReadable="true" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<Manifest>
<Identity>
<ID>MP2</ID>
<Version>1.0.0.0</Version>
</Identity>
<Name>MP2</Name>
<References>
<Reference Alias="Windows">
<ID>Microsoft.Windows.Library</ID>
<Version>6.1.7221.0</Version>
<PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
</Reference>
<Reference Alias="MP1">
<ID>TaskMP1</ID>
<Version>1.0.0.0</Version>
<PublicKeyToken>0823A712C344907</PublicKeyToken>
</Reference>
</References>
</Manifest>
<Presentation>
<ConsoleTasks>
<ConsoleTask ID="Task.LocalCalc" Accessibility="Internal" Enabled="true" Target="System!System.Entity" RequireOutput="true" Category="MonitoringObject">
<Application>%systemroot%\system32\calc.exe</Application>
<WorkingDirectory />
</ConsoleTask>
</ConsoleTasks>
</Presentation>
<LanguagePacks>
<LanguagePack ID="FRA" IsDefault="false">
<DisplayStrings>
<DisplayString ElementID="MP_ExempleTask">
<Name>MP Exemple Task</Name>
</DisplayString>
</DisplayStrings>
</LanguagePack>
<LanguagePack ID="ENU" IsDefault="true">
<DisplayStrings>
<DisplayString ElementID="Task.LocalCalc">
<Name>Ouvrir Calculatrice</Name>
<Description />
</DisplayString>
<DisplayString ElementID="MP_ExempleTask">
<Name>MP Exemple Task</Name>
</DisplayString>
</DisplayStrings>
</LanguagePack>
</LanguagePacks>
</ManagementPack>
Comme vous pouvez le voir dans la partie surlignée, le MP2 hérite du MP1.
Nous avons donc désormais un MP1.mp (MP1 scellé) et un MP2.xml, qu’il ne reste plus qu’à importer dans la console SCOM l’un après l’autre : les tâches stockées dans le MP1 et appelées dans le MP2 apparaissent bien.
Il sera par la suite possible d’appeler de la même façon les tâches définies dans le MP1 dans autant de management packs « enfants » que nécessaire.