Programmatically managing Virtual Server using C#

Virtual Server 2005 (VS2005) is a well-known tool to manage Virtual Machines (VMs) on a host server. It is a great feature to manage virtualization for hardware/software. Most often one would use the VS2005 Web Admin  interface to manage VMs. But at times (like the way it recently happened for a customer of mine) one may want to programmatically control the VMs. This would most often sound a necessity if you would like to provide end users access to manage basic VM activities like turn on/off, save state etc. etc. without giving them access to everything as in through the VS2005 Web Admin site.

Here are some code snippets/sample web application/links in case you would like to try your hands on something like this.

Let me show you a typical screen-shot of how VS2005 Web Admin interface looks like.

image

image

To programmatically manage the Virtual machines on a host server, you need to add a reference to a COM object for your .Net application which exposes various properties/methods.

 image

Visual Studio will add a COM Interop layer for this. You should see the following in your Visual Studio project:

image

Ensure we add a namespace as "using Microsoft.VirtualServer.Interop;" in the web/form page.

Here are code snippets (in C#) to:

a. Turn On/Restore from a saved state for a Virtual machine on a local host machine.

 VMVirtualServerClass vs = new VMVirtualServerClass();

VMVirtualMachine vm = vs.FindVirtualMachine(VM_name);

if (vm.State == VMVMState.vmVMState_TurnedOff || vm.State == VMVMState.vmVMState_Saved)
                {
                        VMTask vt = vm.Startup();
                        if (vt != null)
                            vt.WaitForCompletion(-1);
                }

b. Turn Off a Virtual machine on a local host machine.

 VMVirtualServerClass vs = new VMVirtualServerClass();

VMVirtualMachine vm = vs.FindVirtualMachine(VM_name);

if (vm.State == VMVMState.vmVMState_Running || vm.State == VMVMState.vmVMState_Paused)
                {
                        // Turn the power off on the Guest VM
                        Label1.Text = "Forcefully shutting down VM...";
                        VMTask vt = vm.TurnOff();
                        if (vt != null)
                            vt.WaitForCompletion(-1);
                        else
                            Label1.Text = "Not ready for a turn off. Please wait and try again after a few seconds...";
                 }

c. Save state of a Virtual machine on a local host machine.

 VMVirtualServerClass vs = new VMVirtualServerClass();

VMVirtualMachine vm = vs.FindVirtualMachine(VM_name);

if (vm.State == VMVMState.vmVMState_TurnedOff || vm.State == VMVMState.vmVMState_Saved)
                {
                        VMTask vt = vm.Startup();
                        if (vt != null)
                            vt.WaitForCompletion(-1);
                }

d. Pause a Virtual machine on a local host machine.

 VMVirtualServerClass vs = new VMVirtualServerClass();

VMVirtualMachine vm = vs.FindVirtualMachine(VM_name);

if (vm.State == VMVMState.vmVMState_TurnedOff || vm.State == VMVMState.vmVMState_Saved)
                {
                        VMTask vt = vm.Startup();
                        if (vt != null)
                            vt.WaitForCompletion(-1);
                }

e. Resume a Virtual machine on a local host machine.

 VMVirtualServerClass vs = new VMVirtualServerClass();

VMVirtualMachine vm = vs.FindVirtualMachine(VM_name);

if (vm.State == VMVMState.vmVMState_TurnedOff || vm.State == VMVMState.vmVMState_Saved)
                {
                        VMTask vt = vm.Startup();
                        if (vt != null)
                            vt.WaitForCompletion(-1);
                }

f. Reset a Virtual machine on a local host machine.

 VMVirtualServerClass vs = new VMVirtualServerClass();

VMVirtualMachine vm = vs.FindVirtualMachine(VM_name);

if (vm.State == VMVMState.vmVMState_TurnedOff || vm.State == VMVMState.vmVMState_Saved)
                {
                        VMTask vt = vm.Startup();
                        if (vt != null)
                            vt.WaitForCompletion(-1);
                }

g. Shut down a virtual machine on a local host machine.

 VMVirtualServerClass vs = new VMVirtualServerClass();

VMVirtualMachine vm = vs.FindVirtualMachine(VM_name);

if (vm.State == VMVMState.vmVMState_TurnedOff || vm.State == VMVMState.vmVMState_Saved)
                {
                        VMTask vt = vm.Startup();
                        if (vt != null)
                            vt.WaitForCompletion(-1);
                }

h. Enumerate all the Virtual machines running on the local host machine.

 VMVirtualServerClass vs = new VMVirtualServerClass();

VMVirtualMachine vm = vs.FindVirtualMachine(VM_name);

if (vm.State == VMVMState.vmVMState_TurnedOff || vm.State == VMVMState.vmVMState_Saved)
                {
                        VMTask vt = vm.Startup();
                        if (vt != null)
                            vt.WaitForCompletion(-1);
                }

i. Check various properties exposed through the COM API.

 VMVirtualServerClass vs = new VMVirtualServerClass();

VMVirtualMachine vm = vs.FindVirtualMachine(VM_name);

                string _VMName = vm.Name;
                string _guestOS = String.Empty;
                if (vm.State == VMVMState.vmVMState_Running)
                    _guestOS = vm.GuestOS.OSName;
                else
                    _guestOS = "OS: n/a"; 
                string _memory = vm.Memory.ToString();
                .......

j. At times if you want to manage VMs hosted on a remote machine and not on the local machine, here is what you need to do besides all the steps already mentioned above.

 private VMVirtualServerClass connectToRemoteHost(string remoteHost)
    {
        VMVirtualServerClass virtualServerCOM = null;
        Type VMVirtualServerClassType = typeof(VMVirtualServerClass);
        try
        {
            // create remote type from class identifier
            Type DCOMType = Type.GetTypeFromCLSID(VMVirtualServerClassType.GUID, remoteHost, true);
            object DCOMObject = Activator.CreateInstance(DCOMType);
            // create local object from remote object
            virtualServerCOM = (VMVirtualServerClass)Marshal.CreateWrapperOfType(DCOMObject, VMVirtualServerClassType);
            TextBox1.Text = String.Empty;
            return virtualServerCOM;
        }
        catch
        {
            TextBox1.Text ="There was an error while connecting to the remote host. Make sure that we have the necessary permissions/settings to access the remote host";
            return null;
        }
    }

                                                                                                                       (Courtesy this MSDN magazine)

I have not included error handling in the code snippets above. Please do so when you build the actual application. Also there are many other activities that can be performed besides the ones discussed above like setting up a VM from the beginning with various components like differencing, memory, network adapter etc., changing the disk configuration of an existing machine etc. etc.

The more you explore the more you get to control through the code using the API mentioned above.

Here are some useful links related to the topic.

https://msdn.microsoft.com/en-us/magazine/cc163935.aspx

https://dotnet.sys-con.com/node/47338

https://blogs.msdn.com/david.wang/archive/2006/04/17/HOWTO-Perform-VHD-Maintenance-Automatically.aspx

https://blog.anildesai.net/?p=220, https://blog.anildesai.net/?p=214

Attached is a sample ASP.Net 2.0 web application to try the above commands if interested.

Till next time our paths cross.

Bye!

VS20051.rar