Workloads/Get-OneDriveData.ps1

# Get-OneDriveData.ps1
# Collects OneDrive usage, storage, and large drive signals via the Graph Reports API.
# Part of the M365-QuickAssess module -- not exported.

function Get-OneDriveData
{
    param
    (
        $Assessment
    )

    Write-Log "Collecting OneDrive data (30 days)"

    try
    {
        $od = Get-GraphReportCsv `
            -Uri "https://graph.microsoft.com/v1.0/reports/getOneDriveUsageAccountDetail(period='D30')"

        if ( -not $od -or $od.Count -eq 0 )
        {
            Write-Log "OneDrive report returned no data" "WARN"

            $Assessment.OneDrive.OneDriveCount             = $null
            $Assessment.OneDrive.OneDriveTotalStorageGB    = $null
            $Assessment.OneDrive.LargeOneDriveCount        = $null
            $Assessment.OneDrive.ActiveOneDriveCount       = $null
            $Assessment.OneDrive.HasUnprovisionedOneDrives = $null
            return
        }

        # -------------------------------------------------------------------
        # Totals
        # -------------------------------------------------------------------
        $oneDriveCount = $od.Count

        $totalBytes = ( $od | ForEach-Object {
            if ( $_."Storage Used (Byte)" ) { [int64]$_."Storage Used (Byte)" } else { 0 }
        } | Measure-Object -Sum ).Sum

        if ( -not $totalBytes ) { $totalBytes = 0 }

        $totalStorageGB = [math]::Round( $totalBytes / 1GB, 0 )

        # -------------------------------------------------------------------
        # Activity
        # -------------------------------------------------------------------
        $activeCount = ( $od | Where-Object { $_."Last Activity Date" } ).Count

        # -------------------------------------------------------------------
        # Large Drives (> 100 GB)
        # -------------------------------------------------------------------
        $largeDrives = $od | Where-Object {
            $_."Storage Used (Byte)" -and
            ( [int64]$_."Storage Used (Byte)" / 1GB ) -gt 100
        }

        $largeCount = $largeDrives.Count

        foreach ( $drive in $largeDrives )
        {
            $sizeGB = [math]::Round( ( [int64]$drive."Storage Used (Byte)" / 1GB ), 2 )

            $Assessment.Findings += New-Finding `
                -Type           "LargeOneDrive" `
                -Summary        "Large OneDrive detected" `
                -Category       "OneDrive" `
                -Severity       "Medium" `
                -Details        @( "$( $drive.'Owner Principal Name' ) - $sizeGB GB" ) `
                -Impact         "Large OneDrive accounts increase migration time and risk of failure." `
                -Recommendation "Review storage usage and remove unnecessary files before migration."
        }

        # -------------------------------------------------------------------
        # Populate Schema
        # -------------------------------------------------------------------
        $Assessment.OneDrive.OneDriveCount             = $oneDriveCount
        $Assessment.OneDrive.OneDriveTotalStorageGB    = $totalStorageGB
        $Assessment.OneDrive.LargeOneDriveCount        = $largeCount
        $Assessment.OneDrive.ActiveOneDriveCount       = $activeCount
        $Assessment.OneDrive.HasUnprovisionedOneDrives = ( $activeCount -lt $oneDriveCount )

        $Assessment.Summary.OneDriveCount           = $oneDriveCount
        $Assessment.Summary.OneDriveTotalStorageGB  = $totalStorageGB

        Write-Log "OneDrive: Count=$oneDriveCount StorageGB=$totalStorageGB Active=$activeCount Large=$largeCount Unprovisioned=$( $oneDriveCount - $activeCount )"

        # -------------------------------------------------------------------
        # Finding: High total OneDrive storage
        # -------------------------------------------------------------------
        if ( $totalStorageGB -gt 1000 )
        {
            $severity = if ( $totalStorageGB -gt 5000 ) { "High" } else { "Medium" }

            $Assessment.Findings += New-Finding `
                -Type           "HighOneDriveStorage" `
                -Summary        "Total OneDrive storage is $totalStorageGB GB across $oneDriveCount drives" `
                -Category       "OneDrive" `
                -Severity       $severity `
                -Impact         "High total storage volumes will significantly increase migration time and cost." `
                -Recommendation "Review OneDrive usage across the tenant and identify candidates for cleanup before migration."
        }

        # -------------------------------------------------------------------
        # Finding: Unprovisioned OneDrives
        # -------------------------------------------------------------------
        $unprovisionedCount = $oneDriveCount - $activeCount

        if ( $unprovisionedCount -gt 0 )
        {
            $unprovisionedPercent = [math]::Round( ( $unprovisionedCount / $oneDriveCount ) * 100, 0 )

            if ( $unprovisionedPercent -ge 20 )
            {
                $Assessment.Findings += New-Finding `
                    -Type           "UnprovisionedOneDrives" `
                    -Summary        "$unprovisionedCount OneDrive accounts appear inactive or unprovisioned ($unprovisionedPercent%)" `
                    -Category       "OneDrive" `
                    -Severity       "Info" `
                    -Impact         "Inactive OneDrive accounts may indicate users who have never logged in or stale accounts." `
                    -Recommendation "Review inactive OneDrive accounts before migration to avoid migrating empty or stale data."
            }
        }
    }
    catch
    {
        Write-Log "OneDrive data collection failed: $( $_.Exception.Message )" "ERROR"
    }
}