Update projektplan and TODO with share analysis results
- projektplan: status section (server delivered, driver done), share analysis results in §2.1, customer checklist answers in §2.2, storage resolved in §2.3, new §2.6 on scoping the corpus, updated risks - scripts/list-shares.ps1: enumerate SMB shares incl. paths, permissions and DFS namespaces on the file server - TODO.md: restructured into blocking/server/done Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -2,12 +2,40 @@
|
||||
|
||||
## phy-z-srv-gpu01
|
||||
|
||||
Pre-work per [projektplan](server/phy-z-srv-gpu01/notes/20260710-projektplan.md) (§ references below):
|
||||
Per [projektplan](server/phy-z-srv-gpu01/notes/20260710-projektplan.md) (§ references below).
|
||||
Server is delivered; base setup + NVIDIA driver are done (see `SETUP.md`).
|
||||
|
||||
- [x] Write a script to analyse phytrons whole file share which should be feeded to the llm: file number, structure, pdf kind, etc. → `server/phy-z-srv-gpu01/scripts/share-analysis.ps1`
|
||||
- [ ] Run the share analysis on the Windows server; evaluate: corpus size (§1 revisit trigger), scanned-PDF/OCR share, index size estimate
|
||||
- [ ] Storage decision (§2.3): index estimate vs. ~960 GB usable NVMe — order extra disks **before** delivery if tight
|
||||
- [ ] Customer checklist (§2.2): AD bind account, read-only SMB service account, share include/exclude list, DNS name + TLS, internet access at install, chat-logging/GDPR (works council), maintenance ownership, concretize "other workloads"
|
||||
- [ ] Ansible prep (§2.4): `cifs_mounts` and `llm_stack` role skeletons (`nvidia_gpu` exists); fill `group_vars/phy_z_srv_gpu01.yml` overrides; test non-GPU parts in a throwaway VM
|
||||
- [ ] German eval set (§2.5): collect 20–30 Q&A with the customer — becomes the acceptance criterion
|
||||
- [ ] At install time: re-check and pin versions (driver / vLLM / Open WebUI / oikb / model shortlist) per re-entry checklist §5
|
||||
### Blocking the knowledge base (customer conversation)
|
||||
|
||||
- [ ] **Scope the corpus (§2.6)** — share analysis found 1.26M extractable documents,
|
||||
~12× the planning threshold. Decide with the customer which shares/folders
|
||||
actually form the knowledge base. Everything in Phase 5 depends on this.
|
||||
- [ ] Evaluate the two CSVs still sitting on the file server: `D-toplevel-folders.csv`
|
||||
(basis for the include/exclude list) and `D-file-types.csv` (resolve the
|
||||
1.58M unidentified `other` files)
|
||||
- [ ] Run `scripts/list-shares.ps1` on Z-FILESERVER — map shares → local paths,
|
||||
so the analysis of `D:` can be tied to actual shares
|
||||
- [ ] Data protection / works council: are chat logs stored? (§2.2) — before rollout
|
||||
- [ ] AD details still needed: bind service account + base DN (group `llm_users` and
|
||||
the read-only SMB account are agreed)
|
||||
- [ ] German eval set (§2.5): 20–30 Q&A with the customer — acceptance criterion
|
||||
|
||||
### Server / Ansible
|
||||
|
||||
- [ ] Role `cifs_mounts` — read-only mounts, credentials from `group_vars/secrets.yml`
|
||||
- [ ] Role `llm_stack` — docker compose: vLLM (fixed `--gpu-memory-utilization`),
|
||||
embedding server, Open WebUI + pgvector, reverse proxy, oikb timer.
|
||||
Tag compose tasks with `compose` so `just compose` works.
|
||||
- [ ] Pin versions at install time (vLLM / Open WebUI / oikb / model) per §5
|
||||
- [ ] OCR pipeline for ~166k scanned PDFs (§2.1) — own work block, competes with vLLM for the GPU
|
||||
- [ ] TLS: currently plain HTTP on `chat.phytron.local`; retrofit an internal CA
|
||||
certificate (AD passwords travel in clear text until then)
|
||||
- [ ] Hostname mismatch: server reports `phy-srv-gpu01`, repo/inventory/label use
|
||||
`phy-z-srv-gpu01` — align
|
||||
- [ ] Finish base hardening in `SETUP.md` (ssh, updates) via `just run phy_z_srv_gpu01`
|
||||
|
||||
### Done
|
||||
|
||||
- [x] Share analysis script → `scripts/share-analysis.ps1`, run on 2026-07-14 (§2.1)
|
||||
- [x] Storage decision (§2.3) — 876 GB usable, no extra disks needed
|
||||
- [x] NVIDIA driver via role `nvidia_gpu` (595 open kernel modules)
|
||||
|
||||
@@ -1,11 +1,26 @@
|
||||
# Projektplan — Setup phy-z-srv-gpu01 (LLM-Server mit SMB-Wissensbasis)
|
||||
|
||||
Date: 2026-07-10
|
||||
Status: Plan — Server-Lieferung in einigen Monaten erwartet
|
||||
Date: 2026-07-10 (Stand-Update: 2026-09-03)
|
||||
Status: **In Umsetzung** — Server geliefert, Basis-Setup + GPU-Treiber fertig
|
||||
Basiert auf: `20260706-hardware-assessment.md`, `20260706-software-assessment.md`, `20260707-deep-dive.md`
|
||||
|
||||
---
|
||||
|
||||
## Stand 2026-09-03 (Kurzfassung — Details in den jeweiligen Abschnitten)
|
||||
|
||||
**Erledigt:** Server geliefert und im Rack; Basis-Setup (Ubuntu 24.04.4, Nutzer,
|
||||
Netz, RAID/Filesystem — s. `SETUP.md` im Repo-Root); GPU-Treiber via Ansible-Rolle
|
||||
`nvidia_gpu` (595er-Branch, **open** Kernel-Module — Blackwell läuft nicht mit den
|
||||
proprietären Modulen, s. `manuals/20260714-nvidia-driver-install.md`); Docker
|
||||
installiert. Share-Analyse gelaufen (§2.1).
|
||||
|
||||
**Als Nächstes:** CIFS-Mounts + Container-Stack (Rollen `cifs_mounts`, `llm_stack`)
|
||||
— entspricht Phasen 3–5 in §3.
|
||||
|
||||
**Kritischer offener Punkt:** Der Bestand ist rund **12× größer** als die in §1
|
||||
gesetzte Schwelle. Ohne Eingrenzung des Korpus (Kundengespräch) ist Phase 5 nicht
|
||||
sinnvoll umsetzbar — s. §2.1 und §2.6.
|
||||
|
||||
## 0. Rahmenbedingungen (fixiert)
|
||||
|
||||
| Punkt | Entscheidung |
|
||||
@@ -49,6 +64,14 @@ Deep Dive §4.7). Ausschlaggebend, Stand 2026-07-10 verifiziert:
|
||||
Onyx (mit Eigenbau-Sync) oder Eigenbau-Pipeline (Deep Dive §4.5) neu bewerten.
|
||||
- Datei-genaue NTFS-ACLs werden doch Anforderung → Neubewertung (Deep Dive §4.4/4.5).
|
||||
|
||||
**Status 2026-09-03:** Trigger 1 ist **eingetreten** (1,26 Mio. Office-Dateien,
|
||||
§2.1). Die Produktentscheidung bleibt dennoch bei Open WebUI — aber **nur unter
|
||||
der Bedingung**, dass der Korpus auf einen kuratierten Teilbestand eingegrenzt
|
||||
wird (§2.6). Ein ungefilterter Vollindex über 1,26 Mio. Dokumente ist mit Open
|
||||
WebUI nicht sinnvoll zu betreiben (und liefert auch inhaltlich schlechte
|
||||
Antworten — RAG über einen kompletten, ungeordneten Fileserver retourniert
|
||||
überwiegend Rauschen).
|
||||
|
||||
Jira später: für *Indizierung* von Jira-Inhalten hat Onyx zwar native
|
||||
Konnektoren, Open WebUI deckt das aber über Tools/MCP (Atlassian-MCP) bzw.
|
||||
API-Workloads direkt gegen vLLM ab — kein Entscheidungskriterium für heute.
|
||||
@@ -70,28 +93,54 @@ GPU-Server nötig). Zu erheben:
|
||||
Ergebnis bestimmt: Korpus-Umfang (→ §1-Trigger), OCR-Pipeline ja/nein,
|
||||
Index-Größe (→ Storage-Check §2.3), Erst-Indexierungsdauer.
|
||||
|
||||
### 2.2 Mit dem Kunden zu klären (Checkliste)
|
||||
**Ergebnis (Lauf 2026-07-14, Skript `scripts/share-analysis.ps1` auf `D:` des
|
||||
Fileservers Z-FILESERVER):**
|
||||
|
||||
- [ ] AD/LDAP: Bind-Service-Account, Basis-DN, Gruppe „LLM-Nutzer"
|
||||
- [ ] **SMB-Service-Account read-only** für die Mounts (kein Nutzer-Account)
|
||||
- [ ] Welche Shares/Unterordner genau in den Index? Ausschlussliste (HR o. ä.)
|
||||
- [ ] DNS-Name (z. B. `ki.phytron.local`) + TLS (internes CA-Zertifikat?)
|
||||
- [ ] Internetzugang des Servers (Modell-/Container-Downloads bei Installation;
|
||||
danach einschränkbar)
|
||||
- [ ] Protokollierung/Datenschutz: werden Chats gespeichert? Betriebsrat/DSGVO
|
||||
früh einbinden
|
||||
- [ ] Update-/Wartungsfenster und wer den Betrieb nach Übergabe verantwortet
|
||||
- [ ] „Andere Workloads" konkretisieren (Jira: Inhalte durchsuchen vs.
|
||||
Aktionen ausführen?) → bestimmt MIG-Layout später
|
||||
| Kennzahl | Wert | Konsequenz |
|
||||
|---|---|---|
|
||||
| Gesamt | **3.322.175 Dateien, 2.224 GB** | Scan lief über `D:` gesamt, nicht je Share → Obergrenze, enthält evtl. nicht freigegebene Daten |
|
||||
| `office` (extrahierbar) | **1.258.642 Dateien, 587 GB** | **12× über der §1-Schwelle** → Eingrenzung zwingend (§2.6) |
|
||||
| `other` (unklassifiziert) | 1.575.752 Dateien, 934 GB | größter Block, **noch unidentifiziert** → `D-file-types.csv` auswerten |
|
||||
| Bilder / CAD / Archive / Medien | 403k / 60k / 12,6k / 6,2k Dateien | nicht extrahierbar → Erwartungsmanagement |
|
||||
| PDFs | **924.076**, davon ~**18 % ohne Textlayer** (Stichprobe 200) | ≈ **166.000 Scan-PDFs → OCR**; eigener Zeit-/GPU-Aufwand, konkurriert mit vLLM |
|
||||
| Änderungsrate | 94 % älter als 1 Jahr; nur ~158k in den letzten 365 Tagen | Sync-Frequenz unkritisch; **Alter ≠ Irrelevanz** (Datenblätter, Normen) → Filter primär ordner-/inhaltsbasiert, Aktualität nur sekundär |
|
||||
| Duplikat-/Altversions-Muster | 33.179 Dateien | Filterregeln |
|
||||
| Pfade > 240 Zeichen | 25.169 | Extraktions-Toolchain gezielt testen |
|
||||
| Nicht-ASCII-Dateinamen | 126.111 | UTF-8 durchgängig (CIFS-Mount-Optionen → Extraktion → Index) |
|
||||
|
||||
### 2.3 Storage-Check (⚠️ vor Bestellung ggf. nachsteuern)
|
||||
**Noch auszuwerten** (CSVs liegen auf dem Fileserver, noch nicht gesichtet):
|
||||
`D-toplevel-folders.csv` (Größe/Anzahl je Top-Level-Ordner — die Grundlage für
|
||||
die Include-/Exclude-Liste) und `D-file-types.csv` (Auflösung der `other`-Kategorie).
|
||||
|
||||
2× 960 GB NVMe, vermutlich RAID1 → **~960 GB nutzbar** für OS + Docker +
|
||||
Modelle (~100 GB) + Vektor-DB + Extraktions-Cache. Strategie: **kein lokaler
|
||||
Spiegel der Shares** — nur Index (extrahierter Text + Embeddings, erfahrungsgemäß
|
||||
wenige % des Rohvolumens). Nach der Share-Analyse gegenrechnen; wenn eng:
|
||||
zwei weitere NVMe nachordern (Slots frei) — das ist **vor** Lieferung am
|
||||
billigsten zu ändern.
|
||||
### 2.2 Mit dem Kunden zu klären (Checkliste) — Stand 2026-09-03
|
||||
|
||||
- [x] AD/LDAP: AD-Gruppe **`llm_users`** wird angelegt. *Offen:* Bind-Service-Account
|
||||
und Basis-DN (werden für die LDAP-Konfiguration in Open WebUI gebraucht)
|
||||
- [x] **SMB-Service-Account read-only** wird separat angelegt (kein Nutzer-Account)
|
||||
- [ ] **Welche Shares/Unterordner in den Index?** — offen, wird besprochen;
|
||||
**wichtigster Punkt**, s. §2.1/§2.6
|
||||
- [x] DNS-Name **`chat.phytron.local`** (vorerst); **kein TLS/keine lokalen
|
||||
Zertifikate** zu Beginn → reines HTTP im LAN. *Hinweis:* AD-Passwörter gehen
|
||||
damit im Klartext über das Netz; für später ein internes CA-Zertifikat
|
||||
einplanen (Reverse Proxy ist vorbereitet, nur Zertifikat fehlt)
|
||||
- [x] Internetzugang: **unbeschränkt**, keine Einschränkung nötig
|
||||
- [ ] Protokollierung/Datenschutz: **noch zu besprechen** (Chat-Logs =
|
||||
Verhaltensdaten; Betriebsrat/DSGVO) — vor dem Rollout klären, nicht vor der
|
||||
technischen Umsetzung
|
||||
- [x] Betrieb/Wartung/Updates: **wir** (Softbox)
|
||||
- [x] „Andere Workloads": **Jira vorerst nicht relevant** → MIG bleibt aus, die
|
||||
volle GPU geht an den LLM-Stack
|
||||
|
||||
### 2.3 Storage-Check — ✅ erledigt, unkritisch
|
||||
|
||||
Ist-Stand auf dem Server: **876 GB nutzbar** (`/`, LVM), davon 818 GB frei.
|
||||
Gegenrechnung mit §2.1: selbst ein Vollindex des `office`-Bestands
|
||||
(1,26 Mio. Dokumente → grob 150–250 GB inkl. extrahiertem Text, Embeddings und
|
||||
Index-Overhead) plus Modelle (~100 GB) passt. Strategie bleibt: **kein lokaler
|
||||
Spiegel der Shares**, nur Index. **Keine zusätzlichen NVMe nötig.**
|
||||
|
||||
Der begrenzende Faktor ist damit *nicht* der Plattenplatz, sondern Retrieval-Qualität
|
||||
und Indexgröße (§2.6).
|
||||
|
||||
### 2.4 Ansible vorbereiten (im Repo, testbar ohne GPU)
|
||||
|
||||
@@ -116,6 +165,32 @@ Monaten neu sichten (§ Wiedereinstieg). Kleines deutsches Eval-Set (20–30
|
||||
Fragen mit erwarteten Antworten aus dem Bestand) schon jetzt mit dem Kunden
|
||||
sammeln — das ist später das Abnahmekriterium.
|
||||
|
||||
### 2.6 Korpus eingrenzen (neu, wichtigster offener Punkt)
|
||||
|
||||
Die Share-Analyse (§2.1) hat 1,26 Mio. potenziell extrahierbare Dokumente
|
||||
ergeben. „Alles indizieren" ist weder technisch sinnvoll noch inhaltlich
|
||||
wünschenswert. Vorschlag für das Kundengespräch:
|
||||
|
||||
1. **Ordner statt Alter als Filter.** Aus `D-toplevel-folders.csv` gemeinsam mit
|
||||
dem Kunden die Ordner markieren, die tatsächlich Wissensbasis sind
|
||||
(Doku, Normen, Datenblätter, Handbücher, Projektdoku) — Rest bleibt außen vor.
|
||||
Reiner Aktualitätsfilter wäre falsch: Datenblätter und Normen sind über Jahre
|
||||
gültig.
|
||||
2. **Ausschlusslisten** für Duplikate/Altversionen (33k Treffer), Archiv- und
|
||||
Backup-Ordner, nicht extrahierbare Formate (CAD, Bilder, Medien).
|
||||
3. **Zielgröße nennen.** Als Orientierung: eine gut funktionierende
|
||||
Wissensbasis liegt eher im Bereich **10.000–100.000 Dokumente**. Das ist
|
||||
kein hartes Limit, aber der Bereich, in dem Retrieval-Qualität und
|
||||
Indexierungsdauer beherrschbar bleiben.
|
||||
4. **Iterativ starten.** Phase 5 zuerst mit *einem* gut abgegrenzten Share/Ordner,
|
||||
Qualität am Eval-Set (§2.5) messen, dann erweitern. Das erspart einen
|
||||
tagelangen Fehlversuch über den Gesamtbestand.
|
||||
|
||||
**Erwartungsmanagement gegenüber dem Kunden:** Die ursprüngliche Anforderung
|
||||
lautete sinngemäß „unsere Dokumente auslesen". Realistisch ist „ein kuratierter
|
||||
Teil unserer Dokumente, dafür mit guten Antworten". Das früh sagen — nicht erst,
|
||||
wenn der Vollindex schlechte Treffer liefert.
|
||||
|
||||
## 3. Phasen ab Server-Lieferung
|
||||
|
||||
| Phase | Inhalt | Ergebnis/Abnahme |
|
||||
@@ -133,9 +208,11 @@ sammeln — das ist später das Abnahmekriterium.
|
||||
|
||||
| Risiko | Umgang |
|
||||
|---|---|
|
||||
| Storage zu klein für Index (§2.3) | Share-Analyse → ggf. NVMe nachordern **vor** Lieferung |
|
||||
| Viele gescannte PDFs → OCR-Aufwand & -Qualität | Analyse-Stichprobe; OCR-Phase einplanen; Erwartungen dämpfen |
|
||||
| SM120/Treiber-Kinderkrankheiten (Deep Dive §1.6) | Treiber ≥ 580, NVIDIA-vLLM-Container, Burn-in in Phase 2, HPE-Support |
|
||||
| ~~Storage zu klein für Index~~ | ✅ erledigt — 876 GB nutzbar, reicht (§2.3) |
|
||||
| **Korpus 12× über der Planungsschwelle (§2.1)** | **Eingrenzung auf kuratierten Teilbestand (§2.6); ohne Kundenentscheid keine Phase 5** |
|
||||
| ~166.000 Scan-PDFs → OCR-Aufwand & -Qualität | eigener Arbeitsblock, GPU-Konkurrenz zu vLLM einplanen; Erwartungen dämpfen |
|
||||
| ~~SM120/Treiber-Kinderkrankheiten~~ | ✅ erledigt — Treiber 595 **open** läuft (proprietäre Module scheitern an `RmInitAdapter`) |
|
||||
| Kein TLS zu Beginn (§2.2) | AD-Passwörter im Klartext im LAN; internes CA-Zertifikat nachrüsten, Reverse Proxy vorbereiten |
|
||||
| Software-Stand veraltet bis Lieferung | Versionen **erst bei Installation pinnen**; Wiedereinstiegs-Checkliste |
|
||||
| Erst-Indexierung dauert Tage | Teilbestand zuerst; Sync nachts; Dauer vorab abschätzen |
|
||||
| RAM-Konkurrenz Extraktion/OCR vs. vLLM | vLLM hat feste VRAM-Quote; Indexer-Jobs drosseln (nice/cgroups); 128 GB reichen für OWUI-Stack |
|
||||
@@ -144,12 +221,12 @@ sammeln — das ist später das Abnahmekriterium.
|
||||
|
||||
## 5. Wiedereinstiegs-Checkliste (wenn der Server da ist)
|
||||
|
||||
1. Dieses Dokument + Deep Dive lesen; offene Punkte aus §2.2 abhaken
|
||||
2. Ergebnis der Share-Analyse vorliegen? (sonst zuerst!)
|
||||
3. Neu sichten & **dann erst pinnen**: vLLM-Version (RTX-PRO-6000-Support),
|
||||
Open WebUI + oikb Release Notes, NVIDIA-Treiber, Modell-Shortlist §2.5
|
||||
4. Storage-Entscheidung §2.3 umgesetzt?
|
||||
5. Dann Phasenplan §3 von oben abarbeiten; jede Phase = Ansible-Commit + ggf.
|
||||
1. [x] Dieses Dokument + Deep Dive lesen; offene Punkte aus §2.2 abhaken
|
||||
2. [x] Ergebnis der Share-Analyse vorliegen? → §2.1
|
||||
3. [ ] Neu sichten & **dann erst pinnen**: vLLM-Version (RTX-PRO-6000-/SM120-Support),
|
||||
Open WebUI + oikb Release Notes, Modell-Shortlist §2.5 — NVIDIA-Treiber ✅ (595-open)
|
||||
4. [x] Storage-Entscheidung §2.3 → unkritisch, nichts nachzubestellen
|
||||
5. [ ] Dann Phasenplan §3 von oben abarbeiten; jede Phase = Ansible-Commit + ggf.
|
||||
Runbook unter `manuals/`
|
||||
|
||||
## 6. Bewusst offen gelassen (kein Jetzt-Entscheid nötig)
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Lists all SMB shares of a Windows file server incl. local path, size and
|
||||
permissions — the basis for the include/exclude decision (projektplan §2.6).
|
||||
|
||||
.DESCRIPTION
|
||||
Run ON the file server (or against a remote one via -ComputerName). Reports
|
||||
per share: name, local path, description, share-level permissions, NTFS
|
||||
groups, plus optional size/file count. Admin shares (C$, ADMIN$, IPC$) are
|
||||
skipped unless -IncludeAdminShares is given.
|
||||
|
||||
Purely read-only. Requires local admin for Get-SmbShare (part of Windows
|
||||
Server, no extra module needed).
|
||||
|
||||
.EXAMPLE
|
||||
.\list-shares.ps1
|
||||
|
||||
.EXAMPLE
|
||||
# remote, and with size per share (slow on large shares)
|
||||
.\list-shares.ps1 -ComputerName Z-FILESERVER -WithSize
|
||||
#>
|
||||
param(
|
||||
[string]$ComputerName = $env:COMPUTERNAME,
|
||||
[switch]$IncludeAdminShares,
|
||||
[switch]$WithSize,
|
||||
[string]$OutDir = (Join-Path (Get-Location) "share-list")
|
||||
)
|
||||
|
||||
$ErrorActionPreference = 'Continue'
|
||||
New-Item -ItemType Directory -Path $OutDir -Force | Out-Null
|
||||
|
||||
Write-Host "=== SMB shares on $ComputerName ===" -ForegroundColor Cyan
|
||||
|
||||
$shares = Get-SmbShare -CimSession $ComputerName -ErrorAction Stop
|
||||
if (-not $IncludeAdminShares) {
|
||||
$shares = $shares | Where-Object { -not $_.Name.EndsWith('$') }
|
||||
}
|
||||
|
||||
$result = foreach ($sh in $shares) {
|
||||
Write-Host (" {0,-25} {1}" -f $sh.Name, $sh.Path)
|
||||
|
||||
# share-level permissions
|
||||
$sharePerms = try {
|
||||
(Get-SmbShareAccess -Name $sh.Name -CimSession $ComputerName -ErrorAction Stop |
|
||||
ForEach-Object { "$($_.AccountName)=$($_.AccessRight)" }) -join '; '
|
||||
} catch { 'n/a' }
|
||||
|
||||
# NTFS permissions (top level only) — who actually has access
|
||||
$ntfsPerms = try {
|
||||
$uncPath = "\\$ComputerName\$($sh.Name)"
|
||||
((Get-Acl -LiteralPath $uncPath -ErrorAction Stop).Access |
|
||||
ForEach-Object { "$($_.IdentityReference)=$($_.FileSystemRights)" } |
|
||||
Select-Object -Unique | Select-Object -First 10) -join '; '
|
||||
} catch { 'n/a' }
|
||||
|
||||
$sizeGB = $null; $fileCount = $null
|
||||
if ($WithSize) {
|
||||
Write-Host " measuring size ..." -ForegroundColor DarkGray
|
||||
try {
|
||||
$m = Get-ChildItem -LiteralPath "\\$ComputerName\$($sh.Name)" -Recurse -File -Force -ErrorAction SilentlyContinue |
|
||||
Measure-Object -Property Length -Sum
|
||||
$sizeGB = [Math]::Round($m.Sum / 1GB, 2)
|
||||
$fileCount = $m.Count
|
||||
} catch { }
|
||||
}
|
||||
|
||||
[PSCustomObject]@{
|
||||
Name = $sh.Name
|
||||
Path = $sh.Path
|
||||
Description = $sh.Description
|
||||
SharePermissions = $sharePerms
|
||||
NtfsPermissions = $ntfsPerms
|
||||
SizeGB = $sizeGB
|
||||
FileCount = $fileCount
|
||||
}
|
||||
}
|
||||
|
||||
$csv = Join-Path $OutDir "smb-shares.csv"
|
||||
$result | Export-Csv $csv -NoTypeInformation -Encoding UTF8
|
||||
$result | Format-Table Name, Path, SizeGB, FileCount -AutoSize
|
||||
|
||||
# DFS namespaces (if used) — often the path users actually see
|
||||
Write-Host "`n=== DFS namespaces ===" -ForegroundColor Cyan
|
||||
try {
|
||||
$roots = Get-DfsnRoot -ErrorAction Stop
|
||||
if ($roots) {
|
||||
$dfs = foreach ($r in $roots) {
|
||||
Get-DfsnFolder -Path "$($r.Path)\*" -ErrorAction SilentlyContinue | ForEach-Object {
|
||||
$t = Get-DfsnFolderTarget -Path $_.Path -ErrorAction SilentlyContinue
|
||||
[PSCustomObject]@{ DfsPath = $_.Path; Targets = ($t.TargetPath -join '; ') }
|
||||
}
|
||||
}
|
||||
$dfs | Export-Csv (Join-Path $OutDir "dfs-namespaces.csv") -NoTypeInformation -Encoding UTF8
|
||||
$dfs | Format-Table -AutoSize
|
||||
} else { Write-Host " none" }
|
||||
} catch {
|
||||
Write-Host " no DFS role / not available on this host"
|
||||
}
|
||||
|
||||
Write-Host "`nResults in: $OutDir" -ForegroundColor Green
|
||||
Reference in New Issue
Block a user