VMware {code} Community
Sergio81
Contributor
Contributor
Jump to solution

How to retrieve the network information (NIC) for each VM (perl vim)

Hi,

I have this simple code to retrieve the name of all VirtualMachines in my infrastructure (filtered for datacenter)

[...other code...]

use VMware::VILib;
    Opts::add_options(%opts);
    Opts::parse();
    Opts::validate();
    Util::connect();

my $datacenter = $DCFILTER;

my $clusterFilter = $CLFILTER ;

my $datacenter_view = Vim::find_entity_view(view_type => 'Datacenter', filter => { name => $datacenter });

my @values = split(/\|/, $clusterFilter);

foreach my $val (@values) {

    my $cluster_view = Vim::find_entity_view(view_type => 'ClusterComputeResource', filter => { name => qr/$val/});

    my $vm_views = Vim::find_entity_views(view_type => 'VirtualMachine', begin_entity => $cluster_view);

    foreach (@$vm_views) {

   print $_->name . "\n";
   $vm = $_->name;

    }

}

Util::disconnect();

This code runs, but now I need to recover some information about network of each VM, specifically:

1)the network labels of each NIC  (for each VM)

2)the Adapter  Type (optionally)

3)Device status: Connected at power on (yes/no) (optionally).

I saw that exists the Managed Object - Network, property of Managed Object - VirtualMachine, but i don't know how to use it in my code and if contains the information i need (maybe "Summary")

Here one example:

network-examples.jpg

in this case i would like to know for this VM

1)LANBACKUP.... ; dvPP_LABO...; dvp_LABO...

and if is possible the information 2) and 3) for each NIC...in this case for NIC LANBAKUP...

2)Flexible

3)Connected at the power on: Yes

Can you help me to integrate my code for retrieve the above information?

Thank you very much, for your help.

Sergio

Reply
0 Kudos
1 Solution

Accepted Solutions
stumpr
Virtuoso
Virtuoso
Jump to solution

I would pre-fetch the DVS items:

my $dv_switches = Vim::find_entity_views(view_type => 'DistributedVirtualSwitch', properties => ['name', 'uuid']);

Then, you can look it up by UUID:

($this_dvs) = grep {$_->{'uuid'} eq $the_uuid} @$dv_switches;

This will give you the best performance as well, since you don't have to hit the API for every query (just the efficient first all DVS query).  You can add additional data from the DVSwitch object if you need it in your logic.

Reuben Stump | http://www.virtuin.com | @ReubenStump

View solution in original post

Reply
0 Kudos
8 Replies
stumpr
Virtuoso
Virtuoso
Jump to solution

Well, Flexible is basically just the VirtualPCNet32 adapter; VMware's UI just uses 'flexible' in the UI display.  So in that case you can easily check for it by reviewing the vm.config.hardware.device[] array with isa().

Pseudo logic from reference (not tested):

# For efficient collection, use limited property lists

@vms = Vim::find_entity_views(view_type => 'VirtualMachine', properties => ['name', 'config.hardware.device']);

foreach my $vm ( @vms ) {

print "vm: " . $vm->{'name'} . "\n";

@devs = @{ $vm->{'config.hardware.device'} };

# Pick out just network devices

@net_devs = grep { $_->isa('VirtualEthernetCard'} } @devs;

# iterate the network devices for each VM

foreach my $nic ( @net_devs ) {

     my ($name, $type, $network, $connect, $pg_mo, $pg);

     # NIC type

     if ($nic->isa('VirtualPCNet32') {

          $type = 'Flexible';

     } else {

          $type = ref $nic;

     }

     # The network object is specified as a reference, so it will need to be cross checked against the network objects to get the 'label'

     $pg_mo = $nic->{'backing'}{'network'};

     # You should pre-fetch all the network and DistributedVirtualPortgroup objects, doing a call for each is not efficient, but works

     $pg = Vim::get_view(mo_ref => $pg_mo, properties => ['name']);

     $network = $pg->{'name'};

     # For connect on power on, look at device connectable property

     $connect = ( eval {$nic->{'connectable'}{'startConnected'} ) ? 1 : 0;

     # NIC label (name)

     $name = $nic->{'deviceInfo'}{'label'};

     # Push your values into some csv output data struct or print them

     print "  nic '$name':\n";

     print "    connect on power on: $connect\n";

     print "    network portgroup: $network\n";

     print "    NIC type: $type\n";    

}

}

Reuben Stump | http://www.virtuin.com | @ReubenStump
Sergio81
Contributor
Contributor
Jump to solution

Thanks a lot!!!!

I did some tests and almost everything works.

The only problem I encounter is with a VM that has two NICs with Distributed Virtual Switch:

network-examples2.jpg

The name of this VM is LABO-TEST-MACHINE, and this is the output of the perl scripts:
[...]

VM Name: LABMXXXXX

    NIC type: VirtualE1000

  nic 'Network adapter 1':

    network portgroup: LANBACKUP_LABO

    NIC type: VirtualE1000

    NIC type: VirtualE1000

  nic 'Network adapter 2':

    network portgroup: HEARTBEAT_XXX

    NIC type: VirtualE1000


VM Name: LABO-TEST-MACHINE

    NIC type: Flexible

  nic 'Network adapter 1':

    network portgroup: LANBACKUP_LABO

    NIC type: Flexible

    NIC type: Flexible

Can't call method "type" on an undefined value at /usr/share/perl/5.10/VMware/VICommon.pm line 1026.

How you can see, i receive the error above, only when the script try to extract the Network Portgroup of that VM.

I think the code line with the problem is:

$pg = Vim::get_view(mo_ref => $pg_mo, properties => ['name']);


Instead with the Standard Virtual Switch, i didn't encounter problems.

Here's all new code:

my $datacenter = $DCFILTER;

my $clusterFilter = $CLFILTER ;

my $datacenter_view = Vim::find_entity_view(view_type => 'Datacenter', filter => { name => $datacenter });

my @values = split(/\|/, $clusterFilter);

foreach my $val (@values) {

        my $cluster_view = Vim::find_entity_view(view_type => 'ClusterComputeResource', filter => { name => qr/$val/});

        my $vm_views = Vim::find_entity_views(view_type => 'VirtualMachine', properties => ['name', 'config.hardware.device'], begin_entity => $cluster_view);

                foreach (@$vm_views) {

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

#                       $vm = $_->name;

                        my @devs = @{ $_->{'config.hardware.device'} };

                        my @net_devs = grep { $_->isa('VirtualEthernetCard') } @devs;

                        foreach my $nic ( @net_devs ) {

                                my ($name, $type, $network, $connect, $pg_mo, $pg);

                                # NIC type

                                if ($nic->isa('VirtualPCNet32')) {

                                        $type = 'Flexible';

                                } else {

                                $type = ref $nic;

                       }

                           print "    NIC type: $type\n";

                           $pg_mo = $nic->{'backing'}{'network'};

                          $pg = Vim::get_view(mo_ref => $pg_mo, properties => ['name']);

                           $network = $pg->{'name'};

#                          $connect = ( eval {$nic->{'connectable'}{'startConnected'} ) ? 1 : 0;

                           $name = $nic->{'deviceInfo'}{'label'};

                           print "  nic '$name':\n";

#                          print "    connect on power on: $connect\n";

                           print "    network portgroup: $network\n";

                           print "    NIC type: $type\n";

                        }

                }

}

Util::disconnect();

Reply
0 Kudos
stumpr
Virtuoso
Virtuoso
Jump to solution

It's possible the NIC doesn't have an assigned network portgroup.  So you can just check for an ignore it in cases where it's not set.  You may actually need to do this for a lot of properties in the API.  When building report tools in the past, I usually create an accessor method like 'get_property()' that does all the eval, undefined and other value checks and returns something for print sanity (empty string, 'null', etc).  There's actually a get_property() method that's on every object in the Perl SDK as well, but I don't use it myself.  Not sure how it handles undefined values.

$pg = Vim::get_view(mo_ref => $pg_mo, properties => ['name']) if defined $pg_mo;

$network = (defined $pg->{'name'}) ? $pg->{'name'} : 'unset';

Reuben Stump | http://www.virtuin.com | @ReubenStump
Sergio81
Contributor
Contributor
Jump to solution

Again thank you so much !!

The problem is that the most important information i want collect is the label of the NICs with Distributed Virtual Switch ... the only one who doesn't work) Smiley Sad

Reply
0 Kudos
stumpr
Virtuoso
Virtuoso
Jump to solution

It's probably unset.  If you're not familiar, you can use the vSphere MOB to explore it - https://your_vcenter_hostname:443/mob

I use that a lot when looking for "quirky" properties.

Reuben Stump | http://www.virtuin.com | @ReubenStump
Reply
0 Kudos
Sergio81
Contributor
Contributor
Jump to solution

Hi, now i use this code to  find the Portgroup name:

my $portgroupKey = $nic->{backing}->{port}->{portgroupKey};

                           my $dvsPortgroup = Vim::find_entity_view (

                                 view_type => "DistributedVirtualPortgroup",

                                 begin_entity => $datacenter_view,

                                 properties => [ 'name', 'key', 'config.distributedVirtualSwitch' ],

                                 filter => { 'key' => $portgroupKey }

                           );  

my $Portgroup_name = $dvsPortgroup->name;

this work.

and with this i can retrive the switch UUID:

my $SwitchUuid = $nic->{backing}->{port}->{switchUuid};

it's look like: 90 2d 05 40 1e 9f ba 9b-ea fe 3d ec 93 21 a1 ba

now i need to retrieve the DVSwitch real name, something like "dvs_TEST-DR"...can i use the UUID to find the associated DVS name, how?
Maybe is there a better way?

Thank You!!

Reply
0 Kudos
stumpr
Virtuoso
Virtuoso
Jump to solution

I would pre-fetch the DVS items:

my $dv_switches = Vim::find_entity_views(view_type => 'DistributedVirtualSwitch', properties => ['name', 'uuid']);

Then, you can look it up by UUID:

($this_dvs) = grep {$_->{'uuid'} eq $the_uuid} @$dv_switches;

This will give you the best performance as well, since you don't have to hit the API for every query (just the efficient first all DVS query).  You can add additional data from the DVSwitch object if you need it in your logic.

Reuben Stump | http://www.virtuin.com | @ReubenStump
Reply
0 Kudos
Sergio81
Contributor
Contributor
Jump to solution

Thank you very much Stumpr, now i have all i need Smiley Happy

Bye!!

Reply
0 Kudos