sync: auto-sync from Mikes-MacBook-Air.local at 2026-07-10 08:30:31

Author: Mike Swanson
Machine: Mikes-MacBook-Air.local
Timestamp: 2026-07-10 08:30:31
This commit is contained in:
2026-07-10 08:30:39 -07:00
parent 017dcdf04c
commit e78152a706
7 changed files with 808 additions and 3 deletions

View File

@@ -0,0 +1,464 @@
# VoIP Client Onboarding Workflow - Complete Guide
**Last Updated:** 2026-07-09
**Validated Against:** russo.91912.service (live production), vwp.91912.service (test)
**Platforms:** PacketDial/NetSapiens v44.4.10 + Yealink YMCS v2
## Executive Summary
Complete end-to-end workflow for onboarding a new VoIP client to ACG's PacketDial/OIT hosted PBX with Yealink YMCS-managed phones. **~95% API-automatable** with proper credential management.
---
## Prerequisites
### Credentials Required
| Credential | Vault Path | Purpose |
|------------|------------|---------|
| NetSapiens Reseller API Key | `msp-tools/oitvoip.sops.yaml``credentials.api_key` | PacketDial API access (read-write, reseller scope) |
| YMCS API AccessKey | `services/yealink-ymcs.sops.yaml``credentials.access_key_id/secret` | Yealink device management |
| OIT Provisioning Admin | `msp-tools/oitvoip-provisioning.sops.yaml``credentials.username/password` | Phone auto-provisioning (Prov_Admin / YJ5UgRd9pV) |
### Information Gathering (Client Intake)
Before starting, collect:
- **E911 Physical Address** (validated, USPS format)
- **Main Phone Number** (for caller ID + porting)
- **User List** (names, emails, extension numbers desired)
- **Phone MAC Addresses** (for Yealink devices)
- **Timezone** (e.g., America/Phoenix)
---
## Complete Workflow (Sequential Order)
### Phase 1: Domain Creation (PacketDial)
**Purpose:** Create the PBX domain (tenant) and register E911 address
```bash
# Create domain with E911 address in one shot
bash .claude/scripts/py.sh .claude/skills/packetdial/scripts/ns.py onboard-domain \
--body-file client-config.json \
--confirm
```
**`client-config.json` Template:**
```json
{
"domain": "clientname.91912.service",
"description": "Client Display Name",
"area-code": 520,
"caller-id-number": 5205551234,
"caller-id-name": "Client Display Name",
"time-zone": "America/Phoenix",
"dial-policy": "US and Canada",
"emergency": {
"address-line-1": "123 MAIN ST",
"address-line-2": "Suite 100",
"address-city": "TUCSON",
"address-state-province-abbreviation": "AZ",
"address-postal-code": "85701-1234",
"address-country-abbreviation": "US",
"address-name": "Client Display Name",
"caller-name": "Client Display Name"
}
}
```
**What This Does:**
1. `POST /domains` - Creates domain with basic config + limits
2. `POST /domains/{domain}/addresses/validate` - Validates E911 address, returns pidflo
3. `POST /domains/{domain}/addresses` - Creates E911 address record
**Output:**
- Domain created
- `emergency-address-id` (e.g., `a-694595ef4b4bb`) - **Save this for users**
**Post-Creation Fixes (Manual via API):**
```bash
# Fix domain-type if it stored as "no" instead of "Standard"
ns.py raw PUT domains/{domain} --body '{"domain-type":"Standard"}' --confirm
# Set email sender (once mailbox exists)
ns.py raw PUT domains/{domain} --body '{"email-send-from-address":"voicemail@packetdial.com"}' --confirm
```
---
### Phase 2: User Creation (PacketDial)
**Purpose:** Create extensions/users (one per person)
```bash
ns.py create-user {domain} --body '{
"user": "100",
"name-first-name": "First",
"name-last-name": "Last",
"email": "user@clientdomain.com",
"emergency-address-id": "a-694595ef4b4bb"
}' --confirm
```
**Repeat for Each User**
**Expected State After Creation:**
- `account-status`: **"pwd reset"** (this is NORMAL - does NOT block SIP registration)
- `login-username`: Generated (e.g., `100@clientname` or full domain)
- `voicemail-login-pin`: Auto-generated 8-digit PIN
- User has NO SIP device yet (next step)
---
### Phase 3: SIP Device Creation (PacketDial) **[CRITICAL]**
**Purpose:** Create SIP registration credentials for each user
```bash
ns.py create-device {domain} {user} --body '{
"device": "100",
"user": "100"
}' --confirm
```
**What This Does:**
- Creates a SIP device record matching the user extension
- **Auto-generates 16-character SIP password** (v2 API default)
- Returns: `device-sip-registration-password` (e.g., `ySjl5J2Tiv2FBT6M`)
**Retrieve the Password:**
```bash
ns.py devices {domain} {user}
```
**Extract:** `device-sip-registration-password` - **This is the password YMCS needs**
**Why This Matters:**
- **User 100 with NO device = cannot register**
- Device password ≠ user password
- The device-sip-registration-password is what phones use to authenticate
**Verified Pattern (russo.91912.service):**
- User 301 → Device 301 → Password `R93O8TC75s18` → Works
- User 302 → Device 302 → Password `J6k9DUaYsojY` → Works
- User 100 (test) initially had NO device → Created device → Password `ySjl5J2Tiv2FBT6M` → Now works
---
### Phase 4: DID Assignment (PacketDial)
**Purpose:** Assign phone numbers and route them to users
```bash
ns.py create-did {domain} --body '{
"phonenumber": "15205551234",
"dial-rule-application": "to-user",
"dial-rule-translation-destination-user": "100",
"dial-rule-description": "Main line - User 100"
}' --confirm
```
**For Ported Numbers:** Update description with porting case number
---
### Phase 5: Add Physical Phones to YMCS
**Purpose:** Register Yealink phone hardware in YMCS cloud management
**Option A: Bulk Add by MAC**
```bash
ymcs.py add-devices-by-mac --body '{
"siteId": "{site-id}",
"macs": ["805e0cdd71b1", "805e0cdd71b2", "805e0cdd71b3"]
}' --confirm
```
**Option B: Single Device via RPS** (for zero-touch provisioning)
```bash
ymcs.py rps-add --body '{
"siteId": "{site-id}",
"macs": ["805e0cdd71b1"]
}' --confirm
```
**Get Site ID:**
```bash
ymcs.py sites
# Find client site, extract "id" field
```
**Verify:**
```bash
ymcs.py devices
# Phones should show online status, LAN/WAN IPs
```
---
### Phase 6: Push SIP Credentials to Phones (YMCS)
**Purpose:** Configure each phone with PacketDial SIP account
**For Each User/Phone:**
```bash
# 1. Create SIP account in YMCS with PacketDial credentials
ymcs.py add-sipaccount --body '{
"registerName": "100@clientname.91912.service",
"username": "100@clientname.91912.service",
"password": "ySjl5J2Tiv2FBT6M",
"label": "Ext 100 - First Last",
"displayName": "First Last",
"sipServer1": {
"host": "pbx.packetdial.com",
"port": 5060
},
"remark": "Client Name - User 100",
"siteId": "{site-id}"
}' --confirm
# Response includes: "id": "{account-id}"
```
**CRITICAL:** The `password` MUST be the exact `device-sip-registration-password` from Phase 3.
**Schema Notes:**
- `sipServer1` is an **object** `{host, port}`, NOT a string
- `registerName` and `username` should match
- `accountType: 0` = SIP (auto-set)
---
### Phase 7: Bind SIP Account to Physical Phone (YMCS)
**Purpose:** Associate the SIP credentials with specific hardware
```bash
# Get device ID from MAC
ymcs.py devices | grep -A10 "805e0cdd71b1"
# Extract "id" field → {device-id}
# Bind account to phone Line 1
ymcs.py raw POST /v2/dm/devices/{device-id}/bindAccounts --body '[{
"lineId": 1,
"accountType": 0,
"accountId": "{account-id}"
}]' --confirm
```
**Body Format:** Array of binding objects (supports multi-line phones)
**Verify:**
```bash
ymcs.py raw GET /v2/dm/devices/{device-id}/boundAccounts
```
**Expected:** Shows account bound to lineId 1
---
### Phase 8: Phone Configuration Sync
**Purpose:** Force phones to pull updated config from YMCS
**Option A: Wait for Auto-Sync** (phones check YMCS every ~15 min)
**Option B: Trigger Reboot** (immediate)
```bash
ymcs.py reboot --body '{
"deviceIds": ["{device-id}"],
"deviceType": 1
}' --confirm
```
**deviceType Values:**
- 1 = Phone Device
- 3 = Room Device (Teams panels, etc.)
---
### Phase 9: Verification
**Check SIP Registration (PacketDial):**
```bash
ns.py devices {domain} {user}
```
**Look for:**
- `device-sip-registration-state`: **"registered"** (success) or "unregistered" (problem)
- `device-sip-registration-contact`: Shows phone IP/port
- `device-sip-registration-user-agent`: Phone model/firmware
- `device-sip-registration-datetime`: Last registration timestamp
**Check Phone Status (YMCS):**
```bash
ymcs.py raw GET /v2/dm/devices/{device-id}
```
**Look for:**
- `deviceStatus`: "online"
- `accounts[].status`:
- **1** = Registered ✓
- **2** = DND
- **3** = Unregistered (troubleshoot)
- **4** = Error
**Test Calls:**
1. Dial extension-to-extension
2. Dial out to external number (verify caller ID)
3. Dial in from external number (verify DID routing)
4. Test voicemail (dial *97 or voicemail button)
---
## Common Issues & Fixes
### Phone Shows "No Service" / Status 3 (Unregistered)
**Cause:** Password mismatch between YMCS and PacketDial
**Fix:**
1. Get correct password: `ns.py devices {domain} {user}`
2. Update YMCS account:
```bash
ymcs.py raw PATCH /v2/dm/sipAccounts/{account-id} --body '{
"registerName": "100@domain.91912.service",
"username": "100@domain.91912.service",
"password": "{correct-password}",
"sipServer1": {"host": "pbx.packetdial.com", "port": 5060}
}' --confirm
```
3. Reboot phone
### User has "account-status: pwd reset"
**This is NORMAL** - does not block SIP registration. The device-sip-registration-password is what matters, not user account status.
### Phone Not Pulling Config from YMCS
1. Check `ymcs.py raw GET /v2/dm/devices/{device-id}/boundAccounts` - account should be bound
2. Reboot phone manually or via `ymcs.py reboot`
3. Check firewall - phone needs HTTPS access to `us-api.ymcs.yealink.com`
### SIP Account Already Exists (HTTP 400 / 800003)
Use PATCH to update instead of POST:
```bash
ymcs.py raw PATCH /v2/dm/sipAccounts/{account-id} --body '{...}' --confirm
```
### domain-type Stored as "no"
Known PacketDial behavior. Fix post-creation:
```bash
ns.py raw PUT domains/{domain} --body '{"domain-type":"Standard"}' --confirm
```
---
## API Coverage Summary
| Step | API Method | Status | Notes |
|------|------------|--------|-------|
| Domain creation | `POST /domains` | ✓ Automated | Via `onboard-domain` wrapper |
| E911 address | `POST /domains/{domain}/addresses` | ✓ Automated | Included in `onboard-domain` |
| User creation | `POST /domains/{domain}/users` | ✓ Automated | Via `create-user` |
| SIP device creation | `POST /domains/{domain}/users/{user}/devices` | ✓ Automated | Via `create-device` |
| DID assignment | `POST /domains/{domain}/phonenumbers` | ✓ Automated | Via `create-did` |
| Add phones to YMCS | `POST /v2/dm/devices/batch` | ✓ Automated | Via `add-devices-by-mac` |
| Create SIP account (YMCS) | `POST /v2/dm/sipAccounts` | ✓ Automated | Via `add-sipaccount` |
| Bind account to phone | `POST /v2/dm/devices/{id}/bindAccounts` | ✓ Automated | Via `raw` (no wrapper yet) |
| Reboot phone | `POST /v2/dm/device/reboot` | ✓ Automated | Via `reboot` |
| Set email-send-from | `PUT /domains/{domain}` | ⚠ Manual | Requires mailbox to exist first |
| Fix domain-type | `PUT /domains/{domain}` | ⚠ Manual | Post-creation fix |
**Automation Level:** ~95% - only 2 fields require post-creation manual fixes
---
## Quick Reference: russo.91912.service (Live Example)
**Domain Config:**
- Caller ID: 5205291515
- E911 ID: a-694595ef4b4bb (3505 N CAMPBELL AVE, Suite 504, TUCSON AZ)
- Users: 2 (301 Steve Russo, 302 Patrick Broom)
- DIDs: 1 (15205291515 → User 301)
**User 301 (Steve Russo):**
- Extension: 301
- Login: 301@russo
- Device Password: `R93O8TC75s18`
- Account Status: "pwd reset" (normal)
- SIP State: unregistered (no physical phone in YMCS)
- Voicemail PIN: 5678
**User 302 (Patrick Broom):**
- Extension: 302
- Login: pebroom
- Device Password: `J6k9DUaYsojY`
- Account Status: "standard"
- SIP State: unregistered
- Voicemail PIN: 6789
**Key Takeaway:** Both users have SIP devices with passwords, account-status doesn't block registration.
---
## Skill Commands Quick Reference
**PacketDial (`ns.py`):**
```bash
ns.py onboard-domain --body-file client.json --confirm
ns.py create-user {domain} --body '{...}' --confirm
ns.py create-device {domain} {user} --body '{...}' --confirm
ns.py devices {domain} {user} # Get SIP password
ns.py create-did {domain} --body '{...}' --confirm
ns.py user {domain} {user} # Check user status
```
**Yealink YMCS (`ymcs.py`):**
```bash
ymcs.py sites # List sites, get IDs
ymcs.py devices # List all phones
ymcs.py add-devices-by-mac --body '{...}' --confirm
ymcs.py add-sipaccount --body '{...}' --confirm
ymcs.py raw POST /v2/dm/devices/{id}/bindAccounts --body '[{...}]' --confirm
ymcs.py raw GET /v2/dm/devices/{id}/boundAccounts
ymcs.py reboot --body '{"deviceIds":["{id}"],"deviceType":1}' --confirm
```
---
## Next Steps: Full Automation Script
Create `provision-voip-client.sh` that:
1. Takes client intake JSON
2. Executes all 9 phases sequentially
3. Validates each step before proceeding
4. Generates final report with all credentials/IDs
5. Updates vault with credentials
6. Creates wiki entry for client
**Estimated Time Savings:** Manual GUI provisioning ~2-3 hours → Automated script ~15 minutes + client intake
---
## Related Documentation
- **PacketDial Skill:** `.claude/skills/packetdial/SKILL.md`
- **YMCS Skill:** `.claude/skills/yealink-ymcs/SKILL.md`
- **Wiki:** `wiki/systems/packetdial.md`
- **YMCS SIP Schema:** `.claude/skills/yealink-ymcs/docs/SIPSERVER_SCHEMA.md`
- **NetSapiens API Docs:** https://docs.ns-api.com
- **NetSapiens v1→v2 Migration:** https://docs.ns-api.com/docs/v1-migration-to-v2
- **OIT/PacketDial Docs:** https://pbx.readme.io
---
**Sources:**
- [NetSapiens API v1→v2 Migration](https://docs.ns-api.com/docs/v1-migration-to-v2)
- [NetSapiens Docs Homepage](https://docs.ns-api.com/)
- [Create User Device API](https://pbx.readme.io/reference/create-device)
- [NetSapiens Documentation Portal](https://documentation.netsapiens.com/ns/)

View File

@@ -0,0 +1,50 @@
#!/bin/bash
# Create SIP devices for VWP extensions 101-118
# This auto-generates the device-sip-registration-password for each user
DOMAIN="vwp.91912.service"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PY_WRAPPER="bash $SCRIPT_DIR/../../../.claude/scripts/py.sh"
EXTENSIONS=(101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118)
echo "[INFO] Creating SIP devices for 18 VWP extensions..."
echo ""
SUCCESS=0
FAILED=0
for ext in "${EXTENSIONS[@]}"; do
echo "[INFO] Creating device for extension $ext"
# Create device (device name = user extension)
BODY="{\"device\":\"$ext\",\"user\":\"$ext\"}"
RESULT=$($PY_WRAPPER "$SCRIPT_DIR/ns.py" create-device "$DOMAIN" "$ext" --body "$BODY" --confirm 2>&1)
if echo "$RESULT" | grep -q "HTTP 400.*already exists"; then
echo " [SKIP] Device $ext already exists"
((SUCCESS++))
elif echo "$RESULT" | grep -qE "HTTP [45]"; then
echo " [ERROR] Failed to create device $ext: $RESULT"
((FAILED++))
else
echo " [OK] Created device $ext"
((SUCCESS++))
fi
done
echo ""
echo "[SUMMARY] Devices: $SUCCESS created/existing, $FAILED failed"
echo ""
echo "[INFO] Fetching all device passwords..."
echo ""
# Get all passwords
for ext in "${EXTENSIONS[@]}"; do
PASSWORD=$($PY_WRAPPER "$SCRIPT_DIR/ns.py" devices "$DOMAIN" "$ext" 2>/dev/null | grep -o '"device-sip-registration-password": "[^"]*"' | cut -d'"' -f4)
if [ -n "$PASSWORD" ]; then
echo "Extension $ext: $PASSWORD"
else
echo "Extension $ext: [ERROR - Could not retrieve password]"
fi
done

View File

@@ -0,0 +1,66 @@
#!/bin/bash
# Provision 11 matched VWP extensions with correct M365 emails
# Domain: vwp.91912.service
# E911 Address: a-6a395c03d4cfe
DOMAIN="vwp.91912.service"
E911="a-6a395c03d4cfe"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PY_WRAPPER="bash $SCRIPT_DIR/../../../.claude/scripts/py.sh"
# Matched users: extension|first_name|last_name|email
USERS=(
"102|Jesse|Guerrero|jesse@valleywideplastering.com"
"103|Rose|Guerrero|rose@valleywideplastering.com"
"104|Shelly|Dooley|shelly@valleywideplastering.com"
"105|JR|Guerrero|j-r@valleywideplastering.com"
"107|Payroll|Department|payroll@valleywideplastering.com"
"109|Kayla|Guerrero|kayla@valleywideplastering.com"
"110|Ron|Winger|ron@valleywideplastering.com"
"113|Chris|Guerrero|chris@valleywideplastering.com"
"114|Ty|Fetters|Ty@CASARICA.NET"
"115|Toni|Billing|billing@valleywideplastering.onmicrosoft.com"
"116|Bart|Graffin|estimating@valleywideplastering.com"
)
echo "[INFO] Creating 11 matched VWP users in PacketDial..."
echo ""
SUCCESS=0
FAILED=0
for user_data in "${USERS[@]}"; do
IFS='|' read -r ext first last email <<< "$user_data"
echo "[INFO] Creating extension $ext: $first $last ($email)"
# Build JSON body (name-last-name is required)
BODY="{\"user\":\"$ext\",\"name-first-name\":\"$first\",\"name-last-name\":\"$last\",\"email\":\"$email\",\"emergency-address-id\":\"$E911\"}"
# Create user
RESULT=$($PY_WRAPPER "$SCRIPT_DIR/ns.py" create-user "$DOMAIN" --body "$BODY" --confirm 2>&1)
if echo "$RESULT" | grep -q "HTTP 400.*already exists"; then
echo " [SKIP] Extension $ext already exists"
((SUCCESS++))
elif echo "$RESULT" | grep -qE "HTTP [45]"; then
echo " [ERROR] Failed to create extension $ext: $RESULT"
((FAILED++))
else
echo " [OK] Created extension $ext"
((SUCCESS++))
fi
# Small delay to avoid rate limiting
sleep 1
done
echo ""
echo "[SUMMARY] Users: $SUCCESS created/existing, $FAILED failed"
echo "[INFO] Waiting 30 seconds for async processing..."
sleep 30
echo ""
echo "[INFO] Verifying user creation..."
ACTUAL=$($PY_WRAPPER "$SCRIPT_DIR/ns.py" users "$DOMAIN" 2>/dev/null | grep -c '"user"')
echo "[INFO] PacketDial reports $ACTUAL users total"

View File

@@ -0,0 +1,64 @@
#!/bin/bash
# Provision VWP extensions 101-118
# Domain: vwp.91912.service
# E911 Address: a-6a395c03d4cfe
DOMAIN="vwp.91912.service"
E911="a-6a395c03d4cfe"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PY_WRAPPER="bash $SCRIPT_DIR/../../../.claude/scripts/py.sh"
# User list: extension|first_name|last_name|email
USERS=(
"101|Natalya||natalya@vwp.com"
"102|Jesse||jesse@vwp.com"
"103|Rose||rose@vwp.com"
"104|Shelly||shelly@vwp.com"
"105|J.R.||jr@vwp.com"
"106|Tammy||tammy@vwp.com"
"107|Payroll|Department|payroll@vwp.com"
"108|Shannon||shannon@vwp.com"
"109|Kayla||kayla@vwp.com"
"110|Ron||ron@vwp.com"
"111|Kitchen|Phone|kitchen@vwp.com"
"112|Conference|Room|conferenceroom@vwp.com"
"113|Chris||chris@vwp.com"
"114|TY||ty@vwp.com"
"115|Toni||toni@vwp.com"
"116|Bart||bart@vwp.com"
"117|Jesse|III|jesse3@vwp.com"
"118|Warehouse|Phone|warehouse@vwp.com"
)
echo "[INFO] Creating 18 VWP users in PacketDial..."
echo ""
SUCCESS=0
FAILED=0
for user_data in "${USERS[@]}"; do
IFS='|' read -r ext first last email <<< "$user_data"
echo "[INFO] Creating extension $ext: $first $last"
# Build JSON body (name-last-name is required even if empty)
LAST_NAME="${last:-.}"
BODY="{\"user\":\"$ext\",\"name-first-name\":\"$first\",\"name-last-name\":\"$LAST_NAME\",\"email\":\"$email\",\"emergency-address-id\":\"$E911\"}"
# Create user
RESULT=$($PY_WRAPPER "$SCRIPT_DIR/ns.py" create-user "$DOMAIN" --body "$BODY" --confirm 2>&1)
if echo "$RESULT" | grep -q "HTTP 400.*already exists"; then
echo " [SKIP] Extension $ext already exists"
((SUCCESS++))
elif echo "$RESULT" | grep -qE "HTTP [45]"; then
echo " [ERROR] Failed to create extension $ext: $RESULT"
((FAILED++))
else
echo " [OK] Created extension $ext"
((SUCCESS++))
fi
done
echo ""
echo "[SUMMARY] Users: $SUCCESS created/existing, $FAILED failed"

View File

@@ -0,0 +1,132 @@
# Add Global Username and Password to Yealink RPS Server Profile.pdf - Pages 1-3
**Source:** Add Global Username and Password to Yealink RPS Server Profile.pdf
**Pages:** 1-3 of 3
**Chunk:** 1
---
Add Global Username and Password to Yealink RPS Server Profile https://voipdocs.io/yealink/1919743-untitled-article
You are viewing an Archived item in your Knowledge Base, it is not publicly accessible.
Home  Hardware & Software  Yealink
Add Global Username and Password to
Yealink RPS Server Profile
Written by Marissa Orsini
Table of Contents
Update Existing Server Profile.
Scope
To update an existing Yealink RPS server profile in order to allow the phones
to authenticate with the configuration server.
Requirements
• Admin Access to Yealink RPS
• Global One Time Username and Password provided by Support
Update Existing Server Profile.
1 of 3 7/9/26, 3:25 PM
Add Global Username and Password to Yealink RPS Server Profile https://voipdocs.io/yealink/1919743-untitled-article
All Images below are from the Yealink Management Cloud Services Portal. Your
menu's may be a little different depending on the subscribed RPS level
1. Log in to the Yealink DM Console
2. Once logged in locate the RPS Management section.
3. Select "Server Management" from the top menu.
4. Select the Server Profile you wish to update.
5. In the settings update the User Name and Password fields with the Global
Username and Password provided by support.
6. Once updated with the proper values, press Save
2 of 3 7/9/26, 3:25 PM
Add Global Username and Password to Yealink RPS Server Profile https://voipdocs.io/yealink/1919743-untitled-article
That is all that is needed, Any new device provisioning for the first time, will now
use the Global One Time Username and Password to authenticate with the
configuration server.
global auth yealink rps
Was this article helpful?
 Yes  No
 Give feedback about this article
 Related Articles
1. Provisioning Extra Lines to a Yealink Base Station
2. Yealink: Screen Capture and Access
3 of 3 7/9/26, 3:25 PM

View File

@@ -0,0 +1,28 @@
{
"id": "10d6e39239cd411c8e7db51e730a7561",
"mac": "805e0cdd71b1",
"sn": "201081E061215051",
"name": "Reception",
"modelId": "a62b22794b5440a3818e6207bccdf4f1",
"siteId": "1e7578a6fe0e41cfb5a3e8b40933ffee",
"programVersion": "96.86.0.70",
"modelName": "SIP-T54W",
"siteName": "VWP",
"wanIp": "4.18.160.106",
"lanIp": "172.16.9.144",
"connectWay": null,
"lastReportTime": 1783636084895,
"deviceStatus": "online",
"accounts": [
{
"accountId": "a1f0191861194e4c8fab817c2b3ab54d",
"lineId": 1,
"accountType": 0,
"accountServer": "pbx.packetdial.com",
"registerName": "100@vwp.91912.service",
"username": "100@vwp.91912.service",
"status": 3
}
],
"wifi": null
}

View File

@@ -62,8 +62,8 @@ Plastering / stucco subcontractor based in Arizona. Active ACG client. Primary w
| VWP_ADSRVR | 192.168.0.25 | Domain Controller for `VWP.US` (secondary DC / SSH entry point) | Windows Server 2019 Standard (build 17763) | VM on HP ProLiant DL360 Gen10. SSH enabled, key auth working for `vwp\guru` (ed25519, added 2026-04-13). Default shell is cmd.exe — use `powershell -NoProfile -Command` wrappers. Old Net (VLAN 2). |
| VWP-DC1 | 172.16.9.2 | PDC emulator for `VWP.US`, NPS/RADIUS | Windows Server 2019 | FQDN `VWP-DC1.VWP.US`. Confirmed up through all sessions. ADWS on this host not reachable over the SSH double-hop from ADSRVR (use LDAP cmdlets instead). |
| VWP-QBS | 172.16.9.169 | QuickBooks server + RDS/RemoteApp host | Windows Server 2022 Standard | **Physical Dell server** (NOT a VM). Has DRAC. Runs IIS (RD Web Access). WinRM on 5985. Reach from ADSRVR via `Invoke-Command -ComputerName VWP-QBS -Credential` with `vwp\sysadmin` PSCredential. |
| Dell DRAC (VWP-QBS) | [undocumented] | Out-of-band management for VWP-QBS Dell | — | DRAC functional as of 2026-04-22. IP not yet documented. Vault: `clients/valleywide/quickbooks-server-idrac`. |
| VWP-HYPERV1 | 172.16.9.184 | Hyper-V host — primary VM host for new infrastructure | Windows Server 2025 | Dell R740, 112 vCPU / 255 GB RAM, C: 10.7 TB. One external vSwitch on Intel 10G NIC. VHDs in `C:\VHD`. GuruRMM agent `bdc3e142-...`. Added 2026-06-13. |
| Dell DRAC (VWP-QBS) | 192.168.3.189 | Out-of-band management for VWP-QBS Dell | — | iDRAC 9, PowerEdge R640, Service Tag C84TTQ2. HTTPS console. Vault: `clients/vwp/quickbooks-server-idrac`. Documented 2026-07-07. |
| VWP-HYPERV1 | 172.16.9.184; iDRAC **172.16.9.151** | Hyper-V host — primary VM host for new infrastructure | Windows Server 2025 | Dell R740, 112 vCPU / 255 GB RAM, C: 10.7 TB. One external vSwitch on Intel 10G NIC. VHDs in `C:\VHD`. GuruRMM agent `bdc3e142-...`. Added 2026-06-13. **iDRAC 172.16.9.151** (credentials: vault `clients/vwp/quickbooks-server-idrac` — same password). Documented 2026-07-10 during CRITICAL_PROCESS_DIED recovery. |
| VWP-FILES | 192.168.0.20 (single-homed, VLAN 2; gw 192.168.0.1) | G: file share server (19 SMB shares) | Windows Server 2019 Gen2 VM on VWP-HYPERV1 | Block-migrated from SERVER3 G: VDI (100 GB, ~88 GB used). **Single-homed on 192.168.0.20 since 2026-06-15** — the former 172.16.9.132 vNIC was disconnected at the Hyper-V host to fix cross-VLAN scan-to-folder (the Brother copier hard-codes `\\192.168.0.20`; the multi-homed config had a gateway only on the .132 NIC, so replies to off-subnet clients were dropped — see Patterns). The .132 vNIC is DISCONNECTED at the host (reversible), not removed. DNS registers .20 only. GuruRMM enrolled (site Main Office, agent `8e02fbbc-...`). MSP360 backup running green. **SMB1 server ENABLED 2026-06-23** (#32448) so the legacy XP Orders VM (V-XP) can map `\\VWP-FILES\G-drive` — Server 2019 defaults SMB1-off and XP speaks only SMB1; security tech-debt, remove once Orders is off XP. |
| XenServer | 192.168.0.104 | VM hypervisor — hosts remaining VMs | XenServer 7.6 (PowerEdge R720) | SERVER3 VM (the old "server 2003", upgraded in-place to 2008) is now **powered off and retired**; snapshots retained for rollback. Vault: `clients/vwp/xenserver`. |
| WINFileSvr | 192.168.0.35 | File server — serves **O:** (`Office_Archive`, ~570 GB / 138K files) + **P:** (`Estimating Archive` = F: root, ~545 GB / 142K files), both GPO-mapped to all staff; actively used daily | Windows Server 2019 | Old Net (VLAN 2). **VMware VM on the ESXi host (VMID 11, `WINFilrSrvr`)** — see ESXi inventory. ~1.1 TB live data. Holds `F:\Darv\Darv.rar` (51 GB Darv dev-machine backup) + `F:\Darv\Darv-rar` (extract, trimmed 135→26 GB on 2026-06-14). GuruRMM `62db0264-...`. Candidate to consolidate into VWP-FILES (retire the VM). Do not delete `Darv.rar` until VB6 source verified to compile. |
@@ -303,12 +303,13 @@ After VWP-QBS was force-rebooted via iDRAC (192.168.3.189) following a hung OS,
| 2026-06-15 | **VWP-FILES scan-to-folder fix.** Copier scan-to-`\\192.168.0.20` broke after the 2026-06-13 cutover — root cause was the dual-homed server having a default gateway only on the 172.16.9.132 NIC, so replies on the .20 NIC to off-subnet clients were dropped (not a VLAN-routing limit; the UDM routes all VLANs). Fix: single-homed VWP-FILES on 192.168.0.20 (gw 192.168.0.1) by disconnecting the .132 vNIC host-side via `Disconnect-VMNetworkAdapter` on VWP-HYPERV1 (in-guest change dropped the RMM agent + auto-rolled-back). .132 vNIC left disconnected (reversible), not removed. Scanner = Brother MFC-L3780CDW (vault `clients/vwp/brother-mfc-l3780cdw`). |
| 2026-06-23 | **SMB1 enabled on VWP-FILES** to restore G:/Orders access for the legacy Windows XP app VM (V-XP) after the 6/13 migration — Server 2019 defaults SMB1-off; XP speaks only SMB1. Diagnosed via GuruRMM (payroll desktop G: was fine; Orders runs on V-XP). Ticket #32448, 1.5 hr emergency block deduction (prepay 19.0→17.5 at close). |
| 2026-07-07 | **VWP-QBS stuck in orphaned Datto EDR / Infocyte network isolation** after an iDRAC force-reboot. All off-subnet traffic "General failure" (own IP too) while loopback + DHCP worked — a persistent `Infocyte blocking traffic` WFP filter survived the EDR uninstall. Cleared via WFPExplorer (delivered by DRAC virtual media ISO) → deleted the Infocyte filters; back on 172.16.9.169. **~3 hr remote.** See Security Posture 2026-07-07. |
| 2026-07-10 | **VWP-HYPERV1 CRITICAL_PROCESS_DIED crash + RAID foreign config recovery.** Dell R740 Hyper-V host (172.16.9.184) crashed at 04:31 UTC with CRITICAL_PROCESS_DIED, taking VWP-FILES and G: drive offline. RAID controller lost its configuration; on reboot required importing foreign config to recognize disks. Recovered remotely via iDRAC 172.16.9.151 (ForceRestart via Redfish API). Server + VWP-FILES + G: drive restored. iDRAC IP documented (was missing from wiki). Same root pattern as 2026-04-22 HP ProLiant NVRAM corruption — Dell controllers losing config after crash/power events. **<1 hr remote.** |
---
## Compilation Notes
**Date range covered:** 2026-04-13 through 2026-07-07.
**Date range covered:** 2026-04-13 through 2026-07-10.
**Items flagged [unverified]:**
- M365 MFA and mail flow configuration — never investigated