VMware {code} Community
lamw
Community Manager
Community Manager
Jump to solution

How to use "DatastoreHostMount" data object

I'm trying to iterate over set of Cluster's found in vCenter and for each datastore found, determine whether or not a host has the datastore mounted or if it's visible to the host. I'm thinking of using "DatastoreHostMount" data object, but I'm not exactly sure how to utilize the object to retrieve the host configuration name.

Here is snippet of perl code and I'm getting an error for:

#get all hosts within cluster and check the connectionState and compare with all datastores found
#is there a more efficient way to combine this section with the next section?

        my $hosts = Vim::get_views (mo_ref_array => $cluster->host);

        foreach my $host (@$hosts) {
                if ($host->runtime->connectionState->val eq 'connected') {
                        my $datastores = Vim::get_views (mo_ref_array => $cluster->datastore);
                        foreach my $datastore (@$datastores) {
                                  print "  Datastore ", $datastore->host->summary->config->name,"\n"
                        }
                }
                elsif ($host->runtime->connectionState->val eq 'disconnected') {
                        print "\t|", $host->summary->config->name, "|Disconnected|\n"
                }
                elsif ($host->runtime->connectionState->val eq 'notResponding') {
                        print "\t|", $host->summary->config->name, "|Not Responding|\n"
                }
        }

Can't call method "summary" on unblessed reference at ./listCluster.pl line 71.

End Disconnect

=========================================================================

--William

VMware ESX/ESXi scripts and resources at:

0 Kudos
1 Solution

Accepted Solutions
DougBaer
Commander
Commander
Jump to solution

OK, I remembered how this works. Sorry for the noise:

|

my $datacenter = Opts::get_option('datacenter');

my $datacenter_view = Vim::find_entity_view(view_type => 'Datacenter',

filter => { name => $datacenter });

if (!$datacenter_view) {

die "Datacenter '" . $datacenter . "' not found\n";

}

my $cluster_views = Vim::find_entity_views(view_type => 'ClusterComputeResource',

begin_entity => $datacenter_view);

my $counter = 1;

print "Clusters found:\n";

foreach (@$cluster_views) {

print "$counter: " . $_->name . "\n";

my $datastores = Vim::get_views (mo_ref_array => $_->datastore);

foreach my $datastore (@$datastores) {

my $instances = @{$datastore->host};

my $instance = 0;

while($instance < $instances) {

my $x = Vim::get_view( mo_ref=>$datastore->host->\[$instance\]->key);

print $datastore->summary->name," Datastore ", $x->name,"\n";

$instance++;

}

}

$counter++;

}

Doug Baer, Solution Architect, Advanced Services, Broadcom | VCDX #019, vExpert 2012-23

View solution in original post

0 Kudos
43 Replies
DougBaer
Commander
Commander
Jump to solution

$datastore->host is actually an array of HostSystem object references, so I think you'll have to treat it that way by calling get_view() on each object.

I'll see if I can work up an example -- I know I have run into this before.

You may be able to do something like this

my $instances = @{$datastore->host};

while($instance<$instances) {

my $hostname = $datastore->host->\[$instance\]->summary->config->name ;

print $hostname ;

}

Doug Baer, Solution Architect, Advanced Services, Broadcom | VCDX #019, vExpert 2012-23
0 Kudos
lamw
Community Manager
Community Manager
Jump to solution

Thanks for your quick reply DougBaer,

Using the following snippet of code, which I believe is equilvent to yours:

my $host_instances = @{$datastore->host};
        foreach my $host_instance (@$host_instances) {
                my $hostname = $datastore->host->[$host_instance]->summary->config->name;
                print $hostname;
        }

I get the following error:

Can't use string ("2") as an ARRAY ref while "strict refs" in use at ./listCluster.pl line 72.

End Disconnect

=========================================================================

--William

VMware ESX/ESXi scripts and resources at:

0 Kudos
DougBaer
Commander
Commander
Jump to solution

OK, I remembered how this works. Sorry for the noise:

|

my $datacenter = Opts::get_option('datacenter');

my $datacenter_view = Vim::find_entity_view(view_type =&gt; 'Datacenter',

filter =&gt; { name =&gt; $datacenter });

if (!$datacenter_view) {

die "Datacenter '" . $datacenter . "' not found\n";

}

my $cluster_views = Vim::find_entity_views(view_type =&gt; 'ClusterComputeResource',

begin_entity =&gt; $datacenter_view);

my $counter = 1;

print "Clusters found:\n";

foreach (@$cluster_views) {

print "$counter: " . $_-&gt;name . "\n";

my $datastores = Vim::get_views (mo_ref_array =&gt; $_-&gt;datastore);

foreach my $datastore (@$datastores) {

my $instances = @{$datastore-&gt;host};

my $instance = 0;

while($instance &lt; $instances) {

my $x = Vim::get_view( mo_ref=&gt;$datastore-&gt;host-&gt;\[$instance\]-&gt;key);

print $datastore-&gt;summary-&gt;name," Datastore ", $x-&gt;name,"\n";

$instance++;

}

}

$counter++;

}

Doug Baer, Solution Architect, Advanced Services, Broadcom | VCDX #019, vExpert 2012-23
0 Kudos
DougBaer
Commander
Commander
Jump to solution

btw, I forget how you're formatting the code blocks... we used the code long ago...

Doug Baer, Solution Architect, Advanced Services, Broadcom | VCDX #019, vExpert 2012-23
0 Kudos
lamw
Community Manager
Community Manager
Jump to solution

Thanks, that actually worked. I had to change my "foreach" statement to the while loop:

 my $datastores = Vim::get_views (mo_ref_array => $cluster->datastore);
    foreach my $datastore (@$datastores) {
        my $host_instances = @{$datastore->host};
        my $host_index = 0;
        #foreach my $host_instance (@$host_instances) {
        while($host_index < $host_instances) {
                my $host = Vim::get_view (mo_ref => $datastore->host->[$host_index]->key);
                print $datastore->info->name," Datastore ", $host->summary->config->name,"\n";
                $host_index++;
        }

..your code..

to quote use the following:

{quote} ..your output.. {quote}

=========================================================================

--William

VMware ESX/ESXi scripts and resources at:

0 Kudos
DougBaer
Commander
Commander
Jump to solution

Good deal.

Doug Baer, Solution Architect, Advanced Services, Broadcom | VCDX #019, vExpert 2012-23
0 Kudos
lamw
Community Manager
Community Manager
Jump to solution

Given the following:

foreach my $cluster (@$clusters) {
        print "Cluster: ", $cluster->name, "\n";
        print "----------------------------------------------------------------------------------------\n";
        print "| \tDATASTORE \t";

        #get only connected hosts
        my $hosts = Vim::get_views (mo_ref_array => $cluster->host);
        my @my_array = ();
        foreach my $host (sort {$a->summary->config->name cmp $b->summary->config->name} @$hosts) {
                if ($host->runtime->connectionState->val eq 'connected') {
                        print " | \t", $host->summary->config->name, "\t ";
                        @my_array = (@my_array,$host->summary->config->name);
                }
                #else {
                #       print "\n",$host->summary->config->name, "maybe Disconnected or Not Responding\n";
                #}
        }
        print "\n----------------------------------------------------------------------------------------";
        print "\n";

        my $host_count = @my_array;

        my $datastores = Vim::get_views (mo_ref_array => $cluster->datastore);
        foreach my $datastore (sort {$a->info->name cmp $b->info->name} @$datastores) {
                if ( $datastore->info->isa ('VmfsDatastoreInfo') || $datastore->info->isa ('NasDatastoreInfo')  ) {
                        my $host_instances = @{$datastore->host};
                        my $host_index = 0;
                        my $print_start = 1;
                        while($host_index < $host_instances) {
                                my $host_view = Vim::get_view (mo_ref => $datastore->host->[$host_index]->key);
                                if ( $host_view->summary->config->name eq @my_array[$print_start] ) {
                                        print "found";
                                }
                                else {
                                        $print_start++;
                                }
                                #print "| ", $datastore->info->name,"\t | ", $host_view->summary->config->name, " |\n";
                                $host_index++;
                        }
                }
        }
}

I'm trying to take a list of Hosts and compare with all Datastores found within a Cluster and print out something like the following to determine if a host has access to given datastore.

|	DATASTORE	|	ESX_HOST_1	|	ESX_HOST_2	|
------------------------------------------------------------------------------------------------
|	DS_1		|	    x		|	   		|
|	DS_2		|	    		|	    x		|
|	DS_3		|	    x		|           x		|

but, I'm having some trouble comparing the value of the host at this line:

if ( $host_view->summary->config->name eq @my_array[$print_start] ) {

When I execute, I get nothing printed out, but when I print out the individual values from $host_view->summary->config->name or @my_array[$print_start], there are hosts that match.

Any ideas?

=========================================================================

--William

VMware ESX/ESXi scripts and resources at:

0 Kudos
DougBaer
Commander
Commander
Jump to solution

Sounds like a useful report Smiley Happy

I have seen weird things happen with dereferencing. I would try assigning $host_view->summary->config->name to a variable prior to the comparison, the compare $myvar to @my_array\[$print_start\] to see if that works any better.

Doug Baer, Solution Architect, Advanced Services, Broadcom | VCDX #019, vExpert 2012-23
0 Kudos
lamw
Community Manager
Community Manager
Jump to solution

That was a no go:

my $host_view = Vim::get_view (mo_ref => $datastore->host->[$host_index]->key);
                                my $host_obj = $host_view->summary->config->name;
                                if ( $host_obj eq $my_array[$print_start] ) {
                                        print "found";
                                }

I get the following error:

Use of uninitialized value in string eq at ./listCluster.pl line 82.

=========================================================================

--William

VMware ESX/ESXi scripts and resources at:

0 Kudos
DougBaer
Commander
Commander
Jump to solution

If line 82 is the new line, that indicates to me that $host_obj is not getting assigned anything. OR, it could be that $my_array\[$print_start\] is not assigned...

You said that printing $host_view->summary->config->name actually prints a value? It looks like it should print the name of the host.

If you don't mind sharing the script, it would probably make troubleshooting go a little faster -- you can PM me.

Doug Baer, Solution Architect, Advanced Services, Broadcom | VCDX #019, vExpert 2012-23
0 Kudos
lamw
Community Manager
Community Manager
Jump to solution

I've attached the script to this reply. I'm actually trying to learn how the VI API works and I thought it would be an interesting project to see if I can try to replicate the following:

http://www.yellow-bricks.com/2009/01/19/compare-your-hosts/

but for those that don't use powershell.

Thanks for your help DougBaer

=========================================================================

--William

VMware ESX/ESXi scripts and resources at:

0 Kudos
DougBaer
Commander
Commander
Jump to solution

Rather ambitious, but definitely worthwhile and a way to learn the API Smiley Happy

I will take a look at the script a little this morning and tomorrow -- I've got obligations this afternoon, but I want to see this work.

Doug Baer, Solution Architect, Advanced Services, Broadcom | VCDX #019, vExpert 2012-23
0 Kudos
lamw
Community Manager
Community Manager
Jump to solution

I hope it's not too ambitious Smiley Wink

I've taken a quick look at the powershell compare script and all that's really going on is three loops based on cluster information and taking the list of hosts and checking to see if they all contain the same configuration (datastore,lun and portgroups) and only printing out when you find differences. I think the difficult part will be figuring out what to look for in the API to extract certain pieces of information. I agree it's definitely a great way to learn about the API and hopefully I can see this through too, the concept of the script sees very useful.

=========================================================================

--William

VMware ESX/ESXi scripts and resources at:

0 Kudos
DougBaer
Commander
Commander
Jump to solution

I think you have an off-by-one error... change my $host_print_start = 1 to 0 ... I think it is around line 83/84

...and you want to change your array references to use $ instead of @ when you're grabbing the values:

@array[$index]  should be written $array[$index]

Doug Baer, Solution Architect, Advanced Services, Broadcom | VCDX #019, vExpert 2012-23
0 Kudos
DougBaer
Commander
Commander
Jump to solution

Nah, the Powershell is just easier because so much of the API's complexity is hidden by the commandlets. As long as the information is available and you can figure out how to navigate the API, you'll be fine. I'll warn you that networking is a little odd, IMHO, but the MOB is your friend.

Doug Baer, Solution Architect, Advanced Services, Broadcom | VCDX #019, vExpert 2012-23
0 Kudos
lamw
Community Manager
Community Manager
Jump to solution

Thanks, I think I remember why I set the initial value to 1 but now I have to think about how to store or output the information.

Yea I agree powershell definitely hides quite a bit and does make it somewhat easier. This will definitely be a trial/error project for me. I will post more information or questions as they come up, Thanks.

=========================================================================

--William

VMware ESX/ESXi scripts and resources at:

0 Kudos
lamw
Community Manager
Community Manager
Jump to solution

Okay, here is what I have so far and attached is the latest revision of the script and here is a quick sample output:

[vi-admin@vima-primp-industries ~]$ ./run.sh
Cluster: PrimpESX-cluster
----------------------------------------------------------------------------------------
|       DATASTORE        |      172.30.0.61       |     172.30.0.64
----------------------------------------------------------------------------------------
| appalachian-local-SAS.Storage | FALSE (172.30.0.61) | FALSE (172.30.0.64) |
| appalachian-local-U320.Storage | FALSE (172.30.0.61) | FALSE (172.30.0.64) |
| himalaya-local-SAS.VMStorage | TRUE (172.30.0.61) | FALSE (172.30.0.64) |
| himalaya-local-SAS.primp.Ind-1 | TRUE (172.30.0.61) | FALSE (172.30.0.64) |
| himalaya-local-SATA.Storage | TRUE (172.30.0.61) | FALSE (172.30.0.64) |
| kevin-test-nfs-storage | TRUE (172.30.0.61) | FALSE (172.30.0.64) |
| olga-local-SAS.Storage | FALSE (172.30.0.61) | TRUE (172.30.0.64) |
| tuan-test-nfs-storage | TRUE (172.30.0.61) | FALSE (172.30.0.64) |
----------------------------------------------------------------------------------------
|       LUN              |
----------------------------------------------------------------------------------------

----------------------------------------------------------------------------------------
|       PORTGROUP        |
----------------------------------------------------------------------------------------

I'm not sure why some of the local storage datastores are showing up, based on the initial sample listCluster.pl script, it's able to differentiated between LOCAL, NFS and SHARED VMFS or at least that's how I perceived it. With the code, it should exclude local storage.

Anywho, I might be a little stuck on the next section of retrieving all LUNs and comparing it with the list of hosts that can see the LUNs

Looking at the API reference, here is what I'm thinking and it might be as easy as reusing the existing code but substituting LUN information:

my $luns = Vim::get_views (mo_ref_array =&gt; $cluster-&gt;host);Here is where I think it might get tricky since now the reference is of an array of objects which then needs to be dereference to get to the storageDevice which allows you to get to the scsiLun which is an array of LUN's and you can then print out uuid or canonicalName

#deref = cluster-&gt;host-&gt;[$x]-&gt;key

#@host_deref = @deref-&gt;config-&gt;storageDevice-&gt;scsiLun

#host_deref-&gt;uuid

#host_deref-&gt;canonicalNameI'm not too sure if this is the right way to go or am I off?

I have the following but still missing something:

my $luns = Vim::get_views (mo_ref_array => $cluster->host);
        my $x = 0;
        foreach my $lun (@$luns) {
                my $lun_view = Vim::get_view (mo_ref => $lun->host->[$x]->key);
                my @logicalunitlist = @{$lun_view->host->config->storageDevice->scsiLun};

                foreach(@logicalunitlist) {
                        print $_->canonicalName;
                }
                $x++;
        }

Can't locate object method "host" via package "HostSystem" at ./compareCluster.pl line 108.

End Disconnect

=========================================================================

--William

VMware ESX/ESXi scripts and resources at:

0 Kudos
DougBaer
Commander
Commander
Jump to solution

This will take a bit of time for me to play with and digest and I am trying to interpret the output from my lab. For me, the local datastores report properly, but the shared datastores only show up accessible by the first host.

I believe the only way the script can tell the difference between the types of datastores is by type, and I don't see that being checked in the script anywhere.

(datastore->sumamry->type), and multiple access property (datastore->summary>multipleHostAccess). I don't currently have any NFS datastores in my lab, but I would imagine the same holds true there.(your interpretation of LOCAL would be a combination of type = "VMFS" and multipleHostAccess = "true"

I'll kick this around this morning.

Doug Baer, Solution Architect, Advanced Services, Broadcom | VCDX #019, vExpert 2012-23
0 Kudos
DougBaer
Commander
Commander
Jump to solution

Try this to filter out local datastores... the problem is that LOCAL and VMFS are not mutually exclusive... In fact, LOCAL is just a subset of VMFS.

  if ( ($datastore->info->isa ('VmfsDatastoreInfo') || $datastore->info->isa ('NasDatastoreInfo')) && 
        $datastore->summary->multipleHostAccess ) {

Doug Baer, Solution Architect, Advanced Services, Broadcom | VCDX #019, vExpert 2012-23
0 Kudos