145 lines
No EOL
4.5 KiB
Python
145 lines
No EOL
4.5 KiB
Python
from flask import Blueprint, render_template, redirect, url_for, request, flash, jsonify
|
|
from flask_login import login_required
|
|
from app.core.models import Subnet, Server
|
|
from app.core.extensions import db
|
|
from app.scripts.ip_scanner import scan
|
|
import ipaddress
|
|
from datetime import datetime
|
|
|
|
bp = Blueprint('ipam', __name__, url_prefix='/ipam')
|
|
|
|
@bp.route('/')
|
|
@login_required
|
|
def ipam_home():
|
|
"""Main IPAM dashboard"""
|
|
subnets = Subnet.query.all()
|
|
|
|
# Calculate usage for each subnet
|
|
for subnet in subnets:
|
|
subnet.usage_percent = subnet.used_ips / 254 * 100 if subnet.cidr.endswith('/24') else 0
|
|
|
|
return render_template(
|
|
'ipam/index.html',
|
|
title='IPAM Dashboard',
|
|
subnets=subnets,
|
|
now=datetime.now()
|
|
)
|
|
|
|
@bp.route('/subnet/new', methods=['GET', 'POST'])
|
|
@login_required
|
|
def subnet_new():
|
|
"""Create a new subnet"""
|
|
if request.method == 'POST':
|
|
cidr = request.form.get('cidr')
|
|
location = request.form.get('location')
|
|
auto_scan = 'auto_scan' in request.form
|
|
|
|
# Basic validation
|
|
if not cidr or not location:
|
|
flash('Please fill in all required fields', 'danger')
|
|
return render_template(
|
|
'ipam/subnet_form.html',
|
|
title='New Subnet',
|
|
now=datetime.now()
|
|
)
|
|
|
|
# Check if valid CIDR
|
|
try:
|
|
ipaddress.ip_network(cidr)
|
|
except ValueError:
|
|
flash('Invalid CIDR notation', 'danger')
|
|
return render_template(
|
|
'ipam/subnet_form.html',
|
|
title='New Subnet',
|
|
now=datetime.now()
|
|
)
|
|
|
|
# Check if subnet already exists
|
|
if Subnet.query.filter_by(cidr=cidr).first():
|
|
flash('Subnet already exists', 'danger')
|
|
return render_template(
|
|
'ipam/subnet_form.html',
|
|
title='New Subnet',
|
|
now=datetime.now()
|
|
)
|
|
|
|
subnet = Subnet(
|
|
cidr=cidr,
|
|
location=location,
|
|
auto_scan=auto_scan
|
|
)
|
|
db.session.add(subnet)
|
|
db.session.commit()
|
|
|
|
flash('Subnet created successfully', 'success')
|
|
return redirect(url_for('ipam.subnet_view', subnet_id=subnet.id))
|
|
|
|
return render_template(
|
|
'ipam/subnet_form.html',
|
|
title='New Subnet',
|
|
now=datetime.now()
|
|
)
|
|
|
|
@bp.route('/subnet/<int:subnet_id>')
|
|
@login_required
|
|
def subnet_view(subnet_id):
|
|
"""View subnet details"""
|
|
subnet = Subnet.query.get_or_404(subnet_id)
|
|
servers = Server.query.filter_by(subnet_id=subnet_id).all()
|
|
|
|
# Get network info
|
|
network = ipaddress.ip_network(subnet.cidr)
|
|
total_ips = network.num_addresses - 2 # Excluding network and broadcast addresses
|
|
used_ips = len(servers)
|
|
usage_percent = (used_ips / total_ips) * 100 if total_ips > 0 else 0
|
|
|
|
return render_template(
|
|
'ipam/subnet_view.html',
|
|
title=f'Subnet - {subnet.cidr}',
|
|
subnet=subnet,
|
|
servers=servers,
|
|
total_ips=total_ips,
|
|
used_ips=used_ips,
|
|
usage_percent=usage_percent,
|
|
now=datetime.now()
|
|
)
|
|
|
|
@bp.route('/subnet/<int:subnet_id>/scan')
|
|
@login_required
|
|
def subnet_scan(subnet_id):
|
|
"""Scan a subnet for active hosts"""
|
|
subnet = Subnet.query.get_or_404(subnet_id)
|
|
|
|
try:
|
|
results = scan(subnet.cidr, save_results=True)
|
|
flash(f'Scan completed for subnet {subnet.cidr}. Found {len(results)} active hosts.', 'success')
|
|
except Exception as e:
|
|
flash(f'Error scanning subnet: {e}', 'danger')
|
|
|
|
return redirect(url_for('ipam.subnet_view', subnet_id=subnet_id))
|
|
|
|
@bp.route('/subnet/<int:subnet_id>/visualize')
|
|
@login_required
|
|
def subnet_visualize(subnet_id):
|
|
"""Visualize IP usage in a subnet"""
|
|
subnet = Subnet.query.get_or_404(subnet_id)
|
|
servers = Server.query.filter_by(subnet_id=subnet_id).all()
|
|
|
|
# Create a dictionary of used IPs
|
|
used_ips = {server.ip_address: server.hostname for server in servers}
|
|
|
|
# Get network info
|
|
network = ipaddress.ip_network(subnet.cidr)
|
|
total_ips = network.num_addresses - 2 # Excluding network and broadcast addresses
|
|
used_ip_count = len(servers)
|
|
|
|
return render_template(
|
|
'ipam/subnet_visualization.html',
|
|
title=f'Subnet Visualization - {subnet.cidr}',
|
|
subnet=subnet,
|
|
network=network,
|
|
used_ips=used_ips,
|
|
total_ips=total_ips,
|
|
used_ip_count=used_ip_count,
|
|
now=datetime.now()
|
|
) |