Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • infrastruktur/ansible-warpzone
  • specki/ansible-warpzone
2 results
Show changes
Commits on Source (4)
Showing with 278 additions and 28 deletions
---
- include_tasks: ../functions/get_secret.yml
with_items:
- { path: "/etc/kea/kea_ddns_key", length: 44 }
- name: "Create new zonefile serial"
set_fact:
zonefile_serial: "{{ ansible_date_time.date | replace('-', '') }}01"
- name: "Instaliere debian Pakete"
apt:
update_cache: yes
state: present
name:
- bind9
- name: "Set owner for bind config directory"
file:
path: "/etc/bind"
state: directory
owner: "bind"
group: "bind"
- name: "Copy Service Config Files"
template:
src: "{{ item }}"
dest: "/etc/bind/{{ item }}"
with_items:
- db.warpzone.lan
- named.conf.local
- named.conf.options
- name: enable and restart named.service
systemd:
name: "named.service"
state: restarted
enabled: True
apispec==6.8.2
blinker==1.9.0
certifi==2025.6.15
charset-normalizer==3.4.2
click==8.2.1
Flask==3.1.1
flask-apispec==0.11.4
flask-swagger-ui==5.21.0
idna==3.10
itsdangerous==2.2.0
Jinja2==3.1.6
MarkupSafe==3.0.2
marshmallow==3.26.1
packaging==25.0
requests==2.32.4
urllib3==2.5.0
webargs==8.7.0
Werkzeug==3.1.3
---
- include_tasks: ../functions/get_secret.yml
with_items:
- { path: "/etc/kea/kea_api_password", length: 22 }
- name: "Instaliere debian Pakete"
apt:
update_cache: yes
state: present
name:
- python3
- python3-pip
- python3-virtualenv
- name: "Create dhcpinfo directories"
file:
path: "{{ item }}"
state: directory
with_items:
- "{{ basedir }}"
- "{{ basedir }}/templates"
- "{{ basedir }}/venv"
- name: "copy dhcpinfo files"
template:
src: "{{ item }}"
dest: "{{ basedir }}/{{ item }}"
with_items:
- app.py
- requirements.txt
- templates/leases.html
- name: Installiere Python-Pakete in venv
pip:
requirements: "{{ basedir }}/requirements.txt"
virtualenv: "{{ basedir }}/venv"
- name: "Create Systemd Unit File"
template:
src: "{{ item }}"
dest: "/etc/systemd/system/{{ item }}"
with_items:
- dhcpinfo.service
- name: "Enable and Restart Systemd Service"
systemd:
name: "dhcpinfo.service"
state: restarted
enabled: True
daemon_reload: yes
......@@ -6,6 +6,11 @@ import logging
import os
from requests.auth import HTTPBasicAuth
import sys
from marshmallow import Schema, fields
from flask_apispec import FlaskApiSpec, marshal_with, doc
from apispec import APISpec
from apispec.ext.marshmallow import MarshmallowPlugin
from flask_swagger_ui import get_swaggerui_blueprint
# Flask App Setup
app = Flask(__name__)
......@@ -29,6 +34,25 @@ WEB_DEBUG = True
# Auto-Refresh Intervall in Sekunden (0 = kein Auto-Refresh)
AUTO_REFRESH = 30
# Marshmallow-Schemas (nur einmal definiert, werden überall verwendet)
class LeaseSchema(Schema):
ip_address = fields.Str(data_key='ip-address')
hw_address = fields.Str(data_key='hw-address')
hostname = fields.Str()
state = fields.Int()
cltt = fields.Int()
valid_lft = fields.Int()
subnet_id = fields.Int(data_key='subnet-id')
class StatusSchema(Schema):
connected = fields.Bool()
message = fields.Str()
url = fields.Str()
service = fields.Str()
username = fields.Str()
timestamp = fields.Str()
class KeaDHCPClient:
def __init__(self, url, service, username=None, password=None):
self.url = url
......@@ -149,10 +173,10 @@ def index():
connection_ok, connection_message = kea_client.test_connection()
if not connection_ok:
return render_template('leases.html',
leases=[],
error=f"Verbindungsfehler: {connection_message}",
connection_status="Fehler",
last_update=datetime.now().strftime('%d.%m.%Y %H:%M:%S'))
leases=[],
error=f"Verbindungsfehler: {connection_message}",
connection_status="Fehler",
last_update=datetime.now().strftime('%d.%m.%Y %H:%M:%S'))
# Leases abrufen
lease_response = kea_client.get_all_leases()
......@@ -194,15 +218,17 @@ def index():
server_info = info_response[0].get("arguments", {})
return render_template('leases.html',
leases=leases,
error=error_message,
statistics=statistics,
server_info=server_info,
total_leases=len(leases),
connection_status="Verbunden",
auto_refresh=AUTO_REFRESH,
last_update=datetime.now().strftime('%d.%m.%Y %H:%M:%S'))
leases=leases,
error=error_message,
statistics=statistics,
server_info=server_info,
total_leases=len(leases),
connection_status="Verbunden",
auto_refresh=AUTO_REFRESH,
last_update=datetime.now().strftime('%d.%m.%Y %H:%M:%S'))
@doc(description='Liste aller DHCP-Leases', tags=['leases'])
@marshal_with(LeaseSchema(many=True))
@app.route('/api/leases')
def api_leases():
"""JSON API für Leases"""
......@@ -211,32 +237,83 @@ def api_leases():
if lease_response and lease_response[0].get("result") == 0:
lease_data = lease_response[0].get("arguments", {})
return jsonify(lease_data.get("leases", []))
return lease_data.get("leases", [])
else:
return jsonify({"error": "Fehler beim Abrufen der Leases"}), 500
return {"error": "Fehler beim Abrufen der Leases"}, 500
@doc(description='Status und Verbindung zur Kea API', tags=['status'])
@marshal_with(StatusSchema)
@app.route('/api/status')
def api_status():
"""API-Endpunkt für Verbindungsstatus"""
kea_client = KeaDHCPClient(KEA_CONTROL_AGENT_URL, KEA_SERVICE, KEA_USERNAME, KEA_PASSWORD)
connection_ok, message = kea_client.test_connection()
return jsonify({
return {
"connected": connection_ok,
"message": message,
"url": KEA_CONTROL_AGENT_URL,
"service": KEA_SERVICE,
"username": KEA_USERNAME,
"timestamp": datetime.now().isoformat()
})
}
@app.route('/metrics')
def metrics():
"""Prometheus Metrics Endpoint für Kea Statistiken"""
kea_client = KeaDHCPClient(KEA_CONTROL_AGENT_URL, KEA_SERVICE, KEA_USERNAME, KEA_PASSWORD)
stats_response = kea_client.get_statistics()
output = []
connection_ok, _ = kea_client.test_connection()
output.append(f"kea_connection_ok {1 if connection_ok else 0}")
# Lease-Anzahl ermitteln
lease_response = kea_client.get_all_leases()
total_leases = 0
if lease_response and lease_response[0].get("result") == 0:
lease_data = lease_response[0].get("arguments", {})
total_leases = len(lease_data.get("leases", []))
output.append(f"kea_total_leases {total_leases}")
if stats_response and stats_response[0].get("result") == 0:
stats_data = stats_response[0].get("arguments", {})
for stat_name, stat_values in stats_data.items():
if isinstance(stat_values, list) and len(stat_values) > 0:
value = stat_values[0][0]
prom_name = stat_name.lower().replace('.', '_').replace('-', '_').replace('[', '_').replace(']', '')
output.append(f"kea_{prom_name} {value}")
return '\n'.join(output) + '\n', 200, {'Content-Type': 'text/plain; version=0.0.4; charset=utf-8'}
# OpenAPI/Swagger-Konfiguration
app.config.update({
'APISPEC_SPEC': APISpec(
title='Warpzone DHCP API',
version='1.0.0',
openapi_version='3.0.2',
plugins=[MarshmallowPlugin()],
),
'APISPEC_SWAGGER_URL': '/swagger.yaml',
})
docs = FlaskApiSpec(app)
docs.register(api_leases)
docs.register(api_status)
swaggerui_blueprint = get_swaggerui_blueprint(
'/swagger',
'/swagger.yaml',
config={'app_name': "Warpzone DHCP API"}
)
app.register_blueprint(swaggerui_blueprint, url_prefix='/swagger')
if __name__ == '__main__':
# Konfiguration ausgeben (ohne Passwort)
print(f"🚀 Starte Kea DHCP Web Interface")
print(f"🐞 Debug-Modus: {WEB_DEBUG}")
print(f"📡 Kea Control Agent URL: {KEA_CONTROL_AGENT_URL}")
print(f"🔧 Kea Service: {KEA_SERVICE}")
print(f"👤 Benutzername: {KEA_USERNAME}")
print(f"🔒 Passwort: {'*' * len(KEA_PASSWORD) if KEA_PASSWORD else 'NICHT GESETZT'}")
print(f"🔄 Auto-Refresh: {AUTO_REFRESH} Sekunden")
print(f"🌐 Web Interface: http://{WEB_HOST}:{WEB_PORT}")
print(f"📄 Swagger UI: http://{WEB_HOST}:{WEB_PORT}/swagger")
app.run(debug=WEB_DEBUG, host=WEB_HOST, port=WEB_PORT)
......@@ -10,7 +10,7 @@ Type=simple
User=root
Group=root
WorkingDirectory=/srv/dhcpinfo
ExecStart=/usr/bin/python3 /srv/dhcpinfo/app.py
ExecStart={{ basedir }}/venv/bin/python /srv/dhcpinfo/app.py
ExecReload=/bin/kill -HUP $MAINPID
Restart=always
RestartSec=10
......
......@@ -298,8 +298,11 @@
</span>
</div>
<div class="connection-info">
<span>🔄 Auto-Refresh: {{ auto_refresh }} Sekunden</span>
<span>🕐 Letztes Update: {{ last_update }}</span>
<span>🔄 Auto-Refresh: {{ auto_refresh }} Sekunden</span>
<span>
<a href="/swagger/" target="_blank" style="color:#007bff;text-decoration:underline;">🧩 Swagger API</a>
</span>
</div>
</div>
......
......@@ -6,68 +6,22 @@
- { path: "/etc/kea/kea_ddns_key", length: 44 }
- name: pakete installieren
- name: "Instaliere debian Pakete"
apt:
update_cache: yes
state: present
name:
- bind9
- isc-kea
- python3
- python3-flask
- python3-requests
- name: Generate zonefile serial
set_fact:
zonefile_serial: "{{ ansible_date_time.date | replace('-', '') }}01"
- name: Set owner for bind config directory
file:
path: "/etc/bind"
state: directory
owner: "bind"
group: "bind"
- name: "copy config files"
- name: "Copy Service Config Files"
template:
src: "{{ item }}"
dest: "/etc/{{ item }}"
with_items:
- bind/db.warpzone.lan
- bind/named.conf.local
- bind/named.conf.options
- kea/kea-ctrl-agent.conf
- kea/kea-dhcp-ddns.conf
- kea/kea-dhcp4.conf
- systemd/system/dhcpinfo.service
- name: Ensure dhcpinfo directories exist
file:
path: "{{ item }}"
state: directory
with_items:
- "/srv/dhcpinfo"
- "/srv/dhcpinfo/templates"
- name: "copy dhcpinfo files"
template:
src: "dhcpinfo/{{ item }}"
dest: "/srv/dhcpinfo/{{ item }}"
dest: "/etc/kea/{{ item }}"
with_items:
- app.py
- templates/leases.html
- name: enable and restart named.service
systemd:
name: "named.service"
state: restarted
enabled: True
- kea-ctrl-agent.conf
- kea-dhcp-ddns.conf
- kea-dhcp4.conf
- name: enable and restart isc-kea-dhcp-ddns-server.service
......@@ -97,10 +51,3 @@
state: restarted
enabled: True
- name: enable and restart dhcpinfo.service
systemd:
name: "dhcpinfo.service"
state: restarted
enabled: True
daemon_reload: yes
......@@ -254,18 +254,16 @@
remote_user: root
roles:
- { role: common/cronapt, tags: cronapt }
# - { role: common/docker, tags: docker }
- { role: common/prometheus-node, tags: prometheus-node }
# - {
# role: common/docker_dockerstats, tags: [ dockerstats, docker_services ],
# servicename: dockerstats,
# basedir: /srv/dockerstats,
# metrics_port: 9487
# }
- {
role: intern/dhcpdns, tags: dhcpdns,
servicename: dhcpdns,
domain: "dhcpdns.warpzone.lan"
role: dhcpdns/kea, tags: kea
}
- {
role: dhcpdns/bind, tags: bind
}
- {
role: dhcpdns/dhcpinfo, tags: dhcpinfo,
basedir: /srv/dhcpinfo
}
- hosts: webserver
......