VMware {code} Community
monkeedu8
Contributor
Contributor
Jump to solution

Problem using cdromdisconnect.pl to check for CD-ROM usage on VMs

I am having trouble with this script, cdromdisconnect.pl, and I was hoping someone could help me with it...

When I run 'cdromdisconnect.pl --host my.esx.host --op list --server my.vc.host --passthroughauth', I get 'Host my.esx.host not found.' Yet when I run 'datacenterlisting.pl --datacenter MyDC' it finds 'my.esx.host' just fine. Am I missing something here? Why is the cdrom script not able to find hosts when other scripts have no trouble?

Any help would be appreciated.

-monkeedu

0 Kudos
1 Solution

Accepted Solutions
stumpr
Virtuoso
Virtuoso
Jump to solution

AFAIK, there isn't a way to do a view on a MoRef, just on property values. You can't, for example, match against an array property value. You'll need to adjust your script logic. Once you have your host system view ($host), then you should use the vm property ($host->vm) to get a list of Virtual Machines.

You probably need to change:

my $host_moRef = $host->{mo_ref}{value};
#######################################################################################
#	Get all VMs that are currently running on that ESX Server
#######################################################################################

my $vm_views = Vim::find_entity_views(view_type => 'VirtualMachine', filter => {'runtime.host' => $host_moRef});
my $numDevices = 0;
foreach my $vm_view (@$vm_views) {

to:

#######################################################################################
#	Get all VMs that are currently running on that ESX Server
#######################################################################################

my $numDevices = 0;
my $vm_view;
foreach (@{$host->vm}) {
     $vm_view = Vim::get_view( mo_ref => $_ );

There are some optimizations I can suggest to speed it up, but its probably best to get it working first. Smiley Happy

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

View solution in original post

0 Kudos
14 Replies
stumpr
Virtuoso
Virtuoso
Jump to solution

I would try it without the passthru just to be sure, use --username= and --password= with a valid VC login.

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

Yes, I have tried with and without the pass-through. Neither worked.

0 Kudos
stumpr
Virtuoso
Virtuoso
Jump to solution

I wonder if your name and FQDN names are not the same.

Try the following script, I set my test host in a state where the two don't match.

#!/usr/bin/perl -w

use strict;
use warnings;

use VMware::VIRuntime;

Opts::parse();
Opts::validate();

Util::connect();

my ($hostname, $name, $hosts_view);

$hosts_view = Vim::find_entity_views( view_type => "HostSystem");

foreach ( @{$hosts_view} )
{
	$name = $_->name;
	$hostname = $_->config->network->dnsConfig->hostName;
	$hostname .= $_->config->network->dnsConfig->domainName;
	
	print "Name = $name; hostname = $hostname\n";
}

Util::disconnect();

Output:

$ perl FindHost.pl --username=root --password=vmware --server=172.16.14.51
name = ESX-02.vmwlab.local; hostname = ESX-01.vmwlab.local

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

It doesn't matter which I use, the name or the FQDN, both fail to find the host. Just as a test, I attempted to run the same script using the ESX host as the --server option instead of Virtual Center, and now I get a different error:

C:\Program Files\VMware\VMware VI Perl Toolkit\Perl\apps\vm>cdromdisconnect.pl --op list --server my.esx.host
Enter username: xxxxxxx
Enter password: xxxxxxx
Filtering is only supported for Simple Type
 at C:\Program Files\VMware\VMware VI Perl Toolkit\Perl\apps\vm\cdromdisconnect.pl line 68

End Disconnect

I can see where the script is using the filter, but I don't know enough Perl and its use with the VM API to understand what Simple Type is.

Here is the script:

#!/usr/bin/perl -w
use strict;
use warnings;
use Getopt::Long;
use VMware::VIRuntime;
use VMware::VILib;

# cdromDisconnect.pl
#	To get usage, run pod2html.
#
#	Copyright 2007, VMware Inc.  All rights reserved.
#	Script provided as a sample.
#	DISCLAIMER. THIS SCRIPT IS PROVIDED TO YOU "AS IS" WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 
#     WHETHER ORAL OR WRITTEN, EXPRESS OR IMPLIED. THE AUTHOR SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES 
#     OR CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. 
#
my %opts = (
   host  => {
      type     => "=s",
      variable => "host",
      help     => "Host Name",
      required => 0},
   op  => {
      type     => "=s",
      variable => "operation",
      help     => "Operation (list|disconnect)",
      default  => 'list',
      required => 0},

);

my $env;						# a static variable to cache $env MO
my $login = 0;					# keep track if you logged in.
# validate options, and connect to the server
Opts::add_options(%opts);
Opts::parse();
Opts::validate();
my $op = Opts::get_option ('op');
Fail ("Usage: Op must be list, or disconnect.\n") 
   unless ($op =~ /^list|disconnect$/);
Util::connect();
$login = 1;							# used by Fail.
$| = 1;							# set to unbuffered I/O, improves messages to console

#######################################################################################
#	Decide what type of connection that you have
#		... If through VC, then you need to get the host name argument
#           ... If through ESX, then collect the ESX host view
#######################################################################################
my $host_name;
my $host;
my $sc = Vim::get_service_content();
if ($sc->about->apiType eq "VirtualCenter") {
    Fail ("Please supply the --host parameter.\n") unless (Opts::option_is_set ('host'));
    $host_name = Opts::get_option('host');
    $host = Vim::find_entity_view(view_type => 'HostSystem', filter => {'name' => "$host_name\$"});
    Fail ("Host $host_name not found.\n") unless ($host);
    die "Host ". $opts{host}. " not host found." unless ($host);
    }
else {
    $host = Vim::find_entity_view(view_type => 'HostSystem');
     }    
my $host_moRef = $host->{mo_ref}{value};
#######################################################################################
#	Get all VMs that are currently running on that ESX Server
#######################################################################################

my $vm_views = Vim::find_entity_views(view_type => 'VirtualMachine', filter => {'runtime.host' => $host_moRef});
my $numDevices = 0;
foreach my $vm_view (@$vm_views) {
    next unless ($vm_view->runtime->powerState->val eq 'poweredOn');	# ignore if VM is not powered on
    my $devices = $vm_view->config->hardware->device;
    my $vm_name = $vm_view->name;
    foreach my $device (@$devices) {
        my $name = $device->deviceInfo->label;
        next unless ($device->isa ('VirtualCdrom'));					# look of only CDROM's
        next unless ($device->backing->isa ('VirtualCdromAtapiBackingInfo')); # only connected to host devices
        next unless ($device->connectable->connected == 1);				# only those who are connected
        if ($op eq 'list') {
            print "Virtual Machine      Device\n----------------------------\n" if ($numDevices == 0);
            printf "%-20.20s %s\n", $vm_name, 
                                    $name;
            }
        else {											# simply change the connected flag
            $device->connectable->connected(0);
            my $devSpec = VirtualDeviceConfigSpec->new(
                             operation => VirtualDeviceConfigSpecOperation->new('edit'),
                             device => $device);
            Reconfig ($vm_view, $devSpec, "Disconnecting $name on $vm_name");
            }
         $numDevices++;
        }
    }
print $numDevices, " devices found.\n";
# logout
Util::disconnect();

#########################################################################################
#  Reconfig calls ReconfigVM and interprets status /errors
#########################################################################################

sub Reconfig {
    my ($vm, $devSpec, $msg) = @_;
    print ("$msg ... ");
    my $vmspec = VirtualMachineConfigSpec->new( deviceChange => [$devSpec] );
    eval {
        $vm->ReconfigVM( spec => $vmspec );
         };
    if ($@) {
        print "reconfiguration failed.\n ";
        if ($@->isa ('SoapFault')) {
            print $@->fault_string, "\n";
            }
        else {
            print $@;
            }
        }
    else {
        print "succeeded.\n";
        }
    }

sub Fail {
    my ($msg) = @_;
    Util::disconnect() if ($login);
    die ($msg);
    exit ();
}

0 Kudos
stumpr
Virtuoso
Virtuoso
Jump to solution

The name passed to rye script has to match the ManagedObject property. It is possible the DNS hostname could differ from this property. Did you run the script I posted? I would just do a quick sanity check, looks like it couldn't find a host matching the string you passed to the disconnect script.

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

I ran your script and found something interesting. The names did NOT match the hostnames. Every hostname was missing a '.' I went back and tried to run the original script with the incorrect hostname, and it still failed with a host not found error.

To recap:

C:\Program Files\VMware\VMware VI Perl Toolkit\Perl\apps\vm>checkfqdn.pl --server my.vc.host
Enter username: xxxxx
Enter password: xxxxx
Name = esx01.host.local; hostname = esx01host.local
Name = esx02.host.local; hostname = esx02host.local
Name = esx03.host.local; hostname = esx03host.local

C:\Program Files\VMware\VMware VI Perl Toolkit\Perl\apps\vm>cdromdisconnect.pl --server my.vc.host --host esx01host.local
Enter username: xxxxxx
Enter password: xxxxxx
Host esx01host.local not found.

C:\Program Files\VMware\VMware VI Perl Toolkit\Perl\apps\vm>cdromdisconnect.pl --server my.vc.host --host esx01.host.local
Enter username: xxxxxx
Enter password: xxxxxx
Host esx01.host.local not found.

C:\Program Files\VMware\VMware VI Perl Toolkit\Perl\apps\vm>cdromdisconnect.pl --server esx01host.local
Enter username: xxxxx
Enter password: xxxxx
Error connecting to server at 'https://esx01host.local/sdk/webService': Bad hostname

C:\Program Files\VMware\VMware VI Perl Toolkit\Perl\apps\vm>cdromdisconnect.pl --server esx01.host.local
Enter username: xxxxx
Enter password: xxxxx
Filtering is only supported for Simple Type
 at C:\Program Files\VMware\VMware VI Perl Toolkit\Perl\apps\vm\cdromdisconnect.pl line 68

End Disconnect

0 Kudos
stumpr
Virtuoso
Virtuoso
Jump to solution

I think that is my fault. I missed a "." in the print. Sorry. :). But looks like your hostnames match your name property. Does it work ok any other names?

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

Nope, not a single one. Which makes me think its either a problem with the script, or some odd firewall issue, though I doubt firewalls are the problem.

0 Kudos
stumpr
Virtuoso
Virtuoso
Jump to solution

I think I found the problem.

It looks like there is a '$' in the filter parameter to the find_entity_view and is breaking your string for a match. I'm guessing it was added in an attempt to make a full string match, but should be done as a qr//.

You should change the following line:

    $host = Vim::find_entity_view(view_type => 'HostSystem', filter => {'name' => "$host_name\$"});

to:

    $host = Vim::find_entity_view(view_type => 'HostSystem', filter => {'name' => qr/$host_name$/});

or:

    $host = Vim::find_entity_view(view_type => 'HostSystem', filter => {'name' => "$host_name"});

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

Close! That change gets past the first 'filter' issue. But the second one still remains:

C:\Program Files\VMware\VMware VI Perl Toolkit\Perl\apps\vm>cdromdisconnect.pl --server my.vc.local --passthroughauth --host my.esx01.local
Filtering is only supported for Simple Type
 at C:\Program Files\VMware\VMware VI Perl Toolkit\Perl\apps\vm\cdromdisconnect.pl line 69

End Disconnect

Line 69 in the cdrom script I have refers to:

my $vm_views = Vim::find_entity_views(view_type => 'VirtualMachine', filter => {'runtime.host' => $host_moRef});

Again, I don't know Perl from Ruby from Ada from a hole in the ground, what would I do to go about fixing this line? Something like this:

my $vm_views = Vim::find_entity_views(view_type => 'VirtualMachine', filter => {'runtime.host' => "$host_moRef\$"});

Thanks for all your help. You've certainly gotten me further than I'd have gotten on my own!

-monkeedu

0 Kudos
stumpr
Virtuoso
Virtuoso
Jump to solution

AFAIK, there isn't a way to do a view on a MoRef, just on property values. You can't, for example, match against an array property value. You'll need to adjust your script logic. Once you have your host system view ($host), then you should use the vm property ($host->vm) to get a list of Virtual Machines.

You probably need to change:

my $host_moRef = $host->{mo_ref}{value};
#######################################################################################
#	Get all VMs that are currently running on that ESX Server
#######################################################################################

my $vm_views = Vim::find_entity_views(view_type => 'VirtualMachine', filter => {'runtime.host' => $host_moRef});
my $numDevices = 0;
foreach my $vm_view (@$vm_views) {

to:

#######################################################################################
#	Get all VMs that are currently running on that ESX Server
#######################################################################################

my $numDevices = 0;
my $vm_view;
foreach (@{$host->vm}) {
     $vm_view = Vim::get_view( mo_ref => $_ );

There are some optimizations I can suggest to speed it up, but its probably best to get it working first. Smiley Happy

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

Beautiful. That change has it working exactly as intended. Now I need to understand why what is intended isn't what I need it to do. lol

What this script shows are Virtual Machines that are pointing to the host device for their cd-rom, which is useful, but I need to know if a VM's cd-rom is pointing to anything at all; client device, host device, or datastore iso. As a test, I pointed a VM to an iso, then ran this script against its host, and the script reported no devices. Any advice? 😛

-monkeedu

0 Kudos
stumpr
Virtuoso
Virtuoso
Jump to solution

Well, I didn't write the original script, but I'll take a stab at it. The script is there to address the problem where you go to VMotion a Virtual Machine and find that it has a CDROM backed to the ESX host CDROM drive. This would cause the VMotion to fail, whereas a datastore backed ISO would not block vmotion. So people started creating tools to automatically disconnect ESX host backed CDROMs. I suspect this script was written with the intent to address that issue, so the list operation just checks for ESX host CDROM drive connections.

You can see that it ignores all but Atapi (ESX Host CDROM devices) with the following line in the code:

next unless ($device->backing->isa ('VirtualCdromAtapiBackingInfo')); # only connected to host devices

Essentially the script author skips any device that is not (isa test) a VirtualCdrom and the backing isn't a VirtualCdromAtapiBackingInfo. If you comment out the line I quoted above, it will pretty much work on any CDROM device. This may or may not be your final intended result, but would likely be a quick fix. After making that change, you'll list and disconnect all cdrom devices depending on how you run the script.

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

Awesome. It does what I need now with that line commented out. Maybe I'll get crazy and try to write a new, similar script that is more targeted at just the reporting I need (yeah right!). Thanks for your help, I appreciate it!

-monkeedu

0 Kudos