2021-07-08 19:10:14 +00:00
import re
import sys
import json
import ipaddress
from datetime import datetime , timedelta
2021-07-09 19:13:28 +00:00
from flask import Blueprint , current_app , render_template , make_response
2021-07-08 19:10:14 +00:00
from werkzeug . exceptions import abort
2021-07-09 19:13:28 +00:00
from nanoid import generate
2021-07-08 19:10:14 +00:00
from capsulflask . metrics import durations as metric_durations
from capsulflask . auth import admin_account_required
from capsulflask . db import get_model
from capsulflask . shared import my_exec_info_message
bp = Blueprint ( " admin " , __name__ , url_prefix = " /admin " )
@bp.route ( " / " )
@admin_account_required
def index ( ) :
2021-12-05 22:47:37 +00:00
# first create the hosts list w/ ip allocation visualization
#
2021-07-09 22:08:38 +00:00
hosts = get_model ( ) . list_hosts_with_networks ( None )
vms_by_host_and_network = get_model ( ) . non_deleted_vms_by_host_and_network ( None )
2021-07-12 17:27:07 +00:00
network_display_width_px = float ( 270 )
2021-07-09 19:13:28 +00:00
#operations = get_model().list_all_operations()
2021-07-08 19:10:14 +00:00
display_hosts = [ ]
2021-07-09 19:13:28 +00:00
inline_styles = [ f """
. network - display { ' { ' }
width : { network_display_width_px } px ;
{ ' } ' }
""" ]
2021-07-08 19:10:14 +00:00
2021-12-05 22:50:55 +00:00
vm_by_id = dict ( )
2021-12-05 22:47:37 +00:00
2021-07-08 19:10:14 +00:00
for kv in hosts . items ( ) :
2021-07-09 19:13:28 +00:00
host_id = kv [ 0 ]
2021-07-08 19:10:14 +00:00
value = kv [ 1 ]
2021-07-09 19:13:28 +00:00
display_host = dict ( name = host_id , networks = value [ ' networks ' ] )
2021-07-08 19:10:14 +00:00
2021-07-09 19:13:28 +00:00
for network in display_host [ ' networks ' ] :
2021-07-12 16:29:33 +00:00
2021-07-12 19:38:56 +00:00
network_start_int = int ( ipaddress . ip_address ( network [ " public_ipv4_first_usable_ip " ] ) )
network_end_int = int ( ipaddress . ip_address ( network [ " public_ipv4_last_usable_ip " ] ) )
2021-07-12 16:29:33 +00:00
2021-07-09 19:13:28 +00:00
network [ ' allocations ' ] = [ ]
2021-07-12 17:27:07 +00:00
network_addresses_width = float ( ( network_end_int - network_start_int ) + 1 )
2021-07-09 19:13:28 +00:00
if host_id in vms_by_host_and_network :
if network [ ' network_name ' ] in vms_by_host_and_network [ host_id ] :
for vm in vms_by_host_and_network [ host_id ] [ network [ ' network_name ' ] ] :
2021-12-05 22:50:55 +00:00
vm [ ' network_name ' ] = network [ ' network_name ' ]
vm [ ' virtual_bridge_name ' ] = network [ ' virtual_bridge_name ' ]
vm [ ' host ' ] = host_id
vm_by_id [ vm [ ' id ' ] ] = vm
2021-07-09 19:13:28 +00:00
ip_address_int = int ( ipaddress . ip_address ( vm [ ' public_ipv4 ' ] ) )
2021-07-11 17:18:58 +00:00
if network_start_int < = ip_address_int and ip_address_int < = network_end_int :
2021-07-09 19:13:28 +00:00
allocation = f " { host_id } _ { network [ ' network_name ' ] } _ { len ( network [ ' allocations ' ] ) } "
inline_styles . append (
f """
. { allocation } { ' { ' }
left : { ( float ( ip_address_int - network_start_int ) / network_addresses_width ) * network_display_width_px } px ;
width : { network_display_width_px / network_addresses_width } px ;
{ ' } ' }
"""
)
network [ ' allocations ' ] . append ( allocation )
else :
current_app . logger . warning ( f " /admin: capsul { vm [ ' id ' ] } has public_ipv4 { vm [ ' public_ipv4 ' ] } which is out of range for its host network { host_id } { network [ ' network_name ' ] } { network [ ' public_ipv4_cidr_block ' ] } " )
display_hosts . append ( display_host )
2021-12-05 22:47:37 +00:00
# Now creating the capsuls running status ui
#
db_vms = get_model ( ) . all_vm_ids_with_desired_state ( )
2021-12-05 22:50:55 +00:00
# TODO will be replaced
#virt_vms = current_app.config["HUB_MODEL"].virsh_list()
2021-12-05 22:47:37 +00:00
virt_vms_dict = dict ( )
for vm in virt_vms :
virt_vms_dict [ vm [ " id " ] ] = vm [ " state " ]
in_db_but_not_in_virt = [ ]
needs_to_be_started = [ ]
needs_to_be_started_missing_ipv4 = [ ]
for vm in db_vms :
if vm [ " id " ] not in virt_vms_dict :
in_db_but_not_in_virt . append ( vm [ " id " ] )
elif vm [ " desired_state " ] == " running " and virt_vms_dict [ vm [ " id " ] ] != " running " :
2021-12-05 22:50:55 +00:00
if vm [ " id " ] in vm_by_id :
needs_to_be_started . append ( vm_by_id [ vm [ " id " ] ] )
2021-12-05 22:47:37 +00:00
else :
needs_to_be_started_missing_ipv4 . append ( vm [ " id " ] )
2021-12-05 22:50:55 +00:00
elif vm [ " ipv4 " ] != current_ipv4
2021-12-05 22:47:37 +00:00
2021-07-09 19:13:28 +00:00
csp_inline_style_nonce = generate ( alphabet = " 1234567890qwertyuiopasdfghjklzxcvbnm " , size = 10 )
response_text = render_template (
" admin.html " ,
display_hosts = display_hosts ,
2021-12-05 22:47:37 +00:00
in_db_but_not_in_virt = in_db_but_not_in_virt ,
needs_to_be_started = needs_to_be_started ,
needs_to_be_started_missing_ipv4 = needs_to_be_started_missing_ipv4 ,
2021-07-09 19:13:28 +00:00
network_display_width_px = network_display_width_px ,
csp_inline_style_nonce = csp_inline_style_nonce ,
inline_style = ' \n ' . join ( inline_styles )
)
response = make_response ( response_text )
2021-07-08 19:10:14 +00:00
2021-07-09 19:13:28 +00:00
response . headers . set ( ' Content-Type ' , ' text/html ' )
response . headers . set ( ' Content-Security-Policy ' , f " default-src ' self ' ; style-src ' self ' ' nonce- { csp_inline_style_nonce } ' " )
2021-07-08 19:10:14 +00:00
2021-07-09 19:13:28 +00:00
return response