Accueil > Hyper-V, Virtualisation > WMI – WBEM – Microsft Hyper-V depuis un environnement Java – Linux

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

21/04/2010 jmguilla Editer

This post is also available in: Anglais

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()][]);
	}
}
Les commentaires sont fermés.