- Add Hook interface (filter + execute contract) in server/hooks/hook.h
- Add HookRunner in server/hooks/hook_runner.h: spawns a detached thread
per matching hook, with try/catch protection against crashes
- Add DnsUpdaterHook in server/hooks/dns_updater_hook.{h,cpp}:
triggers on server name changes, logs in to Technitium, deletes the
old A record (ignores 404), and adds the new A record
Config via env vars: TECHNITIUM_HOST/PORT/USER/PASS/ZONE, DNS_TTL
- Add Database::get_nics_for_server() to resolve a server's IPv4 address
- Wire HookRunner into InventoryServer; cmd_edit_server now fires hooks
with before/after Server snapshots
- Update CMakeLists.txt to include dns_updater_hook.cpp
- Document env vars in Dockerfile
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
138 lines
3.5 KiB
Markdown
138 lines
3.5 KiB
Markdown
# device-inventory
|
||
|
||
A lightweight hardware inventory tracker built in C++17.
|
||
Uses a **client/server** model: the server owns the file-backed database and
|
||
exposes a TCP interface on localhost; the CLI client connects to it to run
|
||
commands.
|
||
|
||
---
|
||
|
||
## Architecture
|
||
|
||
```
|
||
┌──────────────┐ TCP (localhost:9876) ┌─────────────────────┐
|
||
│ inventory-cli│ ─────────────────────► │ inventory-server │
|
||
│ (CLI client)│ ◄───────────────────── │ database ► file.db │
|
||
└──────────────┘ └─────────────────────┘
|
||
```
|
||
|
||
* **inventory-server** – loads the inventory file on start, accepts one
|
||
command per connection, and flushes changes to disk after every mutation.
|
||
* **inventory-cli** – a thin CLI that translates subcommands into protocol
|
||
messages, connects to the server, and pretty-prints the response.
|
||
|
||
---
|
||
|
||
## Build
|
||
|
||
Requires CMake ≥ 3.16 and a C++17-capable compiler.
|
||
|
||
```bash
|
||
cd device-inventory
|
||
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
|
||
cmake --build build
|
||
```
|
||
|
||
Binaries end up in `build/inventory-server` and `build/inventory-cli`.
|
||
|
||
---
|
||
|
||
## Running
|
||
|
||
### Start the server
|
||
|
||
```bash
|
||
./build/inventory-server # uses inventory.db in CWD
|
||
./build/inventory-server --port 9876 --db /var/lib/inventory/data.db
|
||
```
|
||
|
||
The server reloads the file every time it restarts. On the very first run the
|
||
file is created automatically.
|
||
|
||
### Use the CLI
|
||
|
||
```bash
|
||
# Shorthand for the examples below
|
||
cli="./build/inventory-cli"
|
||
```
|
||
|
||
---
|
||
|
||
## Commands
|
||
|
||
### Servers
|
||
|
||
```bash
|
||
# Add a server
|
||
$cli add-server "web01" "192.168.1.10" "Rack A" "Primary web server"
|
||
|
||
# List all servers
|
||
$cli list-servers
|
||
|
||
# Edit a field (fields: name | hostname | location | description)
|
||
$cli edit-server 1 hostname "10.0.0.1"
|
||
$cli edit-server 1 description "Retired – do not use"
|
||
```
|
||
|
||
### Part types
|
||
|
||
```bash
|
||
# Add a part type
|
||
$cli add-part-type "RAM" "Memory modules"
|
||
$cli add-part-type "SSD" "Solid-state storage"
|
||
|
||
# List all part types
|
||
$cli list-part-types
|
||
|
||
# Edit a field (fields: name | description)
|
||
$cli edit-part-type 1 description "DDR4/DDR5 memory"
|
||
```
|
||
|
||
### Parts
|
||
|
||
```bash
|
||
# Add a part to a server
|
||
# add-part <server_id> <part_type_id> <name> <serial> <description>
|
||
$cli add-part 1 1 "16 GB DDR4" "SN-MEM-001" "DIMM slot A1"
|
||
$cli add-part 1 2 "Samsung 870 EVO 1 TB" "SN-SSD-004" "Primary OS drive"
|
||
|
||
# List parts of a server
|
||
$cli list-parts 1
|
||
|
||
# Edit a field (fields: name | serial | description | server_id | part_type_id)
|
||
$cli edit-part 2 serial "SN-SSD-005"
|
||
$cli edit-part 2 server_id 3
|
||
```
|
||
|
||
---
|
||
|
||
## Database file format
|
||
|
||
Plain text, one record per line – safe to inspect or diff with standard tools.
|
||
|
||
```
|
||
# device-inventory database
|
||
META|<next_server_id>|<next_part_type_id>|<next_part_id>
|
||
S|<id>|<name>|<hostname>|<location>|<description>
|
||
PT|<id>|<name>|<description>
|
||
P|<id>|<server_id>|<part_type_id>|<name>|<serial>|<description>
|
||
```
|
||
|
||
Pipe characters and backslashes inside field values are escaped with `\|`
|
||
and `\\` respectively.
|
||
|
||
---
|
||
|
||
## Wire protocol
|
||
|
||
Commands are newline-terminated lines; fields are separated by ASCII SOH
|
||
(`0x01`). Each connection carries exactly one request/response pair.
|
||
|
||
```
|
||
Client → Server: COMMAND\x01arg1\x01arg2\n
|
||
Server → Client: OK\n
|
||
field1\x01field2\x01...\n ← 0 or more data rows
|
||
END\n
|
||
-- or --
|
||
ERR <message>\n
|
||
```
|