LocalAuthority / .doc / database.md
Newer Older
439 lines | 12.86kb
Bogdan Timofte authored 4 days ago
1
# SQLite Database
2

            
Bogdan Timofte authored 4 days ago
3
Madagascar Local Authority folosește SQLite ca sursă de adevăr runtime pentru hosturi, aliasuri, vhosturi, Work Orders, workeri de date și certificate.
Bogdan Timofte authored 4 days ago
4

            
5
Locația implicită în checkout:
6

            
7
```text
8
var/host-manager.sqlite
9
```
10

            
11
Locația runtime pe jumper:
12

            
13
```text
14
/usr/local/xdev-host-manager/var/host-manager.sqlite
15
```
16

            
17
Path-ul poate fi schimbat cu:
18

            
19
```text
20
HOST_MANAGER_DB=/path/to/host-manager.sqlite
21
```
22

            
Bogdan Timofte authored 4 days ago
23
## Principii
Bogdan Timofte authored 4 days ago
24

            
Bogdan Timofte authored 4 days ago
25
Hosturile sunt identificate prin FQDN complet, nu prin short name. Exemplu: `gw.local` și `gw.remote` sunt identități diferite. Coloana compatibilă `legacy_id` păstrează ID-ul scurt folosit de UI-ul curent, dar cheia reală este `hosts.fqdn`.
Bogdan Timofte authored 4 days ago
26

            
Bogdan Timofte authored 4 days ago
27
Schema evită să transforme `hosts` într-un tabel cu prea multe coloane. Datele specializate sunt în tabele separate:
Bogdan Timofte authored 4 days ago
28

            
Bogdan Timofte authored 4 days ago
29
- aliasuri: `host_aliases`
30
- roluri: `host_roles`
31
- surse: `host_sources`
32
- flaguri: `host_flags`
33
- SSH: `host_ssh`
34
- vhosturi mutabile: `vhosts`
35
- certificate: `certificates`, `certificate_dns_names`
36
- workeri și observații: `data_workers`, `dhcp_leases`, `mdns_observations`
Bogdan Timofte authored 4 days ago
37

            
Bogdan Timofte authored 4 days ago
38
`documents` rămâne doar tabel legacy pentru migrarea din modelul vechi document-store. Aplicația nu îl mai folosește ca sursă de adevăr.
Bogdan Timofte authored 4 days ago
39

            
Bogdan Timofte authored 4 days ago
40
## Schema Version
41

            
42
Schema curentă este versiunea `2`.
43

            
44
```sql
45
schema_meta('schema_version') = '2'
46
```
47

            
48
`schema_meta` păstrează și metadate runtime precum `registry_updated_at`.
49

            
50
## Catalog
51

            
52
| Tabel | Rol |
53
|-------|-----|
54
| `schema_meta` | metadate de schemă/runtime |
55
| `documents` | document-store legacy pentru migrare |
56
| `hosts` | hosturi canonice, identificate prin FQDN |
57
| `host_aliases` | aliasuri păstrate inclusiv după retragere |
58
| `host_roles` | roluri active/retrase per host |
59
| `host_sources` | surse active/retrase per host |
60
| `host_flags` | flaguri extensibile per host |
61
| `host_ssh` | profile SSH per host |
62
| `vhosts` | vhosturi mutabile între hosturi |
63
| `data_workers` | workeri/surse care colectează date |
64
| `dhcp_leases` | date observate din DHCP lease/reservation |
65
| `mdns_observations` | date observate din mDNS |
66
| `certificates` | certificate emise de CA locală |
67
| `certificate_dns_names` | SAN DNS names pentru certificate |
68
| `work_orders` | Work Orders |
69
| `work_order_checklist` | checklist items pentru Work Orders |
70
| `work_order_actions` | acțiuni confirmabile pentru Work Orders |
71

            
72
## Tabele
73

            
74
### `hosts`
Bogdan Timofte authored 4 days ago
75

            
76
```sql
Bogdan Timofte authored 4 days ago
77
CREATE TABLE hosts (
78
    fqdn TEXT PRIMARY KEY,
79
    legacy_id TEXT NOT NULL UNIQUE,
80
    status TEXT NOT NULL DEFAULT 'active',
81
    hosts_ip TEXT NOT NULL DEFAULT '',
82
    dns_ip TEXT NOT NULL DEFAULT '',
83
    monitoring TEXT NOT NULL DEFAULT 'pending',
84
    notes TEXT NOT NULL DEFAULT '',
85
    created_at TEXT NOT NULL,
Bogdan Timofte authored 4 days ago
86
    updated_at TEXT NOT NULL
87
);
88
```
89

            
Bogdan Timofte authored 4 days ago
90
Chei și indexuri:
Bogdan Timofte authored 4 days ago
91

            
Bogdan Timofte authored 4 days ago
92
- PK: `hosts(fqdn)`
93
- UNIQUE: `hosts(legacy_id)`
Bogdan Timofte authored 4 days ago
94

            
Bogdan Timofte authored 4 days ago
95
### `host_aliases`
Bogdan Timofte authored 4 days ago
96

            
Bogdan Timofte authored 4 days ago
97
```sql
98
CREATE TABLE host_aliases (
99
    alias_name TEXT NOT NULL,
100
    host_fqdn TEXT NOT NULL REFERENCES hosts(fqdn)
101
        ON UPDATE CASCADE ON DELETE RESTRICT,
102
    alias_kind TEXT NOT NULL DEFAULT 'declared',
103
    status TEXT NOT NULL DEFAULT 'active',
104
    is_dns_published INTEGER NOT NULL DEFAULT 1,
105
    created_at TEXT NOT NULL,
106
    retired_at TEXT,
107
    notes TEXT NOT NULL DEFAULT '',
108
    PRIMARY KEY (alias_name, host_fqdn)
109
);
110
```
Bogdan Timofte authored 4 days ago
111

            
Bogdan Timofte authored 4 days ago
112
Indexuri:
Bogdan Timofte authored 4 days ago
113

            
Bogdan Timofte authored 4 days ago
114
```sql
115
CREATE UNIQUE INDEX idx_host_aliases_active_name
116
ON host_aliases(alias_name)
117
WHERE status = 'active';
Bogdan Timofte authored 4 days ago
118

            
Bogdan Timofte authored 4 days ago
119
CREATE INDEX idx_host_aliases_host_status
120
ON host_aliases(host_fqdn, status);
121
```
Bogdan Timofte authored 4 days ago
122

            
Bogdan Timofte authored 4 days ago
123
Reguli:
Bogdan Timofte authored 4 days ago
124

            
Bogdan Timofte authored 4 days ago
125
- aliasurile retrase nu se șterg; se setează `status = 'retired'`
126
- un alias activ poate aparține unui singur host
127
- aliasurile scurte derivate, cum ar fi `baobab`, sunt păstrate cu `alias_kind = 'derived'`
128
- short aliases derivate din vhosturi, cum ar fi `pmx.baobab`, sunt păstrate cu `alias_kind = 'derived-vhost'`
Bogdan Timofte authored 4 days ago
129

            
Bogdan Timofte authored 4 days ago
130
### `vhosts`
Bogdan Timofte authored 4 days ago
131

            
Bogdan Timofte authored 4 days ago
132
```sql
133
CREATE TABLE vhosts (
134
    vhost_fqdn TEXT PRIMARY KEY,
135
    host_fqdn TEXT NOT NULL REFERENCES hosts(fqdn)
136
        ON UPDATE CASCADE ON DELETE RESTRICT,
137
    status TEXT NOT NULL DEFAULT 'active',
138
    service_name TEXT NOT NULL DEFAULT '',
139
    upstream_url TEXT NOT NULL DEFAULT '',
140
    tls_mode TEXT NOT NULL DEFAULT 'local-ca',
141
    certificate_id TEXT REFERENCES certificates(certificate_id)
142
        ON UPDATE CASCADE ON DELETE SET NULL,
143
    notes TEXT NOT NULL DEFAULT '',
144
    created_at TEXT NOT NULL,
145
    updated_at TEXT NOT NULL
146
);
147
```
Bogdan Timofte authored 4 days ago
148

            
Bogdan Timofte authored 4 days ago
149
Indexuri:
Bogdan Timofte authored 4 days ago
150

            
Bogdan Timofte authored 4 days ago
151
```sql
152
CREATE INDEX idx_vhosts_host_status
153
ON vhosts(host_fqdn, status);
154
```
Bogdan Timofte authored 4 days ago
155

            
Bogdan Timofte authored 4 days ago
156
Un vhost se mută de pe un host pe altul prin update pe `vhosts.host_fqdn`. Vhosturile retrase rămân în tabel cu `status = 'retired'`.
Bogdan Timofte authored 4 days ago
157

            
Bogdan Timofte authored 4 days ago
158
### `host_roles`, `host_sources`, `host_flags`, `host_ssh`
Bogdan Timofte authored 4 days ago
159

            
Bogdan Timofte authored 4 days ago
160
```sql
161
CREATE TABLE host_roles (
162
    host_fqdn TEXT NOT NULL REFERENCES hosts(fqdn)
163
        ON UPDATE CASCADE ON DELETE RESTRICT,
164
    role TEXT NOT NULL,
165
    status TEXT NOT NULL DEFAULT 'active',
166
    created_at TEXT NOT NULL,
167
    retired_at TEXT,
168
    PRIMARY KEY (host_fqdn, role)
169
);
Bogdan Timofte authored 4 days ago
170

            
Bogdan Timofte authored 4 days ago
171
CREATE TABLE host_sources (
172
    host_fqdn TEXT NOT NULL REFERENCES hosts(fqdn)
173
        ON UPDATE CASCADE ON DELETE RESTRICT,
174
    source TEXT NOT NULL,
175
    status TEXT NOT NULL DEFAULT 'active',
176
    created_at TEXT NOT NULL,
177
    retired_at TEXT,
178
    PRIMARY KEY (host_fqdn, source)
179
);
Bogdan Timofte authored 4 days ago
180

            
Bogdan Timofte authored 4 days ago
181
CREATE TABLE host_flags (
182
    host_fqdn TEXT NOT NULL REFERENCES hosts(fqdn)
183
        ON UPDATE CASCADE ON DELETE RESTRICT,
184
    flag TEXT NOT NULL,
185
    value TEXT NOT NULL DEFAULT '1',
186
    created_at TEXT NOT NULL,
187
    updated_at TEXT NOT NULL,
188
    PRIMARY KEY (host_fqdn, flag)
189
);
Bogdan Timofte authored 4 days ago
190

            
Bogdan Timofte authored 4 days ago
191
CREATE TABLE host_ssh (
192
    host_fqdn TEXT NOT NULL REFERENCES hosts(fqdn)
193
        ON UPDATE CASCADE ON DELETE RESTRICT,
194
    profile_name TEXT NOT NULL DEFAULT 'default',
195
    username TEXT NOT NULL DEFAULT '',
196
    port INTEGER NOT NULL DEFAULT 22,
197
    identity_file TEXT NOT NULL DEFAULT '',
198
    address TEXT NOT NULL DEFAULT '',
199
    local_forward_host TEXT NOT NULL DEFAULT '',
200
    local_forward_port INTEGER,
201
    remote_forward_host TEXT NOT NULL DEFAULT '',
202
    remote_forward_port INTEGER,
203
    notes TEXT NOT NULL DEFAULT '',
204
    created_at TEXT NOT NULL,
205
    updated_at TEXT NOT NULL,
206
    PRIMARY KEY (host_fqdn, profile_name)
207
);
208
```
Bogdan Timofte authored 4 days ago
209

            
Bogdan Timofte authored 4 days ago
210
### `data_workers`
Bogdan Timofte authored 4 days ago
211

            
212
```sql
Bogdan Timofte authored 4 days ago
213
CREATE TABLE data_workers (
214
    worker_id TEXT PRIMARY KEY,
215
    worker_type TEXT NOT NULL,
216
    name TEXT NOT NULL DEFAULT '',
217
    status TEXT NOT NULL DEFAULT 'active',
218
    source TEXT NOT NULL DEFAULT '',
219
    last_run_at TEXT,
220
    notes TEXT NOT NULL DEFAULT '',
221
    created_at TEXT NOT NULL,
222
    updated_at TEXT NOT NULL
223
);
Bogdan Timofte authored 4 days ago
224
```
225

            
Bogdan Timofte authored 4 days ago
226
Indexuri:
Bogdan Timofte authored 4 days ago
227

            
228
```sql
Bogdan Timofte authored 4 days ago
229
CREATE INDEX idx_data_workers_type_status
230
ON data_workers(worker_type, status);
Bogdan Timofte authored 4 days ago
231
```
232

            
Bogdan Timofte authored 4 days ago
233
Seed implicit:
234

            
235
- `dhcp-router`, type `dhcp`
236
- `mdns-listener`, type `mdns`
237

            
238
### `dhcp_leases`
Bogdan Timofte authored 4 days ago
239

            
240
```sql
Bogdan Timofte authored 4 days ago
241
CREATE TABLE dhcp_leases (
242
    lease_key TEXT PRIMARY KEY,
243
    worker_id TEXT NOT NULL REFERENCES data_workers(worker_id)
244
        ON UPDATE CASCADE ON DELETE RESTRICT,
245
    host_fqdn TEXT REFERENCES hosts(fqdn)
246
        ON UPDATE CASCADE ON DELETE SET NULL,
247
    observed_name TEXT NOT NULL DEFAULT '',
248
    ip_address TEXT NOT NULL,
249
    mac_address TEXT NOT NULL DEFAULT '',
250
    lease_state TEXT NOT NULL DEFAULT '',
251
    first_seen TEXT NOT NULL,
252
    last_seen TEXT NOT NULL,
253
    raw TEXT NOT NULL DEFAULT ''
Bogdan Timofte authored 4 days ago
254
);
255
```
256

            
Bogdan Timofte authored 4 days ago
257
Indexuri:
Bogdan Timofte authored 4 days ago
258

            
259
```sql
Bogdan Timofte authored 4 days ago
260
CREATE INDEX idx_dhcp_leases_ip ON dhcp_leases(ip_address);
261
CREATE INDEX idx_dhcp_leases_mac ON dhcp_leases(mac_address);
262
CREATE INDEX idx_dhcp_leases_worker_last_seen
263
ON dhcp_leases(worker_id, last_seen);
Bogdan Timofte authored 4 days ago
264
```
265

            
Bogdan Timofte authored 4 days ago
266
### `mdns_observations`
Bogdan Timofte authored 4 days ago
267

            
Bogdan Timofte authored 4 days ago
268
```sql
269
CREATE TABLE mdns_observations (
270
    observation_key TEXT PRIMARY KEY,
271
    worker_id TEXT NOT NULL REFERENCES data_workers(worker_id)
272
        ON UPDATE CASCADE ON DELETE RESTRICT,
273
    host_fqdn TEXT REFERENCES hosts(fqdn)
274
        ON UPDATE CASCADE ON DELETE SET NULL,
275
    observed_name TEXT NOT NULL,
276
    ip_address TEXT NOT NULL,
277
    rr_type TEXT NOT NULL DEFAULT 'A',
278
    ttl INTEGER NOT NULL DEFAULT 0,
279
    first_seen TEXT NOT NULL,
280
    last_seen TEXT NOT NULL,
281
    seen_count INTEGER NOT NULL DEFAULT 1,
282
    last_peer TEXT NOT NULL DEFAULT '',
283
    raw TEXT NOT NULL DEFAULT ''
284
);
285
```
Bogdan Timofte authored 4 days ago
286

            
Bogdan Timofte authored 4 days ago
287
Indexuri:
Bogdan Timofte authored 4 days ago
288

            
Bogdan Timofte authored 4 days ago
289
```sql
290
CREATE INDEX idx_mdns_observations_name ON mdns_observations(observed_name);
291
CREATE INDEX idx_mdns_observations_ip ON mdns_observations(ip_address);
292
CREATE INDEX idx_mdns_observations_worker_last_seen
293
ON mdns_observations(worker_id, last_seen);
294
```
Bogdan Timofte authored 4 days ago
295

            
Bogdan Timofte authored 4 days ago
296
### `certificates` și `certificate_dns_names`
Bogdan Timofte authored 4 days ago
297

            
Bogdan Timofte authored 4 days ago
298
```sql
299
CREATE TABLE certificates (
300
    certificate_id TEXT PRIMARY KEY,
301
    host_fqdn TEXT REFERENCES hosts(fqdn)
302
        ON UPDATE CASCADE ON DELETE SET NULL,
303
    common_name TEXT NOT NULL DEFAULT '',
304
    subject TEXT NOT NULL DEFAULT '',
305
    issuer TEXT NOT NULL DEFAULT '',
306
    serial TEXT UNIQUE,
307
    status TEXT NOT NULL DEFAULT 'issued',
308
    not_before TEXT NOT NULL DEFAULT '',
309
    not_after TEXT NOT NULL DEFAULT '',
310
    fingerprint_sha256 TEXT UNIQUE,
311
    cert_path TEXT NOT NULL DEFAULT '',
312
    csr_path TEXT NOT NULL DEFAULT '',
313
    created_at TEXT NOT NULL,
314
    updated_at TEXT NOT NULL,
315
    notes TEXT NOT NULL DEFAULT ''
316
);
Bogdan Timofte authored 4 days ago
317

            
Bogdan Timofte authored 4 days ago
318
CREATE TABLE certificate_dns_names (
319
    certificate_id TEXT NOT NULL REFERENCES certificates(certificate_id)
320
        ON UPDATE CASCADE ON DELETE CASCADE,
321
    dns_name TEXT NOT NULL,
322
    PRIMARY KEY (certificate_id, dns_name)
323
);
Bogdan Timofte authored 4 days ago
324
```
325

            
Bogdan Timofte authored 4 days ago
326
Indexuri:
Bogdan Timofte authored 4 days ago
327

            
Bogdan Timofte authored 4 days ago
328
```sql
329
CREATE INDEX idx_certificate_dns_names_dns_name
330
ON certificate_dns_names(dns_name);
331
```
Bogdan Timofte authored 4 days ago
332

            
Bogdan Timofte authored 4 days ago
333
Certificatele emise sunt sincronizate când aplicația citește lista CA prin `ca_manager.sh list-json`.
Bogdan Timofte authored 4 days ago
334

            
Bogdan Timofte authored 4 days ago
335
### Work Orders
Bogdan Timofte authored 4 days ago
336

            
Bogdan Timofte authored 4 days ago
337
```sql
338
CREATE TABLE work_orders (
339
    id TEXT PRIMARY KEY,
340
    status TEXT NOT NULL DEFAULT 'pending',
341
    title TEXT NOT NULL DEFAULT '',
342
    reason TEXT NOT NULL DEFAULT '',
343
    created_at TEXT NOT NULL,
344
    confirmed_at TEXT NOT NULL DEFAULT '',
345
    result TEXT NOT NULL DEFAULT '',
346
    updated_at TEXT NOT NULL
347
);
Bogdan Timofte authored 4 days ago
348

            
Bogdan Timofte authored 4 days ago
349
CREATE TABLE work_order_checklist (
350
    work_order_id TEXT NOT NULL REFERENCES work_orders(id)
351
        ON UPDATE CASCADE ON DELETE CASCADE,
352
    item_id TEXT NOT NULL,
353
    text TEXT NOT NULL DEFAULT '',
354
    status TEXT NOT NULL DEFAULT 'pending',
355
    owner TEXT NOT NULL DEFAULT '',
356
    notes TEXT NOT NULL DEFAULT '',
357
    updated_at TEXT NOT NULL DEFAULT '',
358
    PRIMARY KEY (work_order_id, item_id)
359
);
Bogdan Timofte authored 4 days ago
360

            
Bogdan Timofte authored 4 days ago
361
CREATE TABLE work_order_actions (
362
    work_order_id TEXT NOT NULL REFERENCES work_orders(id)
363
        ON UPDATE CASCADE ON DELETE CASCADE,
364
    position INTEGER NOT NULL,
365
    type TEXT NOT NULL,
366
    host_fqdn TEXT REFERENCES hosts(fqdn)
367
        ON UPDATE CASCADE ON DELETE SET NULL,
368
    host_legacy_id TEXT NOT NULL DEFAULT '',
369
    name TEXT NOT NULL DEFAULT '',
370
    payload TEXT NOT NULL DEFAULT '',
371
    PRIMARY KEY (work_order_id, position)
372
);
373
```
Bogdan Timofte authored 4 days ago
374

            
Bogdan Timofte authored 4 days ago
375
## Migrare și Seed
Bogdan Timofte authored 4 days ago
376

            
Bogdan Timofte authored 4 days ago
377
La prima inițializare a unei baze fără rânduri în `hosts`, aplicația seed-uiește din:
Bogdan Timofte authored 4 days ago
378

            
Bogdan Timofte authored 4 days ago
379
1. `documents.name = 'hosts_yaml'`, dacă există din vechiul model
380
2. `config/hosts.yaml`, dacă documentul legacy lipsește
381
3. document gol valid, dacă lipsește și seed-ul
Bogdan Timofte authored 4 days ago
382

            
Bogdan Timofte authored 4 days ago
383
Work Orders se seed-uiesc similar din `documents.name = 'work_orders_yaml'` sau `config/work-orders.yaml`.
Bogdan Timofte authored 4 days ago
384

            
Bogdan Timofte authored 4 days ago
385
Seed-ul curent produce:
Bogdan Timofte authored 4 days ago
386

            
Bogdan Timofte authored 4 days ago
387
- 11 hosturi cunoscute
388
- aliasuri scurte derivate pentru hosturi și vhosturi
389
- vhosturile `hosts.*`, `pmx.*` și `pbs.*`
390
- workerii `dhcp-router` și `mdns-listener`
391
- Work Order-ul existent pentru retragerea numelor legacy
Bogdan Timofte authored 4 days ago
392

            
Bogdan Timofte authored 4 days ago
393
`config/local-hosts.tsv` rămâne manifest generat explicit din tabelele runtime.
Bogdan Timofte authored 4 days ago
394

            
395
## Inspecție
396

            
397
Pe jumper:
398

            
399
```bash
400
cd /usr/local/xdev-host-manager
Bogdan Timofte authored 4 days ago
401
sqlite3 var/host-manager.sqlite '.tables'
Bogdan Timofte authored 4 days ago
402
sqlite3 var/host-manager.sqlite '.schema hosts'
403
sqlite3 var/host-manager.sqlite '.schema host_aliases'
404
sqlite3 var/host-manager.sqlite '.schema vhosts'
405
sqlite3 var/host-manager.sqlite 'pragma foreign_key_list(vhosts);'
406
sqlite3 var/host-manager.sqlite 'pragma index_list(host_aliases);'
407
sqlite3 var/host-manager.sqlite 'select fqdn, legacy_id, status, dns_ip from hosts order by legacy_id;'
408
sqlite3 var/host-manager.sqlite 'select alias_name, host_fqdn, alias_kind, status from host_aliases order by alias_name;'
409
sqlite3 var/host-manager.sqlite 'select vhost_fqdn, host_fqdn, status from vhosts order by vhost_fqdn;'
Bogdan Timofte authored 4 days ago
410
```
411

            
412
## Backup
413

            
Bogdan Timofte authored 4 days ago
414
Backup recomandat:
Bogdan Timofte authored 4 days ago
415

            
416
```bash
417
cd /usr/local/xdev-host-manager
418
sqlite3 var/host-manager.sqlite ".backup 'backups/host-manager/host-manager.sqlite.$(date +%Y%m%d_%H%M%S).bak'"
419
```
420

            
Bogdan Timofte authored 4 days ago
421
Cu WAL activ, o copie brută trebuie să trateze fișierele ca set coerent:
Bogdan Timofte authored 4 days ago
422

            
Bogdan Timofte authored 4 days ago
423
```text
424
var/host-manager.sqlite
425
var/host-manager.sqlite-wal
426
var/host-manager.sqlite-shm
Bogdan Timofte authored 4 days ago
427
```
428

            
429
## Restore
430

            
Bogdan Timofte authored 4 days ago
431
Restore-ul înlocuiește sursa de adevăr runtime:
Bogdan Timofte authored 4 days ago
432

            
433
```bash
434
sudo systemctl stop host-manager
435
sudo cp backups/host-manager/host-manager.sqlite.YYYYMMDD_HHMMSS.bak var/host-manager.sqlite
436
sudo chown host-manager:host-manager var/host-manager.sqlite
437
sudo systemctl start host-manager
438
curl -fsS http://127.0.0.1:8088/healthz >/dev/null
439
```