Automation

 View Only
  • 1.  Create a report of all unregistered VMs, then check them to see if they're running under different names

    Posted 19 days ago

    I've created a 2 stage script. This is because may need to break them up and run them with different permissions. Stage1 requires only read-only, stage2 required low level DS permissions. It's working, but I don't know how to update the existing $unregistered.result field prior to exporting it to csv:

    I've added #NOT WORKING to the parts I need help with.

    Thanks in advance!

    #Permission required - Stage 1 RO + Datastore.browse
    $Datastores = Get-Datastore | Where-Object {$_.name -notmatch "local" -and $_.name -notmatch "NFS"}
    #$Datastores = Get-Datastore -name IOMEGA
    $unregistered = @()
    Write-Host "Starting stage 1 - Identify unregistered VMs."
    ForEach ($datastore in $datastores) {
        $psds = Get-Datastore -Name $datastore
        New-PSDrive -Name TgtDS -Location $psds -PSProvider VimDatastore -Root '\' | Out-Null
        $VMXS = Get-ChildItem -Path TgtDS: -Recurse -Filter *.vmx | Where-Object {$_.name -notmatch "vCLS-*" -and $_.name -notmatch "zerto*"}
        #$VMXS = Get-ChildItem -Path TgtDS: -Recurse -Filter *.vmx | Where-Object {$_.name -eq "unregistered_IOMEGA1.vmx"}
        Write-Host "Starting $datastore"
        foreach ($VMX in $VMXS) {
            try {
                    Get-VM -datastore $datastore -name $VMX.name.replace('.vmx','') -ErrorAction:Stop | Out-Null
                    } 
                catch {
                    $mismatch = Get-ChildItem -Path $VMX.PSParentpath -Filter *.lck | Where-Object {$_.name -contains "$($vmx.name).lck"}
                    $unregistered += [PSCustomObject] @{
                        Name = $vmx.Name
                        DatastoreFullPath = $vmx.DatastoreFullPath
                        LastWriteTime = $vmx.LastWriteTime
                        vCNameMismatch = $mismatch.Name 
                        PSParentpath = $VMX.PSParentpath
                        FullName = $VMX.FullName
                        Result = "Unregistered"
                    }
                }
            }
            Write-Host "Done"
            Remove-PSDrive -Name TgtDS
    }
    $unregistered # | export-csv -Path C:\output\UnregisteredonlyVms3.csv -NoTypeInformation
    
    #Stage 2 Permission required - low level DS operations
    write-host "Unregistered VMs have been identified. Now checking to see if they are running under different names."
    $tempFile = New-TemporaryFile
    $lckdetecteds = $unregistered | select * | Where-Object {$_.vCNameMismatch -ne $null}
    ForEach ($lckdetected in $lckdetecteds) {
        Write-Host "Looking at $($lckdetected.fullname)"
        try {
            Copy-DatastoreItem -Item $lckdetected.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 = $lckdetected.name
            $DSpath = $lckdetected.datastorefullpath
            $result = "$VCVMName was found running on vCenter $RegisteredVCenter however it is named $DSVMName on disk."
            #NOTWORKING
            $unregistered.Result = $result
        } 
        catch {
            $error[0]
            $result = "ERROR"
            #NOT WORKING
            $unregistered.Result = $result
        }
        Write-Host "$result"
        Remove-Item -Path $tempFile
    }
    
    $unregistered
    










  • 2.  RE: Create a report of all unregistered VMs, then check them to see if they're running under different names
    Best Answer

    Posted 15 days ago

    Try changing Stage 2 to something like this

    #Stage 2 Permission required - low level DS operations
    Write-Host "Unregistered VMs have been identified. Now checking to see if they are running under different names."
    $tempFile = New-TemporaryFile
    foreach ($entry in $unregistered) {
        if ($entry.vCNameMismatch -ne $null) {
            Write-Host "Looking at $($entry.fullname)"
            try {
                Copy-DatastoreItem -Item $entry.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 = $entry.name
                $DSpath = $entry.datastorefullpath
                $result = "$VCVMName was found running on vCenter $RegisteredVCenter however it is named $DSVMName on disk."
                $entry.Result = $result
            } catch {
                $error[0]
                $result = "ERROR"
                #NOT WORKING
                $entry.Result = $result
            }
            Write-Host "$result"
        }
    }
    Remove-Item -Path $tempFile
    
    $unregistered


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


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


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



  • 3.  RE: Create a report of all unregistered VMs, then check them to see if they're running under different names

    Posted 15 days ago

    This solution was so simple at first I thought you didn't understand the question, because it couldn't possible work. Then it worked like always, and after studying it for like 20 minutes I get it now. Thanks LucD!

    I've added a few things just so that I can see the status of each stage, I may add a final stage to do some more checks. I still don't understand why some of the Copy-DatastoreItem -Item commands result in errors while others do not, I haven't been able to reproduce the error in my home lab. 

    Here is the final script:

    #Permission required - Stage 1 RO + Datastore.browse
    #STAGE1 - Search each datastore for all .vmx files, then search the VCenter inventory to see if there is a VM with that name in inventory. If there are none, add it to the list of suspected ungregistered VMs. ##
    $Datastores = Get-Datastore | Where-Object {$_.name -notmatch "local" -and $_.name -notmatch "NFS"}
    #$Datastores = Get-Datastore -name IOMEGA
    $unregistered = @()
    Write-Host "Starting stage 1 - Identify unregistered VMs."
    ForEach ($datastore in $datastores) {
        $psds = Get-Datastore -Name $datastore
        New-PSDrive -Name TgtDS -Location $psds -PSProvider VimDatastore -Root '\' | Out-Null
        $VMXS = Get-ChildItem -Path TgtDS: -Recurse -Filter *.vmx | Where-Object {$_.name -notmatch "vCLS-*" -and $_.name -notmatch "zerto*"}
        #$VMXS = Get-ChildItem -Path TgtDS: -Recurse -Filter *.vmx | Where-Object {$_.name -eq "unregistered_IOMEGA1.vmx"}
        Write-Host "Starting $datastore"
        foreach ($VMX in $VMXS) {
            try {
                    Get-VM -datastore $datastore -name $VMX.name.replace('.vmx','') -ErrorAction:Stop | Out-Null
                    } 
                catch {
                    $mismatch = Get-ChildItem -Path $VMX.PSParentpath -Filter *.lck | Where-Object {$_.name -contains "$($vmx.name).lck"}
                    $unregistered += [PSCustomObject] @{
                        Name = $vmx.Name
                        DatastoreFullPath = $vmx.DatastoreFullPath
                        LastWriteTime = $vmx.LastWriteTime
                        vCNameMismatch = $mismatch.Name 
                        PSParentpath = $VMX.PSParentpath
                        FullName = $VMX.FullName
                        Result = "Stage1 Unregistered VM suspected."
                    }
                }
            }
            Write-Host "Done"
            Remove-PSDrive -Name TgtDS
    }
    
    $stage1 = $unregistered | select * | Where-Object {$_.name -ne $null -and $_.vCNameMismatch -eq $null}
    $lckdetecteds = $unregistered | select * | Where-Object {$_.name -ne $null -and $_.vCNameMismatch -ne $null}
    
    if ($stage1 -ne $null){
        write-host "The following suspected unregistered VMs were found:"
        $($stage1.name.Replace('.vmx',''))
    }
    
    
    if ($lckdetecteds -ne $null) {
        write-host "The following VMs have .lck files associated with them, indicating they are presently running under a different name. Stage 2 will attempt to determine the name."
        $($lckdetecteds.name.Replace('.vmx',''))
    }
        elseif ($stage1 -eq $null){
        write-host "There were no unregistered VMs found."
    }
        
    #Stage 2 Permission required - low level DS operations
    Write-Host "Starting Stage 2 - Attempting to determine the name VMs are running under within vCenter:"
    $tempFile = New-TemporaryFile
    foreach ($entry in $unregistered) {
        if ($entry.vCNameMismatch -ne $null) {
            Write-Host "Checking to see if $($entry.name.Replace('.vmx','')) is running on $global:DefaultVIServer under a different name."
            try {
                Copy-DatastoreItem -Item $entry.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 = $entry.name
                $DSpath = $entry.datastorefullpath
                $result = "$VCVMName is POWERED-ON on $RegisteredVCenter. It is named $DSVMName on disk."
                $entry.Result = $result
            } catch {
                $error[0]
                $result = "ERROR downloading .vmx to local temp file."
                $entry.Result = $result
            }
            Write-Host "$result"
        }
    }
    Remove-Item -Path $tempFile
    
    $unregistered