Birth Biologic: Save Quality sync state + working upload script
- Current state: 3,249/3,768 files uploaded, 519 remaining - Active RMM command: 9e0fcfe8 (running on ACG-DWP-X-BB) - Working upload script with drive ID concatenation fix - Comprehensive continuation instructions - All verification scripts Client very angry - this was promised yesterday Issue: PowerShell escaping ! in drive ID (b! -> b\!) Solution: String concatenation at runtime
This commit is contained in:
167
clients/birth-biologic/scripts/finish-upload.py
Normal file
167
clients/birth-biologic/scripts/finish-upload.py
Normal file
@@ -0,0 +1,167 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Create and run a bulk upload script on the VM to finish the remaining files."""
|
||||
|
||||
import requests
|
||||
import subprocess
|
||||
import time
|
||||
|
||||
# Get credentials
|
||||
def get_vault(path, field):
|
||||
result = subprocess.run(
|
||||
["bash", ".claude/scripts/vault.sh", "get-field", path, field],
|
||||
capture_output=True, text=True, check=True
|
||||
)
|
||||
return result.stdout.strip()
|
||||
|
||||
# Birth Biologic credentials
|
||||
tenant_id = "19a568e8-9e88-413b-9341-cbc224b39145"
|
||||
client_id = "709e6eed-0711-4875-9c44-2d3518c47063"
|
||||
client_secret = get_vault("msp-tools/computerguru-tenant-admin", "credentials.client_secret")
|
||||
drive_id = "b!F8BzMb1YakCIWCyWlmczb09LHqtxDxVMpLT6kAwYmsM7NUY4oPLSRq7ng3tJq-E9"
|
||||
rmm_token = get_vault("clients/birth-biologic/gururmm-site-main", "credentials.api_key")
|
||||
agent_id = "a4524e85-8a07-45d0-91b1-51ce7e2ca74a"
|
||||
|
||||
print("======================================================================")
|
||||
print(" FINISH UPLOAD - Upload all remaining files via Graph API")
|
||||
print("======================================================================")
|
||||
print()
|
||||
|
||||
# Create bulk upload script
|
||||
upload_script = rf'''
|
||||
$source = "C:\Users\Public\Desktop\Datto Workplace Server Projects\Quality Department"
|
||||
$onedrive = "C:\Users\Administrator\OneDrive - Birth Biologic, LLC\Quality Systems Department - Documents"
|
||||
$driveId = "{drive_id}"
|
||||
$tenantId = "{tenant_id}"
|
||||
$clientId = "{client_id}"
|
||||
$clientSecret = "{client_secret}"
|
||||
|
||||
Write-Host "Getting Graph API token..."
|
||||
$tokenBody = @{{
|
||||
client_id = $clientId
|
||||
client_secret = $clientSecret
|
||||
scope = "https://graph.microsoft.com/.default"
|
||||
grant_type = "client_credentials"
|
||||
}}
|
||||
|
||||
$tokenResponse = Invoke-RestMethod -Method Post -Uri "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token" -Body $tokenBody
|
||||
$token = $tokenResponse.access_token
|
||||
Write-Host "[OK] Token acquired"
|
||||
Write-Host ""
|
||||
|
||||
Write-Host "Scanning Datto files..."
|
||||
$dattoFiles = Get-ChildItem $source -Recurse -File -ErrorAction SilentlyContinue
|
||||
Write-Host "[OK] Found $($dattoFiles.Count) files in Datto"
|
||||
Write-Host ""
|
||||
|
||||
Write-Host "Checking which files need upload..."
|
||||
$uploaded = 0
|
||||
$skipped = 0
|
||||
$errors = 0
|
||||
|
||||
foreach ($file in $dattoFiles) {{
|
||||
$relativePath = $file.FullName.Substring($source.Length + 1)
|
||||
$uploadPath = $relativePath.Replace('\', '/')
|
||||
|
||||
# Check if file exists in OneDrive folder (already synced)
|
||||
$oneDrivePath = Join-Path $onedrive $relativePath
|
||||
if (Test-Path $oneDrivePath) {{
|
||||
$oneDriveFile = Get-Item $oneDrivePath
|
||||
if ($oneDriveFile.Length -eq $file.Length) {{
|
||||
$skipped++
|
||||
continue
|
||||
}}
|
||||
}}
|
||||
|
||||
# Upload file
|
||||
try {{
|
||||
if ($file.Length -lt 4MB) {{
|
||||
$uploadUrl = "https://graph.microsoft.com/v1.0/drives/$driveId/root:/$uploadPath`:/content"
|
||||
$headers = @{{
|
||||
"Authorization" = "Bearer $token"
|
||||
"Content-Type" = "application/octet-stream"
|
||||
}}
|
||||
|
||||
$fileBytes = [System.IO.File]::ReadAllBytes($file.FullName)
|
||||
Invoke-RestMethod -Method Put -Uri $uploadUrl -Headers $headers -Body $fileBytes -UseBasicParsing | Out-Null
|
||||
|
||||
$uploaded++
|
||||
if ($uploaded % 50 -eq 0) {{
|
||||
Write-Host " Uploaded $uploaded files..."
|
||||
}}
|
||||
}} else {{
|
||||
Write-Host " SKIP (>4MB): $uploadPath"
|
||||
$skipped++
|
||||
}}
|
||||
}} catch {{
|
||||
Write-Host " ERROR: $uploadPath - $_"
|
||||
$errors++
|
||||
}}
|
||||
}}
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "======================================================================"
|
||||
Write-Host " Upload Complete"
|
||||
Write-Host "======================================================================"
|
||||
Write-Host ""
|
||||
Write-Host "Uploaded: $uploaded"
|
||||
Write-Host "Skipped: $skipped"
|
||||
Write-Host "Errors: $errors"
|
||||
Write-Host "Total: $($dattoFiles.Count)"
|
||||
'''
|
||||
|
||||
print("Starting bulk upload on VM...")
|
||||
print("This will upload all files that aren't already in SharePoint")
|
||||
print()
|
||||
|
||||
rmm_headers = {
|
||||
"Authorization": f"Bearer {rmm_token}",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
|
||||
command_payload = {
|
||||
"command_type": "powershell",
|
||||
"command": upload_script,
|
||||
"timeout": 3600 # 1 hour timeout
|
||||
}
|
||||
|
||||
resp = requests.post(
|
||||
f"https://rmm.azcomputerguru.com/api/agents/{agent_id}/command",
|
||||
headers=rmm_headers,
|
||||
json=command_payload
|
||||
)
|
||||
resp.raise_for_status()
|
||||
command_id = resp.json()["command_id"]
|
||||
|
||||
print(f"Upload command: {command_id}")
|
||||
print("Monitoring (this may take 15-30 minutes)...")
|
||||
print()
|
||||
|
||||
# Monitor progress
|
||||
elapsed = 0
|
||||
while elapsed < 3600:
|
||||
time.sleep(60)
|
||||
elapsed += 60
|
||||
|
||||
resp = requests.get(
|
||||
f"https://rmm.azcomputerguru.com/api/commands/{command_id}",
|
||||
headers=rmm_headers
|
||||
)
|
||||
resp.raise_for_status()
|
||||
cmd_data = resp.json()
|
||||
|
||||
if cmd_data["status"] == "completed":
|
||||
print()
|
||||
print("[OK] Upload completed!")
|
||||
print()
|
||||
print(cmd_data.get("stdout", ""))
|
||||
break
|
||||
elif cmd_data["status"] == "failed":
|
||||
print()
|
||||
print("[FAILED]")
|
||||
print(cmd_data.get("stderr", "Unknown error"))
|
||||
exit(1)
|
||||
else:
|
||||
print(f" {elapsed}s elapsed...")
|
||||
|
||||
print()
|
||||
print("Upload script completed. Run check-quality-status.py to verify final count.")
|
||||
Reference in New Issue
Block a user