Home > Hyper-V, Virtualization > WMI – WBEM – Microsoft Hyper-V from Java – Linux

WMI – WBEM – Microsoft Hyper-V from Java – Linux

April 21st, 2010 jmguilla

This post is also available in: French

Hyper-V Management API

Hyper-V, take the control from your Java code.

We cannot say that there is a particular API allowing remotely manage Microsoft Hyper-V. Microsoft simply inserted new components related to virtualization to its existing WMI interface. WMI is Microsoft’s WBEM implementation using DCOM as communication layer instead of HTTP like it was planned by the standard. You can easily guess that it is really convenient for use from a Window environment but far more annoying from a Linux operating system. Here is a brief explanation about how to get that to work from a Java/Linux environment!

J-Interop, pure Java-DCOM bridge.

The solution to be able to reach a remote COM object from a Java environment is J-Interop, a pure Java-DCOM bridge. The word “pure” is used to show that there isn’t any tricky things like native Win32 library calls or anything else ( on a Linux platform, it would have been clumsy ). This API is straightforward to use, just connect to the service you want to use and call methods. You can also create new COM object on local/remote computer. Check the quickstart to see how does it work.

WMI to manage Hyper-V

As I said at the beginning, WMI is used to manage Microsoft Hyper-V environment. You can do every thing you want using this interface except actions related to file management. For example, if you play with differencing hard disks, for virtual machine clone creation ( among many possible things… ), you will be able to create files but won’t be able to delete them. To get that done, you will have to connect to default CIMV2 namespace and use CIM_Datafile class. I assume there is many other limitations in the virtualization namespace, but I haven’t found any so far. Below is an example showing how to create a new KVP exchange data item:

$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());

Or here, where we print every Msvm_VirtualSwitch’s path:

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 domain = "DOMAIN";
	public static String url = "SERVER_NAME";
	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(domain,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()][]);
	}
}
  1. Kurt
    June 11th, 2010 at 15:08 | #1

    Hi,

    thanks for this example, but how is this going to help? This first part – is this vbscript? And how does this integrate with the second part which is Java using J-Interop?

    I managed to connec to a Win 2008 R2 server using WMI and can, for example, query the Win32_Process tree and display it (as in the example from J-interop). But now, if I want to query, for example, the virtualswitch object, I do not get much – or, to rephrase this – I do not know how to get the data out of the return, variant objects… any hint would be highly appreciated.

    Thanks
    Kurt

  2. June 11th, 2010 at 15:16 | #2

    Sorry, published the post without the end… I get the code you need and put it online ASAP!!

  3. June 11th, 2010 at 15:37 | #3

    @Kurt Code updated but not tested… I cannot connect to my Hyper-V server right now… Hope this will help so far!! THX

  4. Kurt
    June 11th, 2010 at 15:58 | #4

    Hi,

    thanks for posting this so fast – how do I format the variable “url”? I used domain and host seperately so far… and using hostname.domainname as url gives me the following exception:
    Exception in thread “main” org.jinterop.dcom.common.JIException: The attempted logon is invalid. This is either due to a bad username or authentication information. [0xC000006D]

  5. Kurt
    June 11th, 2010 at 16:07 | #5

    hhmm, I changed the code a bit to get authenticated/access to the Wbem Service. Now it seems to run without an error but your code currently doesn’t produce any output. Am I not supposed to do anything with the result of:

    ((IJIDispatch)JIObjectFactory.narrowObject(vsDispatch.get(“Path_”).getObjectAsComObject().queryInterface(IJIDispatch.IID))).get(“Path”).getObjectAsString2();

    Thanks and sorry for being stupid here…

    Kurt

  6. June 11th, 2010 at 16:09 | #6

    My mistake, I forgot the sysout ;) !!! Can you post the changes you made? I could update the post though… THX

  7. Kurt
    June 11th, 2010 at 16:17 | #7

    session = JISession.createSession(“domain”, “username”, “password”);
    JIComServer comServer = new JIComServer(JIProgId.valueOf(“WbemScripting.SWbemLocator”),”Testdpl1″,session);
    IJIComObject wimObject = comServer.createInstance();

    IJIDispatch locatorDispatch = (IJIDispatch)JIObjectFactory.narrowObject((IJIComObject)wimObject.queryInterface(IJIDispatch.IID));
    Object[] params = new Object[]{
    new JIString(“destinationsever”),

  8. tiltaftelfSet
    July 8th, 2010 at 08:05 | #8

    why not…

  9. Helder
    July 31st, 2010 at 12:02 | #9

    @Kurt: can you repost your changes… Please…
    I am facing the same problems…
    Thanks

  10. Helder
    July 31st, 2010 at 12:36 | #10

    Sorry… I found… it… I was so stupid…
    Thanks…

  11. Swapna
    November 15th, 2010 at 07:18 | #11

    Hi,
    I want to create a VM, power it On, and power it Off and delete it. Can you give me a code sample on how to do this using j-interop
    Thanks,
    Swapna.

  12. Vikram
    May 18th, 2011 at 13:41 | #12

    Hi ,
    I am using Jinterop API to call WMI and creating VM . I have a problem to create fixed VHD of more than 1 GB . ANy idea please for this . i am using org.ow2.proactive.virtualizing.hypervwmi.lib.MsvmImageManagementService class for creating fixedVHD using createFixedVirtualHardDisk() methid .Can you please help me or any clue regarding this

  13. Vikram
    May 20th, 2011 at 09:40 | #13

    Hi John ,

    I have done with the last query now as i have requirement to export a ISO in my Hyper V any clue for that .

    Thanks in Advance
    Virkam

  14. Welson
    March 16th, 2012 at 06:08 | #14

    Thanks for your sharing. I met a weird thing. I use below code to connect hyper-V server and work for one of Hyper-V Server. But for the other one, it didn’t work. The progress was stuck in this code “JIComServer comServer = new JIComServer(valueOf(“WbemScripting.SWbemLocator”), hostname, dcomSession);” and not any exception, just keep running. The hyper-V’s credential is correct. Is there anything I need to do?

  15. Welson
    March 16th, 2012 at 09:43 | #15

    From log, after it received “ALTER_CTX_RESP”, then no any response comes up. The code is work for other hyper-V Server, so I guess some configuration need to do for windows2008, any advices?

  1. February 7th, 2013 at 08:05 | #1
  2. February 20th, 2013 at 00:47 | #2
  3. March 23rd, 2013 at 06:16 | #3
  4. March 23rd, 2013 at 19:16 | #4
Comments are closed.