start working on managed IPs
This commit is contained in:
parent
1e19902df1
commit
e685c8a773
57
capsulflask/admin.py
Normal file
57
capsulflask/admin.py
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
import re
|
||||||
|
import sys
|
||||||
|
import json
|
||||||
|
import ipaddress
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
from flask import Blueprint
|
||||||
|
from flask import flash
|
||||||
|
from flask import current_app
|
||||||
|
from flask import g
|
||||||
|
from flask import request
|
||||||
|
from flask import session
|
||||||
|
from flask import render_template
|
||||||
|
from flask import redirect
|
||||||
|
from flask import url_for
|
||||||
|
from werkzeug.exceptions import abort
|
||||||
|
|
||||||
|
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():
|
||||||
|
hosts = get_model().list_hosts_with_networks()
|
||||||
|
vms = get_model().all_non_deleted_vms()
|
||||||
|
operations = get_model().list_all_operations()
|
||||||
|
|
||||||
|
display_hosts = []
|
||||||
|
|
||||||
|
for kv in hosts.items():
|
||||||
|
name = kv[0]
|
||||||
|
value = kv[1]
|
||||||
|
|
||||||
|
for network in value['networks']:
|
||||||
|
network["network_name"]
|
||||||
|
|
||||||
|
ipv4_network = ipaddress.ip_network(network["public_ipv4_cidr_block"], False)
|
||||||
|
network_start_int = -1
|
||||||
|
network_end_int = -1
|
||||||
|
i = 0
|
||||||
|
for ipv4_address in ipv4_network:
|
||||||
|
i += 1
|
||||||
|
if i > 2:
|
||||||
|
if network_start_int == -1:
|
||||||
|
network_start_int = int(ipv4_address)
|
||||||
|
|
||||||
|
network_end_int = int(ipv4_address)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
display_hosts.append(dict(name=name, last_health_check=value['last_health_check']))
|
||||||
|
|
||||||
|
|
||||||
|
return render_template("admin.html", vms=mappedVms, has_vms=len(vms) > 0, created=created)
|
@ -31,6 +31,22 @@ def account_required(view):
|
|||||||
|
|
||||||
return wrapped_view
|
return wrapped_view
|
||||||
|
|
||||||
|
|
||||||
|
def admin_account_required(view):
|
||||||
|
"""View decorator that redirects non-admin users to the login page."""
|
||||||
|
|
||||||
|
@functools.wraps(view)
|
||||||
|
def wrapped_view(**kwargs):
|
||||||
|
if session.get("account") is None or session.get("csrf-token") is None:
|
||||||
|
return redirect(url_for("auth.login"))
|
||||||
|
|
||||||
|
if session.get("account") not in current_app.config["ADMIN_EMAIL_ADDRESSES_CSV"].split(","):
|
||||||
|
return redirect(url_for("auth.login"))
|
||||||
|
|
||||||
|
return view(**kwargs)
|
||||||
|
|
||||||
|
return wrapped_view
|
||||||
|
|
||||||
@bp.route("/login", methods=("GET", "POST"))
|
@bp.route("/login", methods=("GET", "POST"))
|
||||||
def login():
|
def login():
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
|
@ -56,12 +56,15 @@ class DBModel:
|
|||||||
|
|
||||||
# ------ VM & ACCOUNT MANAGEMENT ---------
|
# ------ VM & ACCOUNT MANAGEMENT ---------
|
||||||
|
|
||||||
|
def all_non_deleted_vms(self):
|
||||||
|
self.cursor.execute("SELECT id, host, network_name, last_seen_ipv4, last_seen_ipv6 FROM vms WHERE deleted IS NULL")
|
||||||
|
return list(map(lambda x: dict(id=x[0], host=x[1], network_name=x[2], last_seen_ipv4=x[3], last_seen_ipv6=x[4]), self.cursor.fetchall()))
|
||||||
|
|
||||||
def all_non_deleted_vm_ids(self,):
|
def all_non_deleted_vm_ids(self):
|
||||||
self.cursor.execute("SELECT id FROM vms WHERE deleted IS NULL")
|
self.cursor.execute("SELECT id FROM vms WHERE deleted IS NULL")
|
||||||
return list(map(lambda x: x[0], self.cursor.fetchall()))
|
return list(map(lambda x: x[0], self.cursor.fetchall()))
|
||||||
|
|
||||||
def operating_systems_dict(self,):
|
def operating_systems_dict(self):
|
||||||
self.cursor.execute("SELECT id, template_image_file_name, description FROM os_images WHERE deprecated = FALSE")
|
self.cursor.execute("SELECT id, template_image_file_name, description FROM os_images WHERE deprecated = FALSE")
|
||||||
|
|
||||||
operatingSystems = dict()
|
operatingSystems = dict()
|
||||||
@ -70,7 +73,7 @@ class DBModel:
|
|||||||
|
|
||||||
return operatingSystems
|
return operatingSystems
|
||||||
|
|
||||||
def vm_sizes_dict(self,):
|
def vm_sizes_dict(self):
|
||||||
self.cursor.execute("SELECT id, dollars_per_month, vcpus, memory_mb, bandwidth_gb_per_month FROM vm_sizes")
|
self.cursor.execute("SELECT id, dollars_per_month, vcpus, memory_mb, bandwidth_gb_per_month FROM vm_sizes")
|
||||||
|
|
||||||
vmSizes = dict()
|
vmSizes = dict()
|
||||||
@ -301,6 +304,21 @@ class DBModel:
|
|||||||
|
|
||||||
# ------ HOSTS ---------
|
# ------ HOSTS ---------
|
||||||
|
|
||||||
|
def list_hosts_with_networks(self):
|
||||||
|
self.cursor.execute("""
|
||||||
|
SELECT hosts.id, hosts.last_health_check, host_network.network_name, host_network.public_ipv4_cidr_block FROM hosts
|
||||||
|
JOIN host_network ON host_network.host = hosts.id
|
||||||
|
""")
|
||||||
|
|
||||||
|
hosts = dict()
|
||||||
|
for row in self.cursor.fetchall():
|
||||||
|
if row[0] not in hosts:
|
||||||
|
hosts[row[0]] = dict(last_health_check=row[1], networks=[])
|
||||||
|
|
||||||
|
hosts[row[0]]["networks"].append(dict(network_name=row[2], public_ipv4_cidr_block=row[3]))
|
||||||
|
|
||||||
|
return hosts
|
||||||
|
|
||||||
def authorized_for_host(self, id, token) -> bool:
|
def authorized_for_host(self, id, token) -> bool:
|
||||||
self.cursor.execute("SELECT id FROM hosts WHERE id = %s AND token = %s", (id, token))
|
self.cursor.execute("SELECT id FROM hosts WHERE id = %s AND token = %s", (id, token))
|
||||||
return self.cursor.fetchone() != None
|
return self.cursor.fetchone() != None
|
||||||
@ -317,8 +335,27 @@ class DBModel:
|
|||||||
self.cursor.execute("SELECT id, https_url FROM hosts WHERE last_health_check > NOW() - INTERVAL '20 seconds'")
|
self.cursor.execute("SELECT id, https_url FROM hosts WHERE last_health_check > NOW() - INTERVAL '20 seconds'")
|
||||||
return list(map(lambda x: OnlineHost(id=x[0], url=x[1]), self.cursor.fetchall()))
|
return list(map(lambda x: OnlineHost(id=x[0], url=x[1]), self.cursor.fetchall()))
|
||||||
|
|
||||||
def create_operation(self, online_hosts: List[OnlineHost], email: str, payload: str) -> int:
|
def list_all_operations(self):
|
||||||
|
self.cursor.execute("""
|
||||||
|
SELECT operations.id, operations.email, operations.created, operations.payload,
|
||||||
|
host_operation.host host_operation.assignment_status, host_operation.assigned,
|
||||||
|
host_operation.completed, host_operation.results FROM operations
|
||||||
|
JOIN host_operation ON host_operation.operation = operations.id
|
||||||
|
""")
|
||||||
|
|
||||||
|
operations = dict()
|
||||||
|
for row in self.cursor.fetchall():
|
||||||
|
if row[0] not in operations:
|
||||||
|
operations[row[0]] = dict(email=row[1], created=row[2], payload=row[3], hosts=[])
|
||||||
|
|
||||||
|
operations[row[0]]["hosts"].append(dict(
|
||||||
|
host=row[4], assignment_status=row[5], assigned=row[6],
|
||||||
|
completed=row[7], results=row[8],
|
||||||
|
))
|
||||||
|
|
||||||
|
return operations
|
||||||
|
|
||||||
|
def create_operation(self, online_hosts: List[OnlineHost], email: str, payload: str) -> int:
|
||||||
self.cursor.execute( "INSERT INTO operations (email, payload) VALUES (%s, %s) RETURNING id", (email, payload) )
|
self.cursor.execute( "INSERT INTO operations (email, payload) VALUES (%s, %s) RETURNING id", (email, payload) )
|
||||||
operation_id = self.cursor.fetchone()[0]
|
operation_id = self.cursor.fetchone()[0]
|
||||||
|
|
||||||
|
6
capsulflask/schema_migrations/16_down_managed_ips.sql
Normal file
6
capsulflask/schema_migrations/16_down_managed_ips.sql
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
|
||||||
|
DROP TABLE host_network;
|
||||||
|
|
||||||
|
ALTER TABLE vms DROP COLUMN network;
|
||||||
|
|
||||||
|
UPDATE schemaversion SET version = 15;
|
14
capsulflask/schema_migrations/16_up_managed_ips.sql
Normal file
14
capsulflask/schema_migrations/16_up_managed_ips.sql
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
|
||||||
|
CREATE TABLE host_network (
|
||||||
|
public_ipv4_cidr_block TEXT PRIMARY KEY NOT NULL,
|
||||||
|
network_name TEXT NOT NULL,
|
||||||
|
host TEXT NOT NULL REFERENCES hosts(id) ON DELETE RESTRICT,
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO host_network (public_ipv4_cidr_block, network_name, host) VALUES ('baikal', 'virbr1', '69.61.2.162/27'),
|
||||||
|
('baikal', 'virbr2', '69.61.2.194/26');
|
||||||
|
|
||||||
|
ALTER TABLE vms ADD COLUMN network_name TEXT NOT NULL;
|
||||||
|
ALTER TABLE vms ADD FOREIGN KEY (host, network_name) REFERENCES host_network(host, network_name) ON DELETE RESTRICT;
|
||||||
|
|
||||||
|
UPDATE schemaversion SET version = 16;
|
Loading…
Reference in New Issue
Block a user