Archive

Articles taggués ‘Virtualisation’

VMware Server 2 – Nom du Datacenter par defaut

Aujourd’hui j’ai un peu joué avec jASMINe VMM pour comparer ses fonctionnalités avec ProActive VMM. Pendant la configuration de VMM-Agent, il faut préciser le nom du datacenter et du répertoire de machines virtuelles dans lesquels vous voulez travailler… Selon Virtual Infrastructure SDK Documentation, il apparaît qu’il n’existe qu’un seul datacenter pour les hôtes ( ESX host ou VMware Server 2 par exemple ), mais je n’ai rien trouvé dans la documentation à propos des noms… J’ai donc légèrement modifié ProActive VMM pour afficher les noms du datacenter par défaut et du répertoire de machines virtuelles:

Datacenterha-datacenter

VM-Folder: vm

Les hyperviseurs les plus utilisés

Le plus utilisé, sans surprise, VMware ESX… Le second, plus surprenant pour le coup, VMware Server 2. Chose intéressante pour moi qu’un hyperviseur de type 2 soit dans le classement. Respectivement aux 3 et 4 ièm places,  Microsoft Hyper-V et Citrix XenServer, mais ceux-ci enregistrant un progrès de plus de 200%…

source

VirtualBox protocol error

Que faire lorsque les répertoires partagés vous donnent du fil a retordre?

Si, comme moi, vous avez besoin d’évaluer le plus de versions de VirtualBox possible, vous upgradez très souvent. Heureusement, comme cela doit être le cas pour les logiciels de virtualisation de plateforme matérielle, les machines virtuelles restent compatibles avec toutes les versions du logiciel ( ou au moins espérons le ). Jusqu’à ce matin, je n’est jamais eu de problème avec VB. Mais aujourd’hui, j’ai cru ma journée gâchée à cause d’un:

/sbin/mount.vboxsf: mounting failed with the error: Protocol error

Problème réglé rapidement, après simple ré-installation des aditions client… Journée sauvée ;)

Passage de paramètres XML CIM avec WinRM

L’information que je partage ici ne se trouve pas à l’heure actuelle dans le réseau ou forums MSDN. Cela m’a valu quelques conversations que vous pouvez relire sur le post MSDN dédié.

Le problème venait du fait qu’il n’est spécifié nulle part la façon dont doivent être écrites les instances XML CIM lors d’un appel de méthode via WinRM. WinRM est un outil très puissant, mais pour certains espaces de noms, il est impossible de créer des instances/objets à la main. A la place, nous devons avoir recours à des methodes utilitaires. C’est le cas par exemple pour l’ajout de paires Clé/Valeur à un Msvm_ComputerSystem ( ie. Machine Virtuelle pour les non initiés à l’implémentation CIM de Microsoft ). La spécification CIM prévoit la description d’objets sous forme XML et c’est bien ça qui nous pause problème… Il n’y a absolument aucun endroit dans toute la documentation MSDN et DMTF où il est spécifié la manière dont ces instances doivent être écrites. La spécification WS-MAN dit que l’entrée d’une méthode est un fragment XML. Le comportement normal de tout être humain ( moi compris ) serait de passer simplement le fragment XML représentant l’instance CIM à la méthode. Si vous pensez comme moi, vous avez certainement écrit quelque chose comme ça:

<p:AddKvpItems_INPUT xmlns:p="http://schemas.microsoft.com/wbem/wsman/1/wmi/root/virtualization/Msvm_VirtualSystemManagementService">
    <p:TargetSystem xmlns:a="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:w="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd" >
        <a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address>
        <a:ReferenceParameters>
            <w:ResourceURI>http://schemas.microsoft.com/wbem/wsman/1/wmi/root/virtualization/Msvm_ComputerSystem</w:ResourceURI>
            <w:SelectorSet>
                <w:Selector Name="CreationClassName">Msvm_ComputerSystem</w:Selector>
                <w:Selector Name="Name">3AA32387-6924-448C-835D-06E63A624C3E</w:Selector>
            </w:SelectorSet>
        </a:ReferenceParameters>
    </p:TargetSystem>
    <p:DataItems>
        <INSTANCE xmlns:p="http://schemas.microsoft.com/wbem/wsman/1/wmi/root/virtualization/Msvm_KvpExchangeDataItem" CLASSNAME="Msvm_KvpExchangeDataItem">
            <QUALIFIER NAME="dynamic" PROPAGATED="true" TYPE="boolean" TOSUBCLASS="false" TOINSTANCE="true">TRUE</QUALIFIER>
            <PROPERTY NAME="__PATH" CLASSORIGIN="___SYSTEM" TYPE="string"></PROPERTY>
            <PROPERTY NAME="__NAMESPACE" CLASSORIGIN="___SYSTEM" TYPE="string"></PROPERTY>
            <PROPERTY NAME="__SERVER" CLASSORIGIN="___SYSTEM" TYPE="string"></PROPERTY>
            <PROPERTY.ARRAY NAME="__DERIVATION" CLASSORIGIN="___SYSTEM"    TYPE="string">
                <VALUE.ARRAY>CIM_ManagedElement</VALUE.ARRAY>
            </PROPERTY.ARRAY>
            <PROPERTY NAME="__PROPERTY_COUNT" CLASSORIGIN="___SYSTEM" TYPE="sint32">6</PROPERTY>
            <PROPERTY NAME="__RELPATH" CLASSORIGIN="___SYSTEM" TYPE="string"></PROPERTY>
            <PROPERTY NAME="__DYNASTY" CLASSORIGIN="___SYSTEM" TYPE="string">CIM_ManagedElement</PROPERTY>
            <PROPERTY NAME="__SUPERCLASS" CLASSORIGIN="___SYSTEM" TYPE="string">CIM_ManagedElement</PROPERTY>
            <PROPERTY NAME="__CLASS" CLASSORIGIN="___SYSTEM" TYPE="string">Msvm_KvpExchangeDataItem</PROPERTY>
            <PROPERTY NAME="__GENUS" CLASSORIGIN="___SYSTEM" TYPE="sint32">2</PROPERTY>
            <PROPERTY NAME="Caption" CLASSORIGIN="CIM_ManagedElement" PROPAGATED="true" TYPE="string">
                <QUALIFIER NAME="CIMTYPE" PROPAGATED="true" TYPE="string" TOINSTANCE="true">string</QUALIFIER>
            </PROPERTY>
            <PROPERTY NAME="Data" CLASSORIGIN="Msvm_KvpExchangeDataItem" PROPAGATED="true" TYPE="string">
                <QUALIFIER NAME="CIMTYPE" PROPAGATED="true" TYPE="string" TOINSTANCE="true">myNewValue</QUALIFIER>
            </PROPERTY>
            <PROPERTY NAME="Description" CLASSORIGIN="CIM_ManagedElement" PROPAGATED="true" TYPE="string">
                <QUALIFIER NAME="CIMTYPE" PROPAGATED="true" TYPE="string" TOINSTANCE="true">string</QUALIFIER>
            </PROPERTY>
            <PROPERTY NAME="ElementName" CLASSORIGIN="CIM_ManagedElement" PROPAGATED="true" TYPE="string">
                <QUALIFIER NAME="CIMTYPE" PROPAGATED="true" TYPE="string" TOINSTANCE="true">string</QUALIFIER>
            </PROPERTY>
            <PROPERTY NAME="Name" CLASSORIGIN="Msvm_KvpExchangeDataItem" PROPAGATED="true" TYPE="string">
                <QUALIFIER NAME="CIMTYPE" PROPAGATED="true" TYPE="string" TOINSTANCE="true">myNewKey</QUALIFIER>
            </PROPERTY>
            <PROPERTY NAME="Source" CLASSORIGIN="Msvm_KvpExchangeDataItem" PROPAGATED="true" TYPE="uint16">
                <QUALIFIER NAME="CIMTYPE" PROPAGATED="true" TYPE="string" TOINSTANCE="true">0</QUALIFIER>
            </PROPERTY>
        </INSTANCE>
    </p:DataItems>
</p:AddKvpItems_INPUT>

Et vous vous êtes également fait insulter de la sorte:

WSManFault
    Message
        ProviderFault
            WSManFault
                Message = The WS-Management service cannot process the request because a date-time element or simple property contains child elements.
            ExtendedError
                __ExtendedStatus
                    Description = null
                    Operation = GetObject
                    ParameterInfo = Msvm_ComputerSystem.CreationClassName="Msvm_ComputerSystem",Name="3AA32387-6924-448C-835D-06E63A624C3E"
                    ProviderName = VmmsWmiInstanceAndMethodProvider
                    StatusCode = null
 
Numéro d'erreur :  -2144108479 0x80338041
Le code XML SOAP du message ne correspond pas à la définition du schéma XML. Modifiez le code XML et réessayez.

Pas réellement utile comme message d’érreur… Je vais faire cours, mais après énormément d’essais, j’ai trouvé le moyen permettant de faire marcher tout ça, il faut échapper les chevrons < and > et faire très attention aux caractères blancs… voici le contenu correct:

    <AddKvpItems_INPUT xmlns:p="http://schemas.microsoft.com/wbem/wsman/1/wmi/root/virtualization/Msvm_VirtualSystemManagementService">
      <p:TargetSystem
        xmlns:a="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:w="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd">
        <a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address>
        <a:ReferenceParameters>
          <w:ResourceURI>http://schemas.microsoft.com/wbem/wsman/1/wmi/root/virtualization/Msvm_ComputerSystem</w:ResourceURI>
          <w:SelectorSet>
            <w:Selector Name="CreationClassName">Msvm_ComputerSystem</w:Selector>
            <w:Selector Name="Name">0F6888A3-1054-48EF-B643-D364CB283830</w:Selector>
          </w:SelectorSet>
        </a:ReferenceParameters>
      </p:TargetSystem>
      <p:DataItems>&lt;INSTANCE CLASSNAME="Msvm_KvpExchangeDataItem"&gt;&lt;PROPERTY CLASSORIGIN="CIM_ManagedElement" NAME="Caption" PROPAGATED="true" TYPE="string"/&gt;&lt;PROPERTY CLASSORIGIN="Msvm_KvpExchangeDataItem" NAME="Data" PROPAGATED="true" TYPE="string"&gt;&lt;VALUE&gt;myNewValue&lt;/VALUE&gt;&lt;/PROPERTY&gt;&lt;PROPERTY CLASSORIGIN="CIM_ManagedElement" NAME="Description" PROPAGATED="true" TYPE="string"/&gt;&lt;PROPERTY CLASSORIGIN="CIM_ManagedElement" NAME="ElementName" PROPAGATED="true" TYPE="string"/&gt;&lt;PROPERTY CLASSORIGIN="Msvm_KvpExchangeDataItem" NAME="Name" TYPE="string"&gt;&lt;VALUE&gt;myNewKey&lt;/VALUE&gt;&lt;/PROPERTY&gt;&lt;PROPERTY CLASSORIGIN="Msvm_KvpExchangeDataItem" NAME="Source" TYPE="uint16"&gt;&lt;VALUE&gt;0&lt;/VALUE&gt;&lt;/PROPERTY&gt;&lt;/INSTANCE&gt;</p:DataItems>
    </AddKvpItems_INPUT>

Vous récupérez maintenant un Msvm_ConcreteJob pour monitorer l’exécution de la méthode.

WMI – WBEM – Microsft Hyper-V depuis un environnement Java – Linux

API de gestion Hyper-V

Hyper-V, prenez le contrôle depuis votre code Java.

Il n’y a pas vraiment d’API dédiée au contrôle à distance de Hyper-V. Microsoft a tout simplement ajouté de nouveaux composants liés à la virtualisation à l’interface WMI déjà existante. WMI est l’implémentation de WBEM par Microsoft utilisant DCOM comme protocole de communication à la place de HTTP comme le standard le prévoyait. Vous pouvez facilement deviner que c’est très pratique pour une utilisation depuis un environnement Windows, mais beaucoup plus ennuyeux depuis un système d’exploitation Linux. Voici une courte explication permettant de mettre en place le nécessaire pour la gestion de Hyper-V depuis un environnement Java/Linux!

J-Interop, pure Java-DCOM implémentation.

Il existe une solution pour être capable de contacter et utiliser un object COM distant depuis un environnement Java: J-Interop, une implémentation Java de DCOM. Cette API ne fait appel à aucune librairie native Win32 comme ses concurrentes. Elle est très simple d’utilisation, connectez vous au service que vous voulez utiliser et appelez des méthodes de l’objet. Vous pouvez également créer de nouveaux objets COM en local ou distant. Essayez le quickstart pour voir comment tout ça fonctionne et à quel point c’est facile.

WMI pour gérer Hyper-V

Je l’ai dit au tout début, WMI est utilisé pour gérer votre hyperviseur Microsoft Hyper-V. Vous pouvez faire absolument tout ce que vous voulez depuis cette interface à l’exception de la gestion de fichiers. Comme exemple, si vous commencez à jouer avec les disques différentiels ( pour la création de clones entre autres ), vous serez capable de créer les fichiers disques mais pas de les supprimer. Pour y arriver, vous devez vous connecter à l’espace de noms par défaut, “root/CIMV2″, et utiliser la classe CIM_Datafile. J’imagine qu’il y a bien d’autres limitations dans l’espace de nom “root/Virtualization”, mais je n’y ai pas encore été confronté. Ci-dessous est un exemple montrant la création de paire clé/valeur pour l’échange de données entre hôte et guest:

$ComputerName = "localhost" $VMManagementService = Get-WmiObject -class "Msvm_VirtualSystemManagementService" -namespace "root\virtualization" -ComputerName $ComputerName
$Vm = Get-WmiObject -Namespace root\virtualization -ComputerName $ComputerName -Query "Select * From Msvm_ComputerSystem Where ElementName='Vista'" $Kvp = Get-WmiObject -Namespace root\virtualization -ComputerName $ComputerName -Query "Associators of {$Vm} Where AssocClass=Msvm_SystemDevice ResultClass=Msvm_KvpExchangeComponent"
 
$Msvm_KvpExchangeDataItemPath = "\\$ComputerName\root\virtualization:Msvm_KvpExchangeDataItem"
$Msvm_KvpExchangeDateItem = [WmiClass]$Msvm_KvpExchangeDataItemPath).CreateInstance()
$Msvm_KvpExchangeDateItem.Name = "bootstrapURL"
$Msvm_KvpExchangeDateItem.Data = "http://excalibur.activeeon.com:18000/"
$Msvm_KvpExchangeDateItem.Source = 0
 
$VMManagementService.AddKvpItems($Vm, $Msvm_KvpExchangeDateItem.PSBase.GetText(1))

Hyper-V’s WMI + J-Interop

Now we put every pieces together to manage Microsoft Hyper-V. Here is an example on how to connect to the Wbem service locator:

JISession session = JISession.createSession("192.168.1.166", "user", "password");
JIComServer comServer = new JIComServer(JIProgId.valueOf("WbemScripting.SWbemLocator"), "192.168.1.166", session);
IJIComObject wimObject = comServer.createInstance();
IJIDispatch locatorDispatch = (IJIDispatch) JIObjectFactory.narrowObject((IJIComObject) wimObject
        .queryInterface(IJIDispatch.IID));
Object[] params = new Object[] { new JIString(url), new JIString(namespace),
JIVariant.OPTIONAL_PARAM(), JIVariant.OPTIONAL_PARAM(), JIVariant.OPTIONAL_PARAM(),
        JIVariant.OPTIONAL_PARAM(), new Integer(0), JIVariant.OPTIONAL_PARAM() };
JIVariant[] res = locatorDispatch.callMethodA("connectServer", params);
IJIDispatch service = (IJIDispatch) JIObjectFactory.narrowObject(res[0].getObjectAsComObject());

Ou ici où l’on récupère les paths de tous les Msvm_VirtualSwitch du système:

import static org.jinterop.dcom.impls.JIObjectFactory.narrowObject;
 
import java.io.IOException;
import java.util.ArrayList;
import java.util.logging.Level;
 
import org.jinterop.dcom.common.JIException;
import org.jinterop.dcom.common.JISystem;
import org.jinterop.dcom.core.IJIComObject;
import org.jinterop.dcom.core.JIArray;
import org.jinterop.dcom.core.JIComServer;
import org.jinterop.dcom.core.JIProgId;
import org.jinterop.dcom.core.JISession;
import org.jinterop.dcom.core.JIString;
import org.jinterop.dcom.core.JIVariant;
import org.jinterop.dcom.impls.JIObjectFactory;
import org.jinterop.dcom.impls.automation.IJIDispatch;
import org.jinterop.dcom.impls.automation.IJIEnumVariant;
 
public class PrintVSPath {
 
	public static String url = "FQDN";
	public static String user = "USER";
	public static String pwd = "PASSWORD";
 
	public static void main(String[] args) throws JIException, SecurityException, IOException{
		JISession session = null;
		try{
			//J-Interop settings
			JISystem.getLogger().setLevel(Level.ALL);
			JISystem.setInBuiltLogHandler(false);
			JISystem.setAutoRegisteration(true);
 
			//Connection
			session = JISession.createSession(url,user,pwd);
			JIComServer comServer = new JIComServer(JIProgId.valueOf("WbemScripting.SWbemLocator"),url,session);
			IJIComObject wimObject = comServer.createInstance();
			IJIDispatch locatorDispatch = (IJIDispatch)JIObjectFactory.narrowObject((IJIComObject)wimObject.queryInterface(IJIDispatch.IID));
			Object[] params = new Object[]{
					new JIString(url),
					new JIString("root\\virtualization"),
					JIVariant.OPTIONAL_PARAM(),
					JIVariant.OPTIONAL_PARAM(),
					JIVariant.OPTIONAL_PARAM(),
					JIVariant.OPTIONAL_PARAM(),
					new Integer(0),
					JIVariant.OPTIONAL_PARAM()
			};
			JIVariant[] res = locatorDispatch.callMethodA("connectServer",params);
			IJIDispatch sWbemServices = (IJIDispatch) JIObjectFactory.narrowObject(res[0].getObjectAsComObject().queryInterface(IJIDispatch.IID));
			res = sWbemServices.callMethodA("ExecQuery", new Object[]{
					new JIString("Select * From Msvm_VirtualSwitch"),
					JIVariant.OPTIONAL_PARAM(),
					new JIVariant(new Integer(0x10 + 0x20))
			});
			JIVariant[][] resSet = enumToJIVariantArray(res);
			IJIDispatch vsDispatch = (IJIDispatch)JIObjectFactory.narrowObject(resSet[0][0].getObjectAsComObject().queryInterface(IJIDispatch.IID));
			((IJIDispatch)JIObjectFactory.narrowObject(vsDispatch.get("Path_").getObjectAsComObject().queryInterface(IJIDispatch.IID))).get("Path").getObjectAsString2();
		}finally{
			if(session != null)
				JISession.destroySession(session);
		}
	}
 
	public static JIVariant[][] enumToJIVariantArray(JIVariant[] set) throws JIException{
		IJIDispatch toConvertDispatch = (IJIDispatch)narrowObject(set[0].getObjectAsComObject().queryInterface(IJIDispatch.IID));
		JIVariant toConvertVariant = toConvertDispatch.get("_NewEnum");
		IJIComObject toConvertComObject = toConvertVariant.getObjectAsComObject();
		IJIEnumVariant toConvertEnumVariant = (IJIEnumVariant)narrowObject(toConvertComObject.queryInterface(IJIEnumVariant.IID));
		ArrayList<JIVariant[]> res = new ArrayList<JIVariant[]>();
		int i = 0, threshold = 1000000; //to avoid infinite loop, in both msdn and j-interop nothing is said about enumeration
		while(true){
			Object[] values = null;
			try{
				values = toConvertEnumVariant.next(1);
			}catch(JIException e){
				break;
			}
			if(values != null){
				JIArray array = (JIArray) values[0];
				res.add((JIVariant[])array.getArrayInstance());
			}
			i++;
			if( i >= threshold){
				break;
			}
		}
		return res.toArray(new JIVariant[res.size()][]);
	}
}