9.5 KiB
dvmcfggen - Answers File Usage
Overview
The answers file feature allows you to pre-populate wizard prompts using a YAML file. This enables:
- Batch Configuration - Generate multiple configurations with shared defaults
- Automation - Integrate with deployment scripts and CI/CD pipelines
- Reproducibility - Save and reuse configuration templates
- Learning - Understand what each prompt expects
Quick Start
1. Use Example Files
Example answers files are provided in the examples/ directory:
# For conventional systems
dvmcfg wizard -a examples/conventional-answers.yml
# For trunked systems
dvmcfg wizard --type trunk -a examples/trunked-answers.yml
2. Create Your Own
Copy an example file and customize it:
cp examples/conventional-answers.yml my-config-answers.yml
vim my-config-answers.yml
dvmcfg wizard -a my-config-answers.yml
3. Run Without Answers File (Default Behavior)
The answers file is completely optional. The wizard works normally without it:
dvmcfg wizard
Answers File Format
Answers files are YAML format with one key-value pair per configuration option. All fields are optional.
Conventional System Template
# Step 2: Basic Configuration
template: enhanced
config_dir: .
system_identity: MYSITE001
network_peer_id: 100001
# Step 3: Logging Configuration
configure_logging: true
log_path: /var/log/dvm
activity_log_path: /var/log/dvm/activity
log_root: DVM
use_syslog: false
disable_non_auth_logging: false
# Step 4: Modem Configuration
modem_type: uart
modem_mode: air
serial_port: /dev/ttyUSB0
rx_level: 50
tx_level: 50
Trunked System Template
# Step 1: System Configuration
system_name: trunked_test
base_dir: .
identity: TRUNKED001
protocol: p25
vc_count: 2
# Step 2: Logging Configuration
configure_logging: true
log_path: /var/log/dvm
activity_log_path: /var/log/dvm/activity
log_root: TRUNKED
use_syslog: false
disable_non_auth_logging: false
Supported Answer Keys
ConfigWizard (Conventional Systems)
Basic Configuration:
template- Template name (conventional, enhanced)config_dir- Configuration directorysystem_identity- System identity/callsignnetwork_peer_id- Network peer ID (integer)
Logging Configuration:
configure_logging- Enable logging (true/false)log_path- Log file directoryactivity_log_path- Activity log directorylog_root- Log filename prefixuse_syslog- Enable syslog (true/false)disable_non_auth_logging- Disable non-authoritative logging (true/false)
Modem Configuration:
modem_type- Modem type (uart, null)modem_mode- Modem mode (air, dfsi)serial_port- Serial port pathrx_level- RX level (0-100)tx_level- TX level (0-100)
Optional Settings:
rpc_config- Configure RPC (true/false)generate_rpc_password- Generate RPC password (true/false)rest_enable- Enable REST API (true/false)generate_rest_password- Generate REST password (true/false)update_lookups- Update lookups (true/false)save_lookups- Save lookups (true/false)allow_activity_transfer- Allow activity transfer (true/false)allow_diagnostic_transfer- Allow diagnostic transfer (true/false)allow_status_transfer- Allow status transfer (true/false)
Protocol Configuration (for Step 8/9):
dmr_color_code- DMR color code (integer)dmr_network_id- DMR network ID (integer)dmr_site_id- DMR site ID (integer)dmr_site_model- DMR site model (small, tiny, large, huge)p25_nac- P25 NAC code (hex string)p25_network_id- P25 network ID (integer)p25_system_id- P25 system ID (integer)p25_rfss_id- P25 RFSS ID (integer)p25_site_id- P25 site ID (integer)
TrunkingWizard (Trunked Systems)
System Configuration:
system_name- System namebase_dir- Base directoryidentity- System identityprotocol- Protocol (p25, dmr)vc_count- Number of voice channels (integer)
Logging Configuration:
configure_logging- Enable logging (true/false)log_path- Log file directoryactivity_log_path- Activity log directorylog_root- Log filename prefixuse_syslog- Enable syslog (true/false)disable_non_auth_logging- Disable non-authoritative logging (true/false)
Network Settings:
fne_address- FNE addressfne_port- FNE port (integer)fne_password- FNE password
Optional Settings:
base_peer_id- Base peer ID (integer)base_rpc_port- Base RPC port (integer)modem_type- Modem type (uart, null)generate_rpc_password- Generate RPC password (true/false)base_rest_port- Base REST port (integer)rest_enable- Enable REST API (true/false)generate_rest_password- Generate REST password (true/false)
Usage Examples
Example 1: Single Configuration with All Defaults
# hotspot-answers.yml
template: enhanced
config_dir: /etc/dvm/hotspot
system_identity: MY_HOTSPOT
network_peer_id: 100001
configure_logging: true
log_path: /var/log/dvm
log_root: HOTSPOT
modem_type: uart
modem_mode: air
serial_port: /dev/ttyUSB0
Usage:
dvmcfg wizard -a hotspot-answers.yml
Example 2: Trunked System
# trunk-p25-answers.yml
system_name: trunk_p25
base_dir: /etc/dvm/trunk
identity: TRUNK_P25
protocol: p25
vc_count: 4
configure_logging: true
log_path: /var/log/dvm
log_root: TRUNK_P25
p25_nac: 0x293
p25_network_id: 1
p25_system_id: 1
Usage:
dvmcfg wizard --type trunk -a trunk-p25-answers.yml
Example 3: Batch Generation
Create multiple configs programmatically:
#!/bin/bash
for SITE_NUM in {1..5}; do
SITE_ID=$((100000 + SITE_NUM))
SITE_NAME="SITE$(printf '%03d' $SITE_NUM)"
cat > /tmp/site-${SITE_NUM}-answers.yml << EOF
template: enhanced
config_dir: ./site-${SITE_NUM}
system_identity: ${SITE_NAME}
network_peer_id: ${SITE_ID}
configure_logging: true
log_root: ${SITE_NAME}
modem_type: uart
modem_mode: air
EOF
dvmcfg wizard -a /tmp/site-${SITE_NUM}-answers.yml
echo "Generated config for ${SITE_NAME}"
done
Example 4: CI/CD Pipeline
# .github/workflows/generate-test-configs.yml
name: Generate Test Configs
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup Python
uses: actions/setup-python@v2
with:
python-version: '3.9'
- name: Generate conventional config
run: |
python3 dvmhost/tools/dvmcfggen/dvmcfg.py wizard \
-a examples/conventional-answers.yml
- name: Generate trunked config
run: |
python3 dvmhost/tools/dvmcfggen/dvmcfg.py wizard \
--type trunk \
-a examples/trunked-answers.yml
- name: Validate configs
run: |
python3 dvmhost/tools/dvmcfggen/dvmcfg.py validate -c config.yml
Advanced Usage
Partial Answers Files
You only need to specify the fields you want to pre-populate. Missing fields will be prompted for interactively:
# minimal-answers.yml
system_identity: MYSITE
network_peer_id: 100001
# User will be prompted for other values
Saving Generated Answers
After creating a configuration interactively, you can extract the answers:
from answers_loader import AnswersLoader
from pathlib import Path
# After wizard completes
answers = {
'template': 'enhanced',
'system_identity': 'MYSITE001',
'network_peer_id': 100001,
# ... etc
}
AnswersLoader.save_answers(answers, Path('my-site-answers.yml'))
Validation
Answers files are validated automatically, but you can check them manually:
from answers_loader import AnswersLoader
from pathlib import Path
answers = AnswersLoader.load_answers(Path('my-answers.yml'))
# Non-strict validation (warns about unknown keys)
is_valid = AnswersLoader.validate_answers(answers, strict=False)
# Strict validation (fails on unknown keys)
is_valid = AnswersLoader.validate_answers(answers, strict=True)
Key Features
✅ Backward Compatible
- Existing wizard usage works unchanged
- Answers file is completely optional
- No breaking changes
✅ Flexible
- Answer any or all questions
- Interactive prompts for missing answers
- Easy to create custom templates
✅ Easy to Use
- Simple YAML format
- Clear comments in example files
- Error messages for invalid files
✅ Reproducible
- Save and version control answers files
- Generate identical configs across systems
- Document configuration decisions
Troubleshooting
"Unrecognized keys in answers file"
This is a warning (not an error) if your answers file contains unknown keys. It won't stop the wizard from running. To suppress this, ensure you're only using valid keys from the lists above.
"Error loading answers file"
Check that:
- The file path is correct
- The file is valid YAML (use
python3 -c "import yaml; yaml.safe_load(open('file.yml'))" - The file has proper indentation (2 spaces per level)
Answers not being used
Verify that:
- The key name matches exactly (case-sensitive)
- The file is being passed with
-aor--answers-file - The value type is correct (string, integer, boolean)
File Reference
Core Files
answers_loader.py- Utility for loading/validating answerswizard.py- ConfigWizard and TrunkingWizard classes (refactored)dvmcfg.py- CLI interface (updated with--answers-filesupport)
Example Files
examples/conventional-answers.yml- Example for conventional systemsexamples/trunked-answers.yml- Example for trunked systems