Automation

 View Only
  • 1.  Create a list of all VMs with mismatched names

    Posted 24 days ago

    Hello, 

    I have created a list of VMs which I suspect are running under different names. I have created a simple script to import that list, then copy the .vmx file to a temp file in order to find the 'displayname' which is the actual name the VM is running under. This works in some cases, but in other cases I'm getting this error:
    Download of file 'https://MYVCETNER.com/folder/lun01&enc=std' failed. Error message: Response status code does not indicate success: 500 (Internal Server Error).    

    Even though I have confirmed that the working VMs and non-working VMs are online and running I cannot find any reason that I get this error in some cases and others I don't.

    While I investigate why it's not working I'd like to add a catch which will simply add "ERROR" to the results variable so that I can flag which results I need to follow up on, but the logic for catch statements is eluding me. If there's an error I want to it be marked as an error, if not I just want the script to continue on:


    $mismatches = Import-Csv -Path C:\output\UnregisteredVms4.csv
    $tempFile = New-TemporaryFile
    
    ForEach ($mismatch in $mismatches) {
        try {
            Copy-DatastoreItem -Item $mismatch.fullname -Destination $tempFile -ErrorAction:Stop | Out-Null
            }
             catch {
             $result = "ERROR"
             }
            $VCVMName = Get-VM -Name (Get-Content -Path $tempFile | where{$_ -match 'displayName'}).Split('"')[1]
            $VCname = (Get-Content -Path $tempFile | where{$_ -match 'displayName'}).Split('"')[1]
            $RegisteredVCenter = $VCVMName.Uid.Substring($VCVMName.Uid.IndexOf('@')+1).Split(":")[0]
            $DSVMName = $mismatch.name
            $DSpath = $mismatch.datastorefullpath
            $result = "$VCVMName was found on vCenter $RegisteredVCenter however it is named $DSVMName on disk."
            }
    write-host "$result"
    Remove-Item -Path $tempFile
    $result
        


  • 2.  RE: Create a list of all VMs with mismatched names
    Best Answer

    Posted 23 days ago

    Can you download the file in $mismatch.fullname via the Web client?
    Do you use an account to connect to the vCenter that has the required privileges (role) to access the file?

    I think you misplaced the Catch block in your code.
    It is now sitting inside the the Try block, but it should follow that Try block.
    Something like this

    $mismatches = Import-Csv -Path C:\output\UnregisteredVms4.csv
    $tempFile = New-TemporaryFile
    
    ForEach ($mismatch in $mismatches) {
        Write-Host "Looking at $($mismatch.fullname)"
        try {
            Copy-DatastoreItem -Item $mismatch.fullname -Destination $tempFile -ErrorAction:Stop | Out-Null
            $VCVMName = Get-VM -Name (Get-Content -Path $tempFile | where { $_ -match 'displayName' }).Split('"')[1]
            $VCname = (Get-Content -Path $tempFile | where { $_ -match 'displayName' }).Split('"')[1]
            $RegisteredVCenter = $VCVMName.Uid.Substring($VCVMName.Uid.IndexOf('@') + 1).Split(":")[0]
            $DSVMName = $mismatch.name
            $DSpath = $mismatch.datastorefullpath
            $result = "$VCVMName was found on vCenter $RegisteredVCenter however it is named $DSVMName on disk."
        } 
        catch {
            $error[0]
            $result = "ERROR"
        }
        Write-Host "$result"
    }
    


    ------------------------------


    Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference


    ------------------------------



  • 3.  RE: Create a list of all VMs with mismatched names

    Posted 22 days ago

    Thanks LucD, the logic makes complete sense now that I see it like that.

    In regards to your question about downloading the .vmx file, I literally cannot do anything with the .vmx file on VMs which are running, this includes both VMs which are WORKING using the script and the examples which are erroring out. I can't even cat the contents of the .vmx file by logging directly into one of the esxi hosts and browsing the directory of the VM. Here is an example of a working VM:

    I'm testing using a VM which is powered on, the name is mismatched to the .vmx name on disk <-- these are the VMs I'm particularly interested in catching to find the running name in the .vmx file under 'displayname'.


    Can you download the file in $mismatch.fullname via the Web client?

    Download the .vmx via web client - ERROR - this page is not working right now.
    Download another fie to test the browser can download files - SUCCESS - I can download a .log file, but not the .vmx file.
    Log directly into one of the esxi hosts via putty - browse to the .vmx fie location. 
    cat unregistered_IOMEGA1.vmx
    cat: can't open 'unregistered_IOMEGA1.vmx': Device or resource busy
    [root@extreme:/vmfs/volumes/5feba04b-9a0e67e4-7b48-000c29de29f0/unregistered_IOMEGA1
    vi unregistered_IOMEGA1.vmx
    (file comes up blank in the editor)
    cp unregistered_IOMEGA1.vmx Test_unregistered_IOMEGA1.vmx
    cp: can't open 'unregistered_IOMEGA1.vmx': Device or resource busy
    [root@extreme:/vmfs/volumes/5feba04b-9a0e67e4-7b48-000c29de29f0/unregistered_IOMEGA1

    Do you use an account to connect to the vCenter that has the required privileges (role) to access the file?
    I have used administrator@vsphere.local for all of the tests above.


    Important Note - In the example above this is working when I use the script, however I have tried all the above tests with a VM which isn't working and I see the exact same behavior. It appears this is working as designed for any running VM, the .vmx file is protected from being downloaded, modified, or copied, however in most cases the script is able to copy it to my $tempfile (if anything, I don't understand why this is working).

    This seems to be more of a VMware questions than a scripting question, but I'm curious if you have an insights.




  • 4.  RE: Create a list of all VMs with mismatched names

    Posted 20 days ago

    Getting closer, the goal with this script is to:
    1. Find all .vmx files on the datastore
    2. Try to match with a VM in the vcenter inventory
    3. If unable to match, see if there is a .lck file which would confirm the VM is running using a different name.
    4. If the VM is found to be running due to the presence of a .lck file, attempt to download the .vmx file to local temp file. Catch errors and report

    The final output should be a list of all mistmatched VMs, VMs which were removed from inventory but not deleted properly, and a list of VMs which could not be checked (I'll continue to troubleshoot why these don't work).

    Something is wrong with my else statement placement, but it's a bit beyond me:

    #PERMISSIONS REQUIRED - Datastore.Browse + Datastore.Low level file operations
    $Datastores = Get-Datastore | Where-Object {$_.name -notmatch "local" -and $_.name -notmatch "NFS"}
    $unregistered = @()
    ForEach ($datastore in $datastores) {
        $psds = Get-Datastore -Name $datastore
        New-PSDrive -Name TgtDS -Location $psds -PSProvider VimDatastore -Root '\' | Out-Null
        #Find every single .vmx file on the datastore.
        $VMXS = Get-ChildItem -Path TgtDS: -Recurse -Filter *.vmx | Where-Object {$_.name -notmatch "vCLS-*" -and $_.name -notmatch "zerto*"}
        Write-Host "Starting $datastore"
        $tempFile = New-TemporaryFile
        foreach ($VMX in $VMXS) {
            #Attempt to find the VM in inventory based on the name of the .vmx file. If it can't find it, this VM may not be in inventory, or it could have a name mismatch.
            try {
                    Get-VM -datastore $datastore -name $VMX.name.replace('.vmx','') -ErrorAction:Stop | Out-Null
                } 
                catch {
                    $VMname = $VMX.name.replace('.vmx','')
                    #Check to see if there is a .lck file associated with the .vmx, if there is then VM is up and running under a different name.
                    $mismatch = Get-ChildItem -Path $VMX.PSParentpath -Filter *.lck | Where-Object {$_.name -contains "$($vmx.name).lck"}
                    if ($mismatch -ne $null) {
                        Write-Host "$($mismatch.fullname) is power-on and running under a different name. Attempting to check $VMX.FullName in order to find the correct displayname in vCenter."
                        try {
                            #Attempt to download the .vmx file to a local $temp file in order to get the actual displayname.
                            Copy-DatastoreItem -Item $VMX.FullName -Destination $tempFile
                            $displayname = Get-Content -Path $tempFile | where{$_ -match 'displayName'}
                            $vmxfilename  = $displayName.Split('"')[1]
                            $result = "NAME MISMATCH - Powered on and running as $vmxfilename."
                            Write-host "$VMname is running using a different name. Result-MISMATCH."
                        }
                        catch {
                            $error[0]
                            $result = "ERROR downloading $VMX.FullName. Confirm that account you are using has Datastore.Low level file operations."
                            }
                        else {
                            write-host "$VMname is not found on $global:DefaultVIServers.name and is not running. UNREGISTERED VM found."
                            $result = "UNREGISTERED."
                        }
                            $unregistered += [PSCustomObject] @{
                            Name = $vmx.Name
                            DatastoreFullPath = $vmx.DatastoreFullPath
                            LastWriteTime = $vmx.LastWriteTime
                            Result = $result
                    }
                }
            }
        }
            Write-Host "Done"
            Remove-PSDrive -Name TgtDS
            #Remove-Item -Path $tempFile
    }
    
    $unregistered  #  | export-csv -Path C:\output\UnregisteredVms3.csv -NoTypeInformation






  • 5.  RE: Create a list of all VMs with mismatched names

    Posted 11 days ago

    Hi LucD.

    Found the answer as to why I could do absolutely nothing with certain .vmx files, could not download, read, copy, etc.

    There are two different vCenters connected to the same LUNs. If I run the script when connected to vCenter1 it can't see the VMs which are running on vCenter2, so it lists them as unregistered VMs, however I cannot download any of the .vmx files for VMs which are running from vCenter2 because I have not authenticated to that vCenter.

    Now that I have a list of all VMs which had errors downloading the .VMX files I can now connect to vCenter2 and re-run the script to verify if the names are correct.

    Thanks for all your help!