VMware {code} Community
Kjellski
Contributor
Contributor
Jump to solution

How to move a VirtualMachine from one Folder to another?

Hi there,

I'm trying to move a Vmware.Vim.VirtualMachine from one Vmware.Vim.Folder to another with the API Provided by the C# Vmware.Vim.dll from the

PowerCLI in a VisualStudio 2010 Project. Please be aware that these Folders are not "normal" Folders, these are the VMware containers...

Could someone tell me how to achieve this?

I found the vm.Relocate_Task() Method, but I was wondering wether it was for moving the disks in storage or should it be used for this task too?

Greetings,

Kjellski

Tags (4)
0 Kudos
1 Solution

Accepted Solutions
lamw
Community Manager
Community Manager
Jump to solution

That's correct, a vApp is treated as a type of ResourcePool, so the MoveIntoResourcePool() - http://www.vmware.com/support/developer/vc-sdk/visdk41pubs/ApiReference/vim.ResourcePool.html#moveIn... is what you'll want to use. Unfortunately this is not an async operation, so you will be be blocked until the operation completed but this should be pretty quickly and if any faults are thrown, the operation will terminate.

I would highly recommend taking a look at VMware Onyx, this is allows you to literally perform an operation using the vSphere Client and the appropriate SOAP, C# or PowerCLI code is generated so you can easily see what methods are being used for what operation. This is really useful in troubleshooting and figuring out what paramters are needed for a particular operation.

View solution in original post

0 Kudos
9 Replies
Kjellski
Contributor
Contributor
Jump to solution

As you go out and ask somebody, you discover new ideas of trying...

Could it be that I need to use the Folder object and tell it to move somethings into itself?

using Vmware.Vim;

class VMAbstraction {

...

     public Task moveTo(ManagedObjectReference targetFolder)

     {

          // vmc is the Vmware.Vim.VimClient

          Folder f = new Folder(vmc, targetFolder);

          return new Task(vmc, f.MoveIntoFolder_Task(new ManagedObjectReference[] { vm.MoRef }));

     }

...

}

0 Kudos
lamw
Community Manager
Community Manager
Jump to solution

That's correct, you'll need to use the MoveIntoFolder_Task() - http://www.vmware.com/support/developer/vc-sdk/visdk41pubs/ApiReference/vim.Folder.html#moveInto

Kjellski
Contributor
Contributor
Jump to solution

An what is the correct way to move a VirtualMachine from one VirtualApp to another, or from a RessourcePool to another?

For a RessourcePool, which is in this case the same things as a VirtualApp if I get the documentation right, there is just the Blocking, no Task returning method MoveIntoResourcePool(). Could I create my own task in order to keep it Async?

I couldn't find a Method on the VirtualMachine side, which would generalize what I want...

My problem is that I don't get arround the idea of sticking every API call to the target side and implement is so often... but that is not your problem Smiley Wink

0 Kudos
lamw
Community Manager
Community Manager
Jump to solution

That's correct, a vApp is treated as a type of ResourcePool, so the MoveIntoResourcePool() - http://www.vmware.com/support/developer/vc-sdk/visdk41pubs/ApiReference/vim.ResourcePool.html#moveIn... is what you'll want to use. Unfortunately this is not an async operation, so you will be be blocked until the operation completed but this should be pretty quickly and if any faults are thrown, the operation will terminate.

I would highly recommend taking a look at VMware Onyx, this is allows you to literally perform an operation using the vSphere Client and the appropriate SOAP, C# or PowerCLI code is generated so you can easily see what methods are being used for what operation. This is really useful in troubleshooting and figuring out what paramters are needed for a particular operation.

0 Kudos
Kjellski
Contributor
Contributor
Jump to solution

Hi again lawm,

just wanted to say thanks again, and thanks for mentioning the Onyx Project which is really helpful.

Greetings,

Kjellski

0 Kudos
vichlu
Contributor
Contributor
Jump to solution

public static void CreateFolder(VimClient client, string foldername, params string[] vmNames)
        {
            // ------- CreateFolder -------

            Folder _this = new Folder(client, new ManagedObjectReference("Folder-group-v3"));
            _this.CreateFolder(foldername);
           
            // ------- MoveIntoFolder_Task -------

            foreach (string t in vmNames)
            {
                var filter = new NameValueCollection { { "name", "^" + t + "$" } };
                var vm = (VirtualMachine)client.FindEntityView(typeof(VirtualMachine), null, filter, null);
                if (vm == null)
                {
                    Console.WriteLine(t + " is not a valid virtual Machine name.");
                }
                else
                {
                    ManagedObjectReference[] list = new ManagedObjectReference[1];
                    list[0] = new ManagedObjectReference {Type = "VirtualMachine", Value = vm.MoRef.Value};
                    ManagedObjectReference m = _this.MoveIntoFolder_Task(list); 
                }
            }

        }

In the above snippet, the virtual machines move but not to the folder specified, they stay where they are, i.e. within DC and the folder is empty after the operation. What am I missing?

0 Kudos
vichlu
Contributor
Contributor
Jump to solution

New snippet that worked...but only once.. It doesn't like the hardcoded values such as new ManagedObjectReference("Folder-group-v470")); How can I make this dynamic?

public static void CreateFolder(VimClient client, string foldername, params string[] vmNames)
        {
            // ------- CreateFolder -------

            Folder folder = new Folder(client, new ManagedObjectReference("Folder-group-v3"));
            folder.CreateFolder(foldername);
           
            // ------- MoveIntoFolder_Task -------
           
            foreach (string t in vmNames)
            {
                var filter = new NameValueCollection { { "name", "^" + t + "$" } };
                var vm = (VirtualMachine)client.FindEntityView(typeof(VirtualMachine), null, filter, null);
                if (vm == null)
                {
                    Console.WriteLine(t + " is not a valid virtual Machine name.");
                }
                else
                {
                    ManagedObjectReference[] list = new ManagedObjectReference[1];
                    list[0] = new ManagedObjectReference {Type = "VirtualMachine", Value = vm.MoRef.Value};
                    Folder _this = new Folder(client, new ManagedObjectReference("Folder-group-v470"));
                    ManagedObjectReference m = _this.MoveIntoFolder_Task(list);
                    AwaitTaskCompletion(client, m);
                }
            }

        }

0 Kudos
Kjellski
Contributor
Contributor
Jump to solution

Hi there vichlu,

I think there are some concepts that you've eventually missed on the run:

  • The examples that you get from the Onyx Console are examples that are exactly for what you did in that moment. Therefor Onyx shows you the IDs for the exact things you've touched with that exact operation. That means, if you just copy that code, it will just repeat that exact operation.
  • Your code is using these unique references and therefor using always the same remote entities. What you could do instead, is use another parameter in your method to hand it the Folder you want to use for moving the vm to, or split the method up into two methads, which I woul suggest.

You could write one method that creates a Folder in a given one, returning that new Folder as a reference and then hand it to another methat that does the actual moving of the vm.

You could reuse the two method for all kind of things in the future and also bundle them with a wrapping method that you could call "createFolderAndMoveVMIntoIt(String newFolderName, ManagedObjectReference folderToCreateTheNewOneInReference, ManagedObjectReference virtualMchineReference)" for example.

For finding a Folder by Name, I use this code snippet:

            System.Collections.Specialized.NameValueCollection filter = new System.Collections.Specialized.NameValueCollection();
            filter.Add("name", name);
 
            Folder f = (Folder) vmc.FindEntityView(typeof(Folder), vmFolder, filter, null);
            if (f != null)
            {
                // Found it, now put it into the cache
                cache.Add(name, new RLFolder(f));
 
                return new RLFolder(vmc, f.MoRef);
            }
            else
            {
                throw new RLVMwareWrapper.Exceptions.FolderNotFoundException("Couldn't find Folder: " + name);
            }

I hope this helps!

Greetings,

Kjellski

0 Kudos
Amatic
Contributor
Contributor
Jump to solution

HI Kjellski

I just don't get it... where do I say where the VM shall be moved to? I mean don't I have to specify a path of something?

Can someone please make me a sample with names and everything?

And what is this ManagedObjectReference? This does not make sense to me since I dont see any path...

Thank you.

0 Kudos