# Fenris Makefile # Spec: §10.1-10.6 SHELL := /bin/bash PYTHON := python3 VENV_DIR := /opt/fenris BIN_DIR := /usr/local/bin LIBEXEC_DIR := /usr/libexec/fenris UNIT_DIR := /etc/systemd/system POLKIT_DIR := /usr/share/polkit-1/actions CONF_DIR := /etc/fenris DATA_DIR := /var/lib/fenris # Placement manifest MANIFEST := manifest.txt .PHONY: help install upgrade uninstall purge update-deps test lint help: @echo "Fenris NVMe endurance monitor" @echo "" @echo "Targets:" @echo " install - Install Fenris (builds wheel, installs to /opt/fenris)" @echo " upgrade - Upgrade Fenris (reinstall wheel, sync units)" @echo " uninstall - Uninstall Fenris (preserves config and store)" @echo " purge - Remove everything including config and store" @echo " test - Run tests" @echo " lint - Run linter" @echo " update-deps - Update dependency pins" # ─── Build ────────────────────────────────────────────────────────────────── dist/fenris-*.whl: pyproject.toml src/fenris/*.py @mkdir -p dist $(PYTHON) -m build --wheel -o dist # ─── Install ──────────────────────────────────────────────────────────────── install: dist/fenris-*.whl @echo "=== Verifying prerequisites ===" @$(PYTHON) --version 2>/dev/null || (echo "Error: python3 not found"; exit 1) @smartctl --version 2>/dev/null | head -1 || (echo "Error: smartctl not found"; exit 1) @echo "=== Creating directories ===" @sudo mkdir -p $(LIBEXEC_DIR) @sudo mkdir -p $(CONF_DIR) @sudo mkdir -p $(DATA_DIR) @sudo mkdir -p $(POLKIT_DIR) @echo "=== Creating data directory ===" @sudo install -d -o root -g fenris -m 2750 $(DATA_DIR) 2>/dev/null || sudo groupadd -f fenris && sudo install -d -o root -g fenris -m 2750 $(DATA_DIR) @echo "=== Installing venv ===" @sudo rm -rf $(VENV_DIR) @sudo $(PYTHON) -m venv $(VENV_DIR) @sudo $(VENV_DIR)/bin/pip install --upgrade pip @sudo $(VENV_DIR)/bin/pip install dist/fenris-*.whl @echo "=== Installing wrapper ===" @sudo install -m 0755 scripts/fenris $(BIN_DIR)/fenris @echo "=== Installing helpers ===" @sudo install -m 0755 src/fenris/monitor.py $(LIBEXEC_DIR)/fenris-monitor @sudo install -m 0755 src/fenris/collect.py $(LIBEXEC_DIR)/fenris-collect @echo "=== Installing systemd units ===" @sudo install -m 0644 units/fenris-collect.timer $(UNIT_DIR)/ @sudo install -m 0644 units/fenris-collect.service $(UNIT_DIR)/ @sudo systemctl daemon-reload @echo "=== Installing polkit policy ===" @sudo install -m 0644 polkit/com.bongbetic.fenris.monitor.policy $(POLKIT_DIR)/ @echo "=== Creating manifest ===" @echo "# Fenris placement manifest - do not edit" > $(MANIFEST) @echo "# Generated by install target" >> $(MANIFEST) @echo "$(BIN_DIR)/fenris" >> $(MANIFEST) @echo "$(LIBEXEC_DIR)/fenris-monitor" >> $(MANIFEST) @echo "$(LIBEXEC_DIR)/fenris-collect" >> $(MANIFEST) @echo "$(UNIT_DIR)/fenris-collect.timer" >> $(MANIFEST) @echo "$(UNIT_DIR)/fenris-collect.service" >> $(MANIFEST) @echo "$(POLKIT_DIR)/com.bongbetic.fenris.monitor.policy" >> $(MANIFEST) @echo "$(VENV_DIR)" >> $(MANIFEST) @echo "$(DATA_DIR)" >> $(MANIFEST) @echo "=== Install complete ===" @echo "Units installed but NOT enabled or started." @echo "To start monitoring: fenris monitor resume" # ─── Upgrade ──────────────────────────────────────────────────────────────── upgrade: dist/fenris-*.whl @echo "=== Upgrading Fenris ===" @echo "=== Installing new wheel ===" @sudo $(VENV_DIR)/bin/pip install dist/fenris-*.whl @echo "=== Syncing units ===" @sudo install -m 0644 units/fenris-collect.timer $(UNIT_DIR)/ @sudo install -m 0644 units/fenris-collect.service $(UNIT_DIR)/ @sudo install -m 0644 polkit/com.bongbetic.fenris.monitor.policy $(POLKIT_DIR)/ @sudo install -m 0755 scripts/fenris $(BIN_DIR)/fenris @sudo install -m 0755 src/fenris/monitor.py $(LIBEXEC_DIR)/fenris-monitor @sudo install -m 0755 src/fenris/collect.py $(LIBEXEC_DIR)/fenris-collect @sudo systemctl daemon-reload # Restart timer only if active and contents changed @if systemctl is-active --quiet fenris-collect.timer; then echo "=== Restarting timer (active) ==="; sudo systemctl restart fenris-collect.timer; fi @echo "=== Upgrade complete ===" # ─── Uninstall ────────────────────────────────────────────────────────────── uninstall: @echo "=== Uninstalling Fenris ===" # Sanctioned disable first (§10.4) @if [ -x $(LIBEXEC_DIR)/fenris-monitor ]; then echo "=== Performing sanctioned disable ==="; sudo $(LIBEXEC_DIR)/fenris-monitor disable --now || true; fi # Stop and disable units @echo "=== Stopping units ===" @sudo systemctl stop fenris-collect.timer 2>/dev/null || true @sudo systemctl disable fenris-collect.timer 2>/dev/null || true @sudo systemctl daemon-reload # Remove installed files (preserving /etc/fenris and /var/lib/fenris) @echo "=== Removing files ===" @-rm -f $(BIN_DIR)/fenris @-rm -f $(LIBEXEC_DIR)/fenris-monitor @-rm -f $(LIBEXEC_DIR)/fenris-collect @-rmdir $(LIBEXEC_DIR) 2>/dev/null || true @-rm -f $(UNIT_DIR)/fenris-collect.timer @-rm -f $(UNIT_DIR)/fenris-collect.service @-rm -f $(POLKIT_DIR)/com.bongbetic.fenris.monitor.policy @sudo rm -rf $(VENV_DIR) @-rm -f $(MANIFEST) @echo "=== Uninstall complete ===" @echo "Config preserved at $(CONF_DIR)" @echo "Store preserved at $(DATA_DIR)" # ─── Purge ────────────────────────────────────────────────────────────────── purge: uninstall @echo "=== Purging Fenris ===" @-sudo rm -rf $(CONF_DIR) @-sudo rm -rf $(DATA_DIR) @echo "=== Purge complete ===" # ─── Test ─────────────────────────────────────────────────────────────────── test: $(PYTHON) -m pytest tests/ -v # ─── Lint ─────────────────────────────────────────────────────────────────── lint: $(PYTHON) -m ruff check src/ tests/ # ─── Dependencies ─────────────────────────────────────────────────────────── update-deps: $(PYTHON) -m pip compile pyproject.toml -o requirements.txt