# PGS - Technical Notes

## Rol

`pgs` ofera un flux manual si predictibil pentru:
- suspend to disk la VM-uri QEMU aflate in rulare
- shutdown graceful la containere LXC aflate in rulare
- resume/start dupa mentenanta pe baza unui state file local

## Comanda instalata

- locatie: `/usr/local/sbin/pgs`
- uninstall canonic: `/usr/local/lib/xdev/pve-guests-state/uninstall.sh`
- documentatie instalata: `/usr/local/share/doc/xdev/pve-guests-state`

## State runtime

- locatie curenta: `/var/lib/xdev/pve-guests-state/pgs-state.json`
- locatie legacy acceptata pentru migrare: `/var/lib/pve-manager/pgs-state.json`
- lock file: `/run/pgs.lock`

State file-ul contine:
- `timestamp`
- `hostname`
- `to_resume`
- `was_suspended`
- `ct_to_start`
- `vm_details`
  - `mode`
  - `suspend_volume`
  - `suspend_file_date`

## Comenzi

```bash
/usr/local/sbin/pgs suspend [-v] [--dry-run]
/usr/local/sbin/pgs resume [-v] [--dry-run]
/usr/local/sbin/pgs cleanup [-v] [--dry-run]
```

## Comportament

### Suspend

- preflight cleanup pentru volume orphan/stale `vm-*-state-suspend-YYYY-MM-DD.raw`
- VM running -> `qm suspend --todisk 1` -> adaugat in `to_resume`
- VM paused/suspended RAM -> suspend to disk, dar nu intra in `to_resume`
- VM deja suspendat pe disk -> warning, fara auto-resume; detectia pentru disk suspend cere `lock: suspended`, `vmstate:` in config si un volum de saved-state rezolvabil in storage
- CT running -> `pct shutdown --timeout 120` -> adaugat in `ct_to_start`
- daca exista deja state file, un nou `suspend` face merge peste state-ul existent si pastreaza intentia anterioara de `to_resume`
- pentru fiecare VM retinut in state se salveaza si `suspend_volume` plus `suspend_file_date`

### Cleanup

- scaneaza doar storage-urile locale de tip `dir` cu `content images` definite in `/etc/pve/storage.cfg`
- cauta exclusiv fisiere `vm-*-state-suspend-YYYY-MM-DD.raw`
- ignora fisiere de forma `vm-*-state-cp*.raw`
- storages remote precum NFS sunt sarite intentionat, pentru ca un mount stale poate bloca procesul in kernel I/O wait chiar inainte de mentenanta
- daca un volum `state-suspend` este referit de un VM valid suspendat, il pastreaza
- daca un volum `state-suspend` este referit, dar VM-ul nu mai are stare valida de suspend, curata `lock`, `vmstate` si volumul
- daca un volum `state-suspend` nu mai este referit de niciun VM, il trateaza ca orphan si il sterge

### Resume

- VMs din `to_resume` -> `qm resume`
- CTs din `ct_to_start` -> `pct start`
- daca `suspend_volume` curent nu mai corespunde cu cel din state, VM-ul este tratat ca alterat dupa salvarea state-ului si nu este auto-resumat
- daca apar esecuri, state file-ul ramane pentru retry
- daca totul reuseste, state file-ul este sters

## Protectii implementate

- stale suspend image cleanup
- cleanup pentru volume orphan `vm-*-state-suspend-YYYY-MM-DD.raw`
- retry dupa erori specifice de quorum
- `pvecm expected 1` in fereastra de mentenanta, cand eroarea indica lipsa de quorum
- cleanup pentru `lock: suspended` cand VM-ul este deja running
- cleanup pentru artefacte stale de suspend pe VM-uri `stopped`: `lock: suspended`, `vmstate:` ramas in config si volume orphaned de saved-state
- lock local pentru a preveni rulari concurente

## Logging

- interactiva: output pe terminal
- prin systemd/journal stream: evitarea dublarii mesajelor in journal
- tag jurnal: `pgs`

Exemple:

```bash
journalctl -t pgs -n 50 --no-pager
journalctl -t pgs -f
```

## Note de design

- proiectul nu mai foloseste unitati systemd pentru execuție automata
- fisierele din `systemd/` sunt legacy si nu fac parte din install-ul curent
- proiectul nu are inca propriul config persistent in `/etc/xdev/...`
