Skip to content

Instantly share code, notes, and snippets.

Created June 13, 2013 22:33
Show Gist options
  • Select an option

  • Save anonymous/5777983 to your computer and use it in GitHub Desktop.

Select an option

Save anonymous/5777983 to your computer and use it in GitHub Desktop.
Sample vSphere SDK for Perl script showing how to build up a Managed Object using MoRef ID
#!/usr/bin/perl -w
# William Lam
# http://www.virtuallyghetto.com/
use strict;
use warnings;
use VMware::VIRuntime;
use VMware::VILib;
my %opts = (
vmname => {
type => "=s",
help => "Name of VM",
required => 1,
},
);
Opts::add_options(%opts);
Opts::parse();
Opts::validate();
Util::connect();
my $vmname = Opts::get_option('vmname');
# searches for VM object based on vmname input
my $vm = Vim::find_entity_view(view_type => 'VirtualMachine', properties => ['name'], filter => {'name' => $vmname});
if(defined($vm)) {
# performs simple async task, save the Task Ref
my $taskRef = $vm->PowerOnVM_Task();
# get Task Ref view
my $taskView = Vim::get_view(mo_ref => $taskRef);
# get Task MoRef ID
my $taskMoRefId = $taskView->{'mo_ref'}->value;
# print out MoRef ID + state of task
print "MoRefID: " . $taskMoRefId . "\t " . "State:" . $taskView->info->state->val . "\n";
# adding a dummer timer, you could do something else and then check back later using MoRef ID
sleep 10;
# build a new MO using the Task MoRef ID
my $newTaskRef = ManagedObjectReference->new(type => "Task", value => $taskMoRefId);
# get Task Ref view
my $newTaskView = Vim::get_view(mo_ref => $newTaskRef);
# get Task MoRef ID from new object to ensure it's the same one
my $newTaskMoRefId = $taskView->{'mo_ref'}->value;
# print Task MoRef ID + state and you should see it change
print "MoRefID: " . $newTaskMoRefId . "\t " . "State:" . $newTaskView->info->state->val . "\n";
# power off VM
$vm->PowerOffVM_Task();
} else {
print "Unable to find $vmname\n";
}
Util::disconnect();
### SAMPLE OUTPUT ###
lamw:~/vmware » ./taskExample.pl --server mini --username root --vmname VM1
MoRefID: haTask-20-vim.VirtualMachine.powerOn-506061389 State:running
MoRefID: haTask-20-vim.VirtualMachine.powerOn-506061389 State:success
@shawncplus
Copy link

# yes, no, maybe?

print Dumper(Vim::get_view( mo_ref => ManagedObjectReference->new(type => 'Task', value => $task_id)));¬


Output:
Fault string: The object has already been deleted or has not been completely created
Fault detail: ManagedObjectNotFoundFault

OR

    my $TaskManager = Vim::get_view( mo_ref => Vim::get_service_content()->taskManager )
        || die "Unable to initialize TaskManager!";
        my $TaskFilterSpec = TaskFilterSpec->new(
        rootTaskKey => [$task_id] );
    my $collector = $TaskManager->CreateCollectorForTasks(
        filter => $TaskFilterSpec
    );


    my $TaskHistoryCollector = Vim::get_view ( mo_ref => $collector )
        || die "Unable to get TaskHistoryCollector view!";
    my $tasks = $TaskHistoryCollector->ReadNextTasks( maxCount => 10 );

    print Dumper($tasks);

OR

$type = 'Task';
$value = 'task-12345'; # example
   my $propertyCollector = Vim::get_view( mo_ref => Vim::get_service_content()->propertyCollector );

    my $mor = ManagedObjectReference->new(type => $type, value => $value );

    my $objectSet = ObjectSpec->new(obj => $mor);
    my $propSet = PropertySpec->new(type => $type, all => 1);

    eval
    {
        my $specSet = PropertyFilterSpec->new(propSet => [$propSet], objectSet => [$objectSet]);

        my $props = $propertyCollector->RetrieveProperties(
            specSet => $specSet
        );
        1;
    }
    or do
    {
        print Dumper($@);
    }

None of these work

@shawncplus
Copy link

My current situation. All I have is a string containing the key from the TaskInfo, i.e., someone is hitting our API at /task/

and I want to return the TaskInfo object for that task

@lamw
Copy link

lamw commented Jun 13, 2013

Are you sure the Task object still exists in the system? If you take a look at the error message, it says it may not longer be valid/exists which sounds like you're trying to access a Task object that's no longer in the system.

@shawncplus
Copy link

It definitely does because if I do the following where $fqdn is given a specific hostname

    my $vm_view = Vim::find_entity_view (
        view_type => "VirtualMachine",
        properties => [ 'name' ],
        filter => { 'name' => "$fqdn" } );


    die "Failed to get virtual machine '$fqdn'!" unless $vm_view;

    my $TaskManager = Vim::get_view( mo_ref => Vim::get_service_content()->taskManager )
        || die "Unable to initialize TaskManager!";

    my $TaskFilterSpecByEntity = TaskFilterSpecByEntity->new(
        entity => $vm_view,
        recursion => TaskFilterSpecRecursionOption->new( "self" ),
    );

    my $TaskFilterSpec = TaskFilterSpec->new(
        entity => $TaskFilterSpecByEntity );
    my $TaskHistoryCollector_mor = $TaskManager->CreateCollectorForTasks( filter => $TaskFilterSpec );

    my $TaskHistoryCollector = Vim::get_view ( mo_ref => $TaskHistoryCollector_mor )
        || die "Unable to get TaskHistoryCollector view!";

    $TaskHistoryCollector->RewindCollector();

    my $tasks = $TaskHistoryCollector->ReadNextTasks( maxCount => 10 );

@shawncplus
Copy link

And I get back

/* chop */
[
        {
            "cancelable": "0",
            "cancelled": "0",
            "completeTime": "2013-04-01T21:50:15.018Z",
            "descriptionId": "Drm.ExecuteVMotionLRO",
            "entity": {
                "type": "VirtualMachine",
                "value": "vm-22805"
            },
            "entityName": "myhostnamehere",
            "eventChainId": "75089172",
            "key": "task-1173277",
            "queueTime": "2013-04-01T21:49:05.251Z",
            "reason": {},
            "startTime": "2013-04-01T21:49:05.397Z",
            "state": {
                "val": "success"
            },
            "task": {
                "type": "Task",
                "value": "task-1173277"
            }
        }
]

@lamw
Copy link

lamw commented Jun 13, 2013

So you're saying that the task_id you provided earlier is showing up in the $tasks array ref?

@shawncplus
Copy link

So at the very least it exists somewhere and I want to get it from that magical place when they give me that ID

@shawncplus
Copy link

Right, so using the

Vim::get_view( mo_ref => ManagedObjectReference->new(type => 'Task', value => 'task-1173277'));

I get that error message. But as you can see in that output, it's somewhere

@shawncplus
Copy link

The only thing I can think of is that TaskHistoryCollector returns completed tasks and get_view will not

@lamw
Copy link

lamw commented Jun 13, 2013

Well TaskHistoryCollector can return whatever you want, it's all based on your spec definition as defined by the API docs here http://pubs.vmware.com/vsphere-51/index.jsp?topic=%2Fcom.vmware.wssdk.apiref.doc%2Fvim.TaskFilterSpec.html

@shawncplus
Copy link

So any ideas why get_view doesn't return it but TaskHistoryCollector does?

@shawncplus
Copy link

The tl;dr is I have a task key and need to get the TaskInfo for it. It looks like the get_view approach is the correct way but it's not working so if I could either A) get it working or B) Figure out why it's not returning the task I would be stoked

@lamw
Copy link

lamw commented Jun 13, 2013

FYI - It does work for me. I don't have a chatty system right now, but I just did a self-vMotion which looks like the type of task you had originally. Then looked at the latestTask property and used "task-102" and it worked for me.

@shawncplus
Copy link

http://www.youtube.com/watch?v=krD4hdGvGHM I initiated two new tasks (powerOff and powerOn) and after they finished I hit /task/task-(task-id) (Endpoint that runs the get_view code) and both worked. However the older tasks in the list of tasks for that machine (Tasks returned from TaskCollector) did not work. I wonder if there's some TTL on get_view or something odd. Either way, at least now I can handle the Fault and and know the code is right.

@shawncplus
Copy link

Workflow:

Initiate task on Machine A

/task/task-(new task id)

Hooray, get stuff

Initiate new task on Machine A

/task/task-(new task id)

Hooray, get stuff

/task/task-(old task id)

Boooo, task is gone, despite still showing up in the list of tasks for that machine with full details and with the same task id as it originally had. Nothing changed about the task as far as I can tell except that get_view won't return it

However,

Initiate task on Machine A

/task/task-id get stuff

Initiate Task on Machine B

/task/task-id get stuff
/task/task-old-task-id get stuff

tl;dr I think get_view can only return the most recent task (FOR A SINGLE MACHINE). That seems.... very, very wrong and/or broken.

EDIT: Gah! This doesn't seem to be the case either.

EDIT2: Seems to be time related, it stopped being returned from get_view around 5-7 minutes

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment