Param ( [Parameter(Mandatory=$false,Position=0)][string]$Version = "1.1", #Script version [Parameter(Mandatory=$True,Position=0)][string]$MG, #Script version [switch]$GUI, #Are we invoking this from the GUI [switch]$Dropouts #User wants to see the items we're not capturing in the \Dropouts directory ) ############################################################################################################################# Function Generate-VMPSO ($Line, $StartPosition, $PrimaryBreakCharacter, $AlternateBreakCharacter) <# *********************************************************************************************************** *********************************************************************************************************** #> { #Adding the VM data to our comprehensive array $VMPSO = [PSCustomObject]@{ Name = (ParseLine $VM.name 0 "." " ")[0]; Number = (ParseLine $VM.name 0 "-" " ")[0]; vCPU = $VM.vCPU; vRAM = $VM.memoryGB; Cluster = $ShortClusterName; power_state = $VM.power_state; hypervisor = $Hypervisor.name; DC = $DC } return $VMPSO } ############################################################################################################################# Function ParseLine ($Line, $StartPosition, $PrimaryBreakCharacter, $AlternateBreakCharacter) <# *********************************************************************************************************** This function is passed a string, a position in the string to start and two characters on which if encountered the processing of the string will stop. This is used to extract information from a messy and/or inconsistent string. Essentially you pass it a string and tell it where you want it to stop and on what character (up to two) you want it to stop. It will return all the characters between where you told it to start and the stop character, not including the stop character. It also returns the position in the string where it encountered the stop character. *********************************************************************************************************** #> { $ResultArray=@("string",2) $PrimaryValue=@() $CurrentLine = 0 $LineLength = $Line.Length - 1 for ($ParseLoop = $StartPosition; $ParseLoop -le $LineLength; $ParseLoop++) { If ($Line[$ParseLoop] -eq $PrimaryBreakCharacter -or $Line[$ParseLoop] -eq $AlternateBreakCharacter) { $CurrentLine = $ParseLoop $ParseLoop = $LineLength } Else { $PrimaryValue += $Line[$ParseLoop] } } $PrimaryValue = -join $PrimaryValue $ResultArray[0] = $PrimaryValue $ResultArray[1] = $CurrentLine Return $ResultArray } ############################################################################################################################# #Getting the current directory and importing the CTKCore module $Dir=(Get-Item -Path . -Verbose).FullName $CTKModule = [string]((get-item $Dir).parent.fullname)+"\Modules\CTKCore\CTKCore.psm1" $ExcelModule = [string]((get-item $Dir).parent.fullname)+"\Modules\ExcelHandlers\ExcelHandlers.psm1" Import-Module $CTKModule -force -DisableNameChecking Import-Module $ExcelModule -force -DisableNameChecking ###################################################################################### #Setting TLS to v1.2 [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 ###################################################################################### #Checking CORE token try { $Testing = Get-CoreDevice -Device 879665 } catch { Get-CoreToken } ###################################################################################### #Getting start time $Stopwatch = [system.diagnostics.stopwatch]::startNew() #******************************** #Excel border definitions ******* #******************************** $BorderLeft = 7 # $BorderTop = 8 # $BorderBottom = 9 # $BorderRight = 10 # $BorderInsideVertical = 11 # $BorderInsideHorizontal = 12 # #******************************** #Variable definition #Creating move groups $Destination_File = "C:\Users\ira.babb\Desktop\Counts.xlsx" $Dir=(Get-Item -Path . -Verbose).FullName $AllColumn = 1 $AllRow = 1 $PhysicalColumn = 1 $PhysicalRow = 1 $MRRRow = 1 $MRRColumn = 1 $CurrentMG = 0 $URI = "https://dbapi.nsi.rackspace.com/migration/dfw1/Find" $JSON = @" { "query": { "move_group":"$MG" } } "@ $UniqueAccounts=@() $VirtURI = "https://virtutility.pc.rackspace.com/api/inventory/" $CurrentDevice = 0 $CurrentAccount = 0 $InventoryCollected = @() $Outline = "Account,Device,OS,DC" $NotFoundfile = $Dir+"\Not Found - $MG.csv" Set-Content $NotFoundFile $Outline $Outline = "Account,Device,OS" $Foundfile = $Dir+"\Found - $MG.csv" Set-Content $FoundFile $Outline ###################################################################################### #Cleaning our old dropouts if ($Dropouts) { $DropoutsDir = $Dir+"\Dropouts\" $DropoutsCSV = $DropoutsDir+"*Counts.csv" #Testing the dropouts directory and creating it if it doesn't exist if (!(test-path $DropoutsDir)) { new-item $DropoutsDir -type directory | Out-Null } #Deleting the appropriate files in the dropouts directory remove-item $DropoutsCSV } $Results = Invoke-RestMethod -Uri $URI -Body "$JSON" -ContentType "application/json" -Method "POST" -Headers @{"X-Auth"=$Global:Token} -TimeoutSec 120 Foreach ($Device in $Results.Result) { $CurrentDevice++ $DevicePercentageComplete = ($CurrentDevice/$Results.result.count)*100 $DevicePercentageComplete = "{0:N0}" -f $DevicePercentageComplete Write-Progress -Activity "Processing devices for $MG" -Status "Device $CurrentDevice of $($Results.result.count), $DevicePercentageComplete% Complete" -PercentComplete $DevicePercentageComplete $NewAccount = $True #Determining the type of device if ($Device.deleted -ne "true") { #$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ #Counting unique accounts Foreach ($Account in $UniqueAccounts) { if ($Device.account.number -eq $Account.Number) { $NewAccount = $False if ($Device.device.type -eq "VM") { $Account.Devices+=$Device $Total++ } } } if ($NewAccount) { $AccountPSO = [PSCustomObject]@{ Name = $Device.account.name; Number = $Device.account.number; Devices = @() } if ($Device.device.type -eq "VM") { $AccountPSO.Devices+=$Device $Total++ } $UniqueAccounts+=$AccountPSO } } } #$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ foreach ($Account in $UniqueAccounts) { #Initializing the VM inventory array $InventoryCollected = @() #Writing progress $CurrentAccount++ $AccountPercentageComplete = ($CurrentAccount/$UniqueAccounts.count)*100 $AccountPercentageComplete = "{0:N0}" -f $AccountPercentageComplete Write-Progress -Activity "Processing accounts for $MG" -Status "Account $CurrentAccount of $($UniqueAccounts.count), $AccountPercentageComplete% Complete" -PercentComplete $AccountPercentageComplete -id 1 #Polling the VirtUtility API try { $VirtInventory = $Request = Invoke-RestMethod -Uri "$VirtURI/$($Account.Number)/DFW1" -Method "GET" -TimeoutSec 180 } catch { #If the VirtUtility API returns an error we'll set the inventory to $Null $VirtInventory = $Null } #If we got something from VirtUtility we'll process as required if ($VirtInventory -ne $Null) { #Collecting VMs #Iterating through clusters on the customer's account. VMs are child objects of hypervisors, which when clustered are child items of clusters ForEach ($Cluster in $VirtInventory.Clusters) { Foreach ($Hypervisor in $Cluster.hosts) { Foreach ($VM in $Hypervisor.vms) {$InventoryCollected+=Generate-VMPSO $VM} } } #Iterating through the standalone hypervisors, which are separate from clusters. Foreach ($Hypervisor in $Request.standAloneHyps) { Foreach ($VM in $Hypervisor.vms) {$InventoryCollected+=Generate-VMPSO $VM} } #Iterating through the data we pulled via NSI pull and comparing with the VirtUtility. foreach ($Device in $Account.Devices) { #Assuming we won't find the device $Found = $False #Iterating through our inventory foreach ($VM in $InventoryCollected) { #If the NSI device number = the VM device number, set found to $True if ([string]$Device._id -eq [string]$VM.Number) {$Found = $True} } #Depending on whether we've found the device in our list we'll set the output file and increment the appropriate count if (!($Found)) { $Outfile = $NotFoundFile $FoundCount++ } else { $Outfile = $FoundFile $NotFoundCount++ } $Outline = [string]$Device.account.number+","+[string]$Device._id+","+$Device.device.os Add-Content $OutFile $Outline } } else #Failsafe in case there VirtUtility craps out { #Checking if there are any VMs in the account foreach ($Device in $Account.Devices) { $Found = $False if ($Device.device.type -eq "VM") #-and $Device.device.type -notlike "*Microsoft*") { #Pull the data from Core and compare $CorePull = Get-CoreDevice -Device $Device._id write-host $CorePull.DatacenterSymbol if ($CorePull.DatacenterSymbol -like "*DFW1*") {$Found = $True} if (!($Found)) { $Outfile = $NotFoundFile $FoundCount++ } else { $Outfile = $FoundFile $NotFoundCount++ } $Outline = [string]$Device.account.number+","+[string]$Device._id+","+$Device.device.os+","+$CorePull.DatacenterSymbol Add-Content $OutFile $Outline #write-host "$($Device.account.number)`t$($Device._id)`t$($Device.device.os)" -foregroundcolor "yellow" } } } read-host } if ($FoundCount -eq 0) {Remove-Item $FoundFile} if ($NotFoundCount -eq 0) {Remove-Item $NotFoundFile} ###################################################################################### #Timing functions $Stopwatch.stop() write-host write-host "Complete." -foregroundcolor "green" write-host write-host "Execution time: "$Stopwatch.Elapsed.Minutes" minutes "$Stopwatch.Elapsed.Seconds" seconds." -foregroundcolor "green" write-host