Archive

Posts Tagged ‘Hyper-V’

Most used hypervisors

May 10th, 2010 jmguilla No comments

The most used, easy to guess, VMware ESX… The second one, a little bit harder, VMware Server 2. To me, it is an interesting point to see a type 2 hypervisor at the 2nd position in this ranking. At the 3rd and 4th places, respectively Microsoft Hyper-V and Citrix XenServer, both with more than a 200% progress…

source

WinRM & XML CIM Instances as method parameter

April 29th, 2010 jmguilla No comments

Here is a something I couldn’t find anywhere on MSDN network documentation an forums. If you want to have a quick look at all the story, you can visit the msdn network’s dedicated thread.

The problem was I didn’t know how to be able to pass XML CIM Instances as parameter during a WinRM method call. WinRM is really powerful, but with some namespaces, you can’t create objects using the CREATE action. Instead, you must use appropriate managers’ methods, for instance, in the virtualization’s namespace, if you want to add a new Key/Value pair to a Msvm_ComputerSystem ( ie. a virtual machine for those of you who are not familiar with Microsoft’s CIM ). Here come the troubles… There isn’t any single place in the entire MSDN and DMTF documentation which describes the way CIM XML Instances have to be written. The WSMAN specification says that method input is XML. The normal behavior would be to think that the CIM Instances are just unchanged. If you think like me, you have certainly written:

<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>

and you get an answer like:

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.

Not really meaningful… It comes that, after many, many, many tries, I found that, to make that work, you must escape < and > and be careful with withe spaces… Here is the great input file:

    <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>

You now get a Msvm_ConcreteJob to monitor the method execution.

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

April 21st, 2010 jmguilla 19 comments

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()][]);
	}
}