v0.3.0
This commit is contained in:
parent
a463cd670c
commit
f9eebfef5e
33 changed files with 15111 additions and 2575 deletions
|
@ -1,3 +1,12 @@
|
|||
# 0.3.0
|
||||
- Improved Dockerfile for quicker builds
|
||||
- Added version specific flask and werkzeug to requirements due to build error in dependencies
|
||||
- Added a Network Zones page
|
||||
- Added a Network page with DHCP Leases, Network Load Balancers, Forwards, and Peers
|
||||
- Added missing parameters in API for creating a network
|
||||
- Upgraded jQuery to version 3.7.1
|
||||
- Updated layout to container and virtual machines pages
|
||||
|
||||
# 0.2.1
|
||||
- Updated local xterm.js packages to version 5.1.0 and loading from local file
|
||||
- Modified CSS to hide terminal scrollbar in chrome based browsers
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
FROM python:3.10.6
|
||||
|
||||
RUN mkdir -p /opt/lxconsole
|
||||
ADD lxconsole /opt/lxconsole/lxconsole
|
||||
COPY requirements.txt /opt/lxconsole/requirements.txt
|
||||
COPY run.py /opt/lxconsole/run.py
|
||||
|
||||
COPY requirements.txt /opt/lxconsole/requirements.txt
|
||||
RUN pip install --upgrade pip
|
||||
RUN pip3 install -r /opt/lxconsole/requirements.txt
|
||||
|
||||
ADD lxconsole /opt/lxconsole/lxconsole
|
||||
COPY run.py /opt/lxconsole/run.py
|
||||
|
||||
RUN apt update
|
||||
RUN apt install sqlite3
|
||||
|
||||
|
|
|
@ -7,9 +7,11 @@ from . import cluster_members
|
|||
from . import images
|
||||
from . import container
|
||||
from . import containers
|
||||
from . import network
|
||||
from . import networks
|
||||
from . import network_acl
|
||||
from . import network_acls
|
||||
from . import network_zones
|
||||
from . import profiles
|
||||
from . import operations
|
||||
from . import projects
|
||||
|
@ -38,9 +40,11 @@ api.add_url_rule('/certificates/<endpoint>', view_func=certificates.api_certific
|
|||
api.add_url_rule('/cluster-groups/<endpoint>', view_func=cluster_groups.api_cluster_groups_endpoint, methods=['GET', 'POST'])
|
||||
api.add_url_rule('/cluster-members/<endpoint>', view_func=cluster_members.api_cluster_members_endpoint, methods=['GET', 'POST'])
|
||||
api.add_url_rule('/images/<endpoint>', view_func=images.api_images_endpoint, methods=['GET', 'POST'])
|
||||
api.add_url_rule('/network/<endpoint>', view_func=network.api_network_endpoint, methods=['GET', 'POST'])
|
||||
api.add_url_rule('/networks/<endpoint>', view_func=networks.api_networks_endpoint, methods=['GET', 'POST'])
|
||||
api.add_url_rule('/network-acl/<endpoint>', view_func=network_acl.api_network_acl_endpoint, methods=['GET', 'POST'])
|
||||
api.add_url_rule('/network-acls/<endpoint>', view_func=network_acls.api_network_acls_endpoint, methods=['GET', 'POST'])
|
||||
api.add_url_rule('/network-zones/<endpoint>', view_func=network_zones.api_network_zones_endpoint, methods=['GET', 'POST'])
|
||||
api.add_url_rule('/profiles/<endpoint>', view_func=profiles.api_profiles_endpoint, methods=['GET', 'POST'])
|
||||
api.add_url_rule('/operations/<endpoint>', view_func=operations.api_operations_endpoint, methods=['GET', 'POST'])
|
||||
api.add_url_rule('/projects/<endpoint>', view_func=projects.api_projects_endpoint, methods=['GET', 'POST'])
|
||||
|
|
|
@ -24,6 +24,10 @@ def privilege_check(privilege, server_id = 0):
|
|||
#'add_instance_usb_device',
|
||||
#'add_instance',
|
||||
#'add_network_acl',
|
||||
#'add_network_zone',
|
||||
#'add_network_load_balancer',
|
||||
#'add_network_forward',
|
||||
#'add_network_peer',
|
||||
#'add_network',
|
||||
#'add_profile',
|
||||
#'add_project',
|
||||
|
@ -52,6 +56,10 @@ def privilege_check(privilege, server_id = 0):
|
|||
#'delete_instance',
|
||||
#'delete_instance',
|
||||
#'delete_network_acl',
|
||||
#'delete_network_zone',
|
||||
#'delete_network_load_balancer',
|
||||
#'delete_network_forward',
|
||||
#'delete_network_peer',
|
||||
#'delete_network',
|
||||
#'delete_operation',
|
||||
#'delete_profile',
|
||||
|
@ -68,6 +76,7 @@ def privilege_check(privilege, server_id = 0):
|
|||
#'export_instance_backup',
|
||||
'get_access_control',
|
||||
'get_group',
|
||||
'get_network_state',
|
||||
'get_server_info',
|
||||
'get_server_initial_project',
|
||||
'get_server_resources',
|
||||
|
@ -102,6 +111,11 @@ def privilege_check(privilege, server_id = 0):
|
|||
'list_instances',
|
||||
'list_logs',
|
||||
'list_network_acls',
|
||||
'list_network_forwards',
|
||||
'list_network_leases',
|
||||
'list_network_load_balancers',
|
||||
'list_network_peers',
|
||||
'list_network_zones',
|
||||
'list_network_managed_devices',
|
||||
'list_networks',
|
||||
'list_operations',
|
||||
|
@ -119,6 +133,11 @@ def privilege_check(privilege, server_id = 0):
|
|||
'load_image',
|
||||
'load_instance',
|
||||
'load_network_acl',
|
||||
'load_network_forward',
|
||||
'load_network_lease',
|
||||
'load_network_load_balancer',
|
||||
'load_network_peer',
|
||||
'load_network_zone',
|
||||
'load_network',
|
||||
'load_operation',
|
||||
'load_profile',
|
||||
|
@ -141,6 +160,11 @@ def privilege_check(privilege, server_id = 0):
|
|||
#'update_image',
|
||||
#'update_instance',
|
||||
#'update_network_acl',
|
||||
#'update_network_forward',
|
||||
#'update_network_lease',
|
||||
#'update_network_load_balancer',
|
||||
#'update_network_peer',
|
||||
#'update_network_zone',
|
||||
#'update_network',
|
||||
#'update_profile',
|
||||
#'update_project',
|
||||
|
@ -166,6 +190,10 @@ def privilege_check(privilege, server_id = 0):
|
|||
#'add_instance_usb_device',
|
||||
#'add_instance',
|
||||
#'add_network_acl',
|
||||
#'add_network_zone',
|
||||
#'add_network_load_balancer',
|
||||
#'add_network_forward',
|
||||
#'add_network_peer',
|
||||
#'add_network',
|
||||
#'add_profile',
|
||||
#'add_project',
|
||||
|
@ -194,6 +222,10 @@ def privilege_check(privilege, server_id = 0):
|
|||
#'delete_instance',
|
||||
#'delete_instance',
|
||||
#'delete_network_acl',
|
||||
#'delete_network_zone',
|
||||
#'delete_network_load_balancer',
|
||||
#'delete_network_forward',
|
||||
#'delete_network_peer',
|
||||
#'delete_network',
|
||||
#'delete_operation',
|
||||
#'delete_profile',
|
||||
|
@ -210,6 +242,7 @@ def privilege_check(privilege, server_id = 0):
|
|||
'export_instance_backup',
|
||||
'get_access_control',
|
||||
'get_group',
|
||||
'get_network_state',
|
||||
'get_server_info',
|
||||
'get_server_initial_project',
|
||||
'get_server_resources',
|
||||
|
@ -244,6 +277,11 @@ def privilege_check(privilege, server_id = 0):
|
|||
'list_instances',
|
||||
'list_logs',
|
||||
'list_network_acls',
|
||||
'list_network_forwards',
|
||||
'list_network_leases',
|
||||
'list_network_load_balancers',
|
||||
'list_network_peers',
|
||||
'list_network_zones',
|
||||
'list_network_managed_devices',
|
||||
'list_networks',
|
||||
'list_operations',
|
||||
|
@ -261,6 +299,11 @@ def privilege_check(privilege, server_id = 0):
|
|||
'load_image',
|
||||
'load_instance',
|
||||
'load_network_acl',
|
||||
'load_network_forward',
|
||||
'load_network_lease',
|
||||
'load_network_load_balancer',
|
||||
'load_network_peer',
|
||||
'load_network_zone',
|
||||
'load_network',
|
||||
'load_operation',
|
||||
'load_profile',
|
||||
|
@ -283,6 +326,11 @@ def privilege_check(privilege, server_id = 0):
|
|||
#'update_image',
|
||||
#'update_instance',
|
||||
#'update_network_acl',
|
||||
#'update_network_forward',
|
||||
#'update_network_lease',
|
||||
#'update_network_load_balancer',
|
||||
#'update_network_peer',
|
||||
#'update_network_zone',
|
||||
#'update_network',
|
||||
#'update_profile',
|
||||
#'update_project',
|
||||
|
@ -308,6 +356,10 @@ def privilege_check(privilege, server_id = 0):
|
|||
'add_instance_usb_device',
|
||||
'add_instance',
|
||||
'add_network_acl',
|
||||
'add_network_zone',
|
||||
'add_network_load_balancer',
|
||||
'add_network_forward',
|
||||
'add_network_peer',
|
||||
'add_network',
|
||||
'add_profile',
|
||||
'add_project',
|
||||
|
@ -336,6 +388,10 @@ def privilege_check(privilege, server_id = 0):
|
|||
'delete_instance',
|
||||
'delete_instance',
|
||||
'delete_network_acl',
|
||||
'delete_network_zone',
|
||||
'delete_network_load_balancer',
|
||||
'delete_network_forward',
|
||||
'delete_network_peer',
|
||||
'delete_network',
|
||||
'delete_operation',
|
||||
'delete_profile',
|
||||
|
@ -352,6 +408,7 @@ def privilege_check(privilege, server_id = 0):
|
|||
'export_instance_backup',
|
||||
'get_access_control',
|
||||
'get_group',
|
||||
'get_network_state',
|
||||
'get_server_info',
|
||||
'get_server_initial_project',
|
||||
'get_server_resources',
|
||||
|
@ -386,6 +443,11 @@ def privilege_check(privilege, server_id = 0):
|
|||
'list_instances',
|
||||
'list_logs',
|
||||
'list_network_acls',
|
||||
'list_network_forwards',
|
||||
'list_network_leases',
|
||||
'list_network_load_balancers',
|
||||
'list_network_peers',
|
||||
'list_network_zones',
|
||||
'list_network_managed_devices',
|
||||
'list_networks',
|
||||
'list_operations',
|
||||
|
@ -403,6 +465,11 @@ def privilege_check(privilege, server_id = 0):
|
|||
'load_image',
|
||||
'load_instance',
|
||||
'load_network_acl',
|
||||
'load_network_forward',
|
||||
'load_network_lease',
|
||||
'load_network_load_balancer',
|
||||
'load_network_peer',
|
||||
'load_network_zone',
|
||||
'load_network',
|
||||
'load_operation',
|
||||
'load_profile',
|
||||
|
@ -425,6 +492,11 @@ def privilege_check(privilege, server_id = 0):
|
|||
'update_image',
|
||||
'update_instance',
|
||||
'update_network_acl',
|
||||
'update_network_forward',
|
||||
'update_network_lease',
|
||||
'update_network_load_balancer',
|
||||
'update_network_peer',
|
||||
'update_network_zone',
|
||||
'update_network',
|
||||
'update_profile',
|
||||
'update_project',
|
||||
|
@ -450,6 +522,10 @@ def privilege_check(privilege, server_id = 0):
|
|||
'add_instance_usb_device',
|
||||
'add_instance',
|
||||
'add_network_acl',
|
||||
'add_network_zone',
|
||||
'add_network_load_balancer',
|
||||
'add_network_forward',
|
||||
'add_network_peer',
|
||||
'add_network',
|
||||
'add_profile',
|
||||
'add_project',
|
||||
|
@ -478,6 +554,10 @@ def privilege_check(privilege, server_id = 0):
|
|||
'delete_instance',
|
||||
'delete_instance',
|
||||
'delete_network_acl',
|
||||
'delete_network_zone',
|
||||
'delete_network_load_balancer',
|
||||
'delete_network_forward',
|
||||
'delete_network_peer',
|
||||
'delete_network',
|
||||
'delete_operation',
|
||||
'delete_profile',
|
||||
|
@ -494,6 +574,7 @@ def privilege_check(privilege, server_id = 0):
|
|||
'export_instance_backup',
|
||||
'get_access_control',
|
||||
'get_group',
|
||||
'get_network_state',
|
||||
'get_server_info',
|
||||
'get_server_initial_project',
|
||||
'get_server_resources',
|
||||
|
@ -528,6 +609,11 @@ def privilege_check(privilege, server_id = 0):
|
|||
'list_instances',
|
||||
'list_logs',
|
||||
'list_network_acls',
|
||||
'list_network_forwards',
|
||||
'list_network_leases',
|
||||
'list_network_load_balancers',
|
||||
'list_network_peers',
|
||||
'list_network_zones',
|
||||
'list_network_managed_devices',
|
||||
'list_networks',
|
||||
'list_operations',
|
||||
|
@ -545,6 +631,11 @@ def privilege_check(privilege, server_id = 0):
|
|||
'load_image',
|
||||
'load_instance',
|
||||
'load_network_acl',
|
||||
'load_network_forward',
|
||||
'load_network_lease',
|
||||
'load_network_load_balancer',
|
||||
'load_network_peer',
|
||||
'load_network_zone',
|
||||
'load_network',
|
||||
'load_operation',
|
||||
'load_profile',
|
||||
|
@ -567,6 +658,11 @@ def privilege_check(privilege, server_id = 0):
|
|||
'update_image',
|
||||
'update_instance',
|
||||
'update_network_acl',
|
||||
'update_network_forward',
|
||||
'update_network_lease',
|
||||
'update_network_load_balancer',
|
||||
'update_network_peer',
|
||||
'update_network_zone',
|
||||
'update_network',
|
||||
'update_profile',
|
||||
'update_project',
|
||||
|
|
392
lxconsole/api/network.py
Normal file
392
lxconsole/api/network.py
Normal file
|
@ -0,0 +1,392 @@
|
|||
from flask import jsonify, request
|
||||
import json
|
||||
import requests
|
||||
import os
|
||||
from lxconsole import db
|
||||
from lxconsole.models import Server
|
||||
from datetime import datetime
|
||||
from flask_login import login_required
|
||||
from lxconsole.api.access_controls import privilege_check
|
||||
|
||||
|
||||
def get_client_crt():
|
||||
return 'certs/client.crt'
|
||||
|
||||
def get_client_key():
|
||||
return 'certs/client.key'
|
||||
|
||||
@login_required
|
||||
def api_network_endpoint(endpoint):
|
||||
|
||||
if not privilege_check(endpoint, request.args.get('id')):
|
||||
return jsonify({'data': [], 'metadata':[], 'error': 'not authorized', 'error_code': 403})
|
||||
|
||||
|
||||
if endpoint == 'add_network_forward':
|
||||
id = request.args.get('id')
|
||||
project = request.args.get('project')
|
||||
network = request.args.get('network')
|
||||
server = Server.query.filter_by(id=id).first()
|
||||
url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/networks/' + network + '/forwards?project=' + project
|
||||
client_cert = get_client_crt()
|
||||
client_key = get_client_key()
|
||||
|
||||
if request.form.get('json'):
|
||||
data = request.form.get('json')
|
||||
results = requests.post(url, verify=server.ssl_verify, cert=(client_cert, client_key), data=data)
|
||||
return jsonify(results.json())
|
||||
|
||||
data = {}
|
||||
data.update({'listen_address': request.form.get('listen_address')})
|
||||
data.update({'description': request.form.get('description')})
|
||||
#config = {}
|
||||
#config.update({'user.mykey': request.form.get('user.mykey')}) if request.form.get('user.mykey') else False
|
||||
port = {}
|
||||
port.update({'description': request.form.get('port_description')}) if request.form.get('port_description') else False
|
||||
port.update({'listen_port': request.form.get('port_listen_port')}) if request.form.get('port_listen_port') else False
|
||||
port.update({'protocol': request.form.get('port_protocol')}) if request.form.get('port_protocol') else False
|
||||
port.update({'target_address': [ request.form.get('port_target_address') ]}) if request.form.get('port_target_address') else False
|
||||
port.update({'target_port': [ request.form.get('port_target_port') ]}) if request.form.get('port_target_port') else False
|
||||
|
||||
#data.update({'config': config})
|
||||
data.update({'ports': [ port ]})
|
||||
results = requests.post(url, verify=server.ssl_verify, cert=(client_cert, client_key), json=data)
|
||||
|
||||
return jsonify(results.json())
|
||||
|
||||
|
||||
if endpoint == 'add_network_load_balancer':
|
||||
id = request.args.get('id')
|
||||
project = request.args.get('project')
|
||||
network = request.args.get('network')
|
||||
server = Server.query.filter_by(id=id).first()
|
||||
url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/networks/' + network + '/load-balancers?project=' + project
|
||||
client_cert = get_client_crt()
|
||||
client_key = get_client_key()
|
||||
|
||||
if request.form.get('json'):
|
||||
data = request.form.get('json')
|
||||
results = requests.post(url, verify=server.ssl_verify, cert=(client_cert, client_key), data=data)
|
||||
return jsonify(results.json())
|
||||
|
||||
data = {}
|
||||
data.update({'listen_address': request.form.get('listen_address')})
|
||||
data.update({'description': request.form.get('description')})
|
||||
backend = {}
|
||||
backend.update({'description': request.form.get('backend_description')}) if request.form.get('backend_description') else False
|
||||
backend.update({'name': request.form.get('backend_name')}) if request.form.get('backend_name') else False
|
||||
backend.update({'target_address': request.form.get('backend_target_address')}) if request.form.get('backend_target_address') else False
|
||||
backend.update({'target_port': request.form.get('backend_target_port')}) if request.form.get('backend_target_port') else False
|
||||
#config = {}
|
||||
#config.update({'user.mykey': request.form.get('user.mykey')}) if request.form.get('user.mykey') else False
|
||||
port = {}
|
||||
port.update({'description': request.form.get('port_description')}) if request.form.get('port_description') else False
|
||||
port.update({'listen_port': request.form.get('port_listen_port')}) if request.form.get('port_listen_port') else False
|
||||
port.update({'protocol': request.form.get('port_protocol')}) if request.form.get('port_protocol') else False
|
||||
port.update({'target_backend': [ request.form.get('port_target_backend') ]}) if request.form.get('port_target_backend') else False
|
||||
|
||||
data.update({'backends': [ backend ]})
|
||||
#data.update({'config': config})
|
||||
data.update({'ports': [ port ]})
|
||||
results = requests.post(url, verify=server.ssl_verify, cert=(client_cert, client_key), json=data)
|
||||
|
||||
return jsonify(results.json())
|
||||
|
||||
|
||||
if endpoint == 'add_network_peer':
|
||||
id = request.args.get('id')
|
||||
project = request.args.get('project')
|
||||
network = request.args.get('network')
|
||||
server = Server.query.filter_by(id=id).first()
|
||||
url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/networks/' + network + '/peers?project=' + project
|
||||
client_cert = get_client_crt()
|
||||
client_key = get_client_key()
|
||||
|
||||
if request.form.get('json'):
|
||||
data = request.form.get('json')
|
||||
results = requests.post(url, verify=server.ssl_verify, cert=(client_cert, client_key), data=data)
|
||||
return jsonify(results.json())
|
||||
|
||||
data = {}
|
||||
data.update({'name': request.form.get('name')})
|
||||
data.update({'description': request.form.get('description')})
|
||||
data.update({'target_network': request.form.get('target_network')})
|
||||
data.update({'target_project': request.form.get('target_network')})
|
||||
#config = {}
|
||||
#config.update({'user.mykey': request.form.get('user.mykey')}) if request.form.get('user.mykey') else False
|
||||
|
||||
#data.update({'config': config})
|
||||
results = requests.post(url, verify=server.ssl_verify, cert=(client_cert, client_key), json=data)
|
||||
|
||||
return jsonify(results.json())
|
||||
|
||||
|
||||
if endpoint == 'delete_network_forward':
|
||||
id = request.args.get('id')
|
||||
project = request.args.get('project')
|
||||
network = request.args.get('network')
|
||||
name = request.form.get('name')
|
||||
server = Server.query.filter_by(id=id).first()
|
||||
url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/networks/' + network + '/forwards/' + name + '?project=' + project
|
||||
client_cert = get_client_crt()
|
||||
client_key = get_client_key()
|
||||
results = requests.delete(url, verify=server.ssl_verify, cert=(client_cert, client_key))
|
||||
return jsonify(results.json())
|
||||
|
||||
|
||||
if endpoint == 'delete_network_load_balancer':
|
||||
id = request.args.get('id')
|
||||
project = request.args.get('project')
|
||||
network = request.args.get('network')
|
||||
name = request.form.get('name')
|
||||
server = Server.query.filter_by(id=id).first()
|
||||
url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/networks/' + network + '/load-balancers/' + name + '?project=' + project
|
||||
client_cert = get_client_crt()
|
||||
client_key = get_client_key()
|
||||
results = requests.delete(url, verify=server.ssl_verify, cert=(client_cert, client_key))
|
||||
return jsonify(results.json())
|
||||
|
||||
|
||||
if endpoint == 'delete_network_peer':
|
||||
id = request.args.get('id')
|
||||
project = request.args.get('project')
|
||||
network = request.args.get('network')
|
||||
name = request.form.get('name')
|
||||
server = Server.query.filter_by(id=id).first()
|
||||
url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/networks/' + network + '/peers/' + name + '?project=' + project
|
||||
client_cert = get_client_crt()
|
||||
client_key = get_client_key()
|
||||
results = requests.delete(url, verify=server.ssl_verify, cert=(client_cert, client_key))
|
||||
return jsonify(results.json())
|
||||
|
||||
|
||||
if endpoint == 'get_network_state':
|
||||
id = request.args.get('id')
|
||||
project = request.args.get('project')
|
||||
server = Server.query.filter_by(id=id).first()
|
||||
name = request.args.get('name')
|
||||
recursion = request.args.get('recursion')
|
||||
if recursion == '1':
|
||||
url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/networks/' + name + '/state?recursion=1&project=' + project
|
||||
else:
|
||||
url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/networks/' + name + '/state?project=' + project
|
||||
client_cert = get_client_crt()
|
||||
client_key = get_client_key()
|
||||
|
||||
try:
|
||||
results = requests.get(url, verify=server.ssl_verify, cert=(client_cert, client_key), timeout=5)
|
||||
results.raise_for_status()
|
||||
except requests.exceptions.RequestException as errex:
|
||||
return jsonify({'metadata': []})
|
||||
|
||||
return jsonify(results.json())
|
||||
|
||||
|
||||
if endpoint == 'list_network_forwards':
|
||||
id = request.args.get('id')
|
||||
project = request.args.get('project')
|
||||
server = Server.query.filter_by(id=id).first()
|
||||
name = request.args.get('name')
|
||||
recursion = request.args.get('recursion')
|
||||
if recursion == '1':
|
||||
url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/networks/' + name + '/forwards?recursion=1&project=' + project
|
||||
else:
|
||||
url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/networks/' + name + '/forwards?project=' + project
|
||||
client_cert = get_client_crt()
|
||||
client_key = get_client_key()
|
||||
try:
|
||||
results = requests.get(url, verify=server.ssl_verify, cert=(client_cert, client_key), timeout=5)
|
||||
results.raise_for_status()
|
||||
except requests.exceptions.RequestException as errex:
|
||||
return jsonify({'metadata': []})
|
||||
|
||||
forwards = json.dumps(results.json())
|
||||
forwards = json.loads(forwards)
|
||||
if forwards['metadata']:
|
||||
return jsonify(results.json())
|
||||
else:
|
||||
return jsonify({'metadata': []})
|
||||
|
||||
|
||||
if endpoint == 'list_network_leases':
|
||||
id = request.args.get('id')
|
||||
project = request.args.get('project')
|
||||
server = Server.query.filter_by(id=id).first()
|
||||
name = request.args.get('name')
|
||||
recursion = request.args.get('recursion')
|
||||
if recursion == '1':
|
||||
url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/networks/' + name + '/leases?recursion=1&project=' + project
|
||||
else:
|
||||
url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/networks/' + name + '/leases?project=' + project
|
||||
client_cert = get_client_crt()
|
||||
client_key = get_client_key()
|
||||
|
||||
try:
|
||||
results = requests.get(url, verify=server.ssl_verify, cert=(client_cert, client_key), timeout=5)
|
||||
results.raise_for_status()
|
||||
except requests.exceptions.RequestException as errex:
|
||||
return jsonify({'metadata': []})
|
||||
|
||||
leases = json.dumps(results.json())
|
||||
leases = json.loads(leases)
|
||||
if leases['metadata']:
|
||||
return jsonify(results.json())
|
||||
else:
|
||||
return jsonify({'metadata': []})
|
||||
|
||||
|
||||
if endpoint == 'list_network_load_balancers':
|
||||
id = request.args.get('id')
|
||||
project = request.args.get('project')
|
||||
server = Server.query.filter_by(id=id).first()
|
||||
name = request.args.get('name')
|
||||
recursion = request.args.get('recursion')
|
||||
if recursion == '1':
|
||||
url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/networks/' + name + '/load-balancers?recursion=1&project=' + project
|
||||
else:
|
||||
url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/networks/' + name + '/load-balancers?project=' + project
|
||||
client_cert = get_client_crt()
|
||||
client_key = get_client_key()
|
||||
try:
|
||||
results = requests.get(url, verify=server.ssl_verify, cert=(client_cert, client_key), timeout=5)
|
||||
results.raise_for_status()
|
||||
except requests.exceptions.RequestException as errex:
|
||||
return jsonify({'metadata': []})
|
||||
|
||||
load_balancers = json.dumps(results.json())
|
||||
load_balancers = json.loads(load_balancers)
|
||||
if load_balancers['metadata']:
|
||||
return jsonify(results.json())
|
||||
else:
|
||||
return jsonify({'metadata': []})
|
||||
|
||||
|
||||
if endpoint == 'list_network_peers':
|
||||
id = request.args.get('id')
|
||||
project = request.args.get('project')
|
||||
server = Server.query.filter_by(id=id).first()
|
||||
name = request.args.get('name')
|
||||
recursion = request.args.get('recursion')
|
||||
if recursion == '1':
|
||||
url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/networks/' + name + '/peers?recursion=1&project=' + project
|
||||
else:
|
||||
url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/networks/' + name + '/peers?project=' + project
|
||||
client_cert = get_client_crt()
|
||||
client_key = get_client_key()
|
||||
try:
|
||||
results = requests.get(url, verify=server.ssl_verify, cert=(client_cert, client_key), timeout=5)
|
||||
results.raise_for_status()
|
||||
except requests.exceptions.RequestException as errex:
|
||||
return jsonify({'metadata': []})
|
||||
|
||||
peers = json.dumps(results.json())
|
||||
peers = json.loads(peers)
|
||||
if peers['metadata']:
|
||||
return jsonify(results.json())
|
||||
else:
|
||||
return jsonify({'metadata': []})
|
||||
|
||||
|
||||
if endpoint == 'load_network_forward':
|
||||
id = request.args.get('id')
|
||||
project = request.args.get('project')
|
||||
network = request.args.get('network')
|
||||
name = request.form.get('name')
|
||||
server = Server.query.filter_by(id=id).first()
|
||||
|
||||
url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/networks/' + network + '/forwards/' + name + '?project=' + project
|
||||
client_cert = get_client_crt()
|
||||
client_key = get_client_key()
|
||||
results = requests.get(url, verify=server.ssl_verify, cert=(client_cert, client_key))
|
||||
return jsonify(results.json())
|
||||
|
||||
|
||||
if endpoint == 'load_network_load_balancer':
|
||||
id = request.args.get('id')
|
||||
project = request.args.get('project')
|
||||
network = request.args.get('network')
|
||||
name = request.form.get('name')
|
||||
server = Server.query.filter_by(id=id).first()
|
||||
|
||||
url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/networks/' + network + '/load-balancers/' + name + '?project=' + project
|
||||
client_cert = get_client_crt()
|
||||
client_key = get_client_key()
|
||||
results = requests.get(url, verify=server.ssl_verify, cert=(client_cert, client_key))
|
||||
return jsonify(results.json())
|
||||
|
||||
|
||||
if endpoint == 'load_network_peer':
|
||||
id = request.args.get('id')
|
||||
project = request.args.get('project')
|
||||
network = request.args.get('network')
|
||||
name = request.form.get('name')
|
||||
server = Server.query.filter_by(id=id).first()
|
||||
|
||||
url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/networks/' + network + '/peers/' + name + '?project=' + project
|
||||
client_cert = get_client_crt()
|
||||
client_key = get_client_key()
|
||||
results = requests.get(url, verify=server.ssl_verify, cert=(client_cert, client_key))
|
||||
return jsonify(results.json())
|
||||
|
||||
|
||||
if endpoint == 'update_network_forward':
|
||||
id = request.args.get('id')
|
||||
project = request.args.get('project')
|
||||
name = request.args.get('name')
|
||||
server = Server.query.filter_by(id=id).first()
|
||||
network = request.args.get('network')
|
||||
url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/networks/' + network + '/forwards/' + name + '?project=' + project
|
||||
client_cert = get_client_crt()
|
||||
client_key = get_client_key()
|
||||
|
||||
if request.form.get('json'):
|
||||
data = request.form.get('json')
|
||||
results = requests.put(url, verify=server.ssl_verify, cert=(client_cert, client_key), data=data)
|
||||
return jsonify(results.json())
|
||||
|
||||
data = {}
|
||||
data.update({'name': request.form.get('name')})
|
||||
results = requests.post(url, verify=server.ssl_verify, cert=(client_cert, client_key), json=data)
|
||||
return jsonify(results.json())
|
||||
|
||||
|
||||
if endpoint == 'update_network_load_balancer':
|
||||
id = request.args.get('id')
|
||||
project = request.args.get('project')
|
||||
name = request.args.get('name')
|
||||
server = Server.query.filter_by(id=id).first()
|
||||
network = request.args.get('network')
|
||||
url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/networks/' + network + '/load-balancers/' + name + '?project=' + project
|
||||
client_cert = get_client_crt()
|
||||
client_key = get_client_key()
|
||||
|
||||
if request.form.get('json'):
|
||||
data = request.form.get('json')
|
||||
results = requests.put(url, verify=server.ssl_verify, cert=(client_cert, client_key), data=data)
|
||||
return jsonify(results.json())
|
||||
|
||||
data = {}
|
||||
data.update({'name': request.form.get('name')})
|
||||
results = requests.post(url, verify=server.ssl_verify, cert=(client_cert, client_key), json=data)
|
||||
return jsonify(results.json())
|
||||
|
||||
|
||||
if endpoint == 'update_network_peer':
|
||||
id = request.args.get('id')
|
||||
project = request.args.get('project')
|
||||
name = request.args.get('name')
|
||||
server = Server.query.filter_by(id=id).first()
|
||||
network = request.args.get('network')
|
||||
url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/networks/' + network + '/peers/' + name + '?project=' + project
|
||||
client_cert = get_client_crt()
|
||||
client_key = get_client_key()
|
||||
|
||||
if request.form.get('json'):
|
||||
data = request.form.get('json')
|
||||
results = requests.put(url, verify=server.ssl_verify, cert=(client_cert, client_key), data=data)
|
||||
return jsonify(results.json())
|
||||
|
||||
data = {}
|
||||
data.update({'name': request.form.get('name')})
|
||||
results = requests.post(url, verify=server.ssl_verify, cert=(client_cert, client_key), json=data)
|
||||
return jsonify(results.json())
|
103
lxconsole/api/network_zones.py
Normal file
103
lxconsole/api/network_zones.py
Normal file
|
@ -0,0 +1,103 @@
|
|||
from flask import jsonify, request
|
||||
import requests
|
||||
from lxconsole import db
|
||||
from lxconsole.models import Server
|
||||
from flask_login import login_required
|
||||
from lxconsole.api.access_controls import privilege_check
|
||||
|
||||
|
||||
def get_client_crt():
|
||||
return 'certs/client.crt'
|
||||
|
||||
def get_client_key():
|
||||
return 'certs/client.key'
|
||||
|
||||
@login_required
|
||||
def api_network_zones_endpoint(endpoint):
|
||||
|
||||
if not privilege_check(endpoint, request.args.get('id')):
|
||||
return jsonify({'data': [], 'metadata':[], 'error': 'not authorized', 'error_code': 403})
|
||||
|
||||
|
||||
if endpoint == 'add_network_zone':
|
||||
id = request.args.get('id')
|
||||
project = request.args.get('project')
|
||||
server = Server.query.filter_by(id=id).first()
|
||||
url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/network-zones?project=' + project
|
||||
client_cert = get_client_crt()
|
||||
client_key = get_client_key()
|
||||
|
||||
if request.form.get('json'):
|
||||
data = request.form.get('json')
|
||||
results = requests.post(url, verify=server.ssl_verify, cert=(client_cert, client_key), data=data)
|
||||
return jsonify(results.json())
|
||||
|
||||
data = {}
|
||||
data.update({'name': request.form.get('name')})
|
||||
data.update({'description': request.form.get('description')})
|
||||
results = requests.post(url, verify=server.ssl_verify, cert=(client_cert, client_key), json=data)
|
||||
|
||||
return jsonify(results.json())
|
||||
|
||||
|
||||
if endpoint == 'delete_network_zone':
|
||||
id = request.args.get('id')
|
||||
project = request.args.get('project')
|
||||
name = request.form.get('name')
|
||||
server = Server.query.filter_by(id=id).first()
|
||||
url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/network-zones/' + name + '?project=' + project
|
||||
client_cert = get_client_crt()
|
||||
client_key = get_client_key()
|
||||
results = requests.delete(url, verify=server.ssl_verify, cert=(client_cert, client_key))
|
||||
return jsonify(results.json())
|
||||
|
||||
|
||||
|
||||
if endpoint == 'list_network_zones':
|
||||
id = request.args.get('id')
|
||||
project = request.args.get('project')
|
||||
server = Server.query.filter_by(id=id).first()
|
||||
recursion = request.args.get('recursion')
|
||||
if recursion == '1':
|
||||
url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/network-zones?recursion=1&project=' + project
|
||||
else:
|
||||
url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/network-zones?project=' + project
|
||||
client_cert = get_client_crt()
|
||||
client_key = get_client_key()
|
||||
results = requests.get(url, verify=server.ssl_verify, cert=(client_cert, client_key))
|
||||
return jsonify(results.json())
|
||||
|
||||
|
||||
if endpoint == 'load_network_zone':
|
||||
id = request.args.get('id')
|
||||
project = request.args.get('project')
|
||||
name = request.form.get('name')
|
||||
server = Server.query.filter_by(id=id).first()
|
||||
url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/network-zones/' + name + '?project=' + project
|
||||
client_cert = get_client_crt()
|
||||
client_key = get_client_key()
|
||||
results = requests.get(url, verify=server.ssl_verify, cert=(client_cert, client_key))
|
||||
return jsonify(results.json())
|
||||
|
||||
|
||||
if endpoint == 'update_network_zone':
|
||||
id = request.args.get('id')
|
||||
project = request.args.get('project')
|
||||
name = request.args.get('name')
|
||||
server = Server.query.filter_by(id=id).first()
|
||||
url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/network-zones/' + name + '?project=' + project
|
||||
client_cert = get_client_crt()
|
||||
client_key = get_client_key()
|
||||
|
||||
if request.form.get('json'):
|
||||
data = request.form.get('json')
|
||||
results = requests.put(url, verify=server.ssl_verify, cert=(client_cert, client_key), data=data)
|
||||
return jsonify(results.json())
|
||||
|
||||
if request.form.get('name'):
|
||||
data = {}
|
||||
data.update({'name': request.form.get('name')})
|
||||
results = requests.post(url, verify=server.ssl_verify, cert=(client_cert, client_key), json=data)
|
||||
return jsonify(results.json())
|
||||
return False
|
||||
|
|
@ -34,8 +34,65 @@ def api_networks_endpoint(endpoint):
|
|||
return jsonify(results.json())
|
||||
|
||||
data = {}
|
||||
data.update({'name': request.form.get('name')})
|
||||
data.update({'description': request.form.get('description')})
|
||||
data.update({'name': request.form.get('name')}) if request.form.get('name') else False
|
||||
data.update({'description': request.form.get('description')}) if request.form.get('description') else False
|
||||
data.update({'type': request.form.get('type')}) if request.form.get('type') else False
|
||||
data.update({'parent': request.form.get('parent')}) if request.form.get('parent') else False
|
||||
data.update({'network': request.form.get('network')}) if request.form.get('network') else False
|
||||
data.update({'mtu': request.form.get('mtu')}) if request.form.get('mtu') else False
|
||||
data.update({'vlan': request.form.get('vlan')}) if request.form.get('vlan') else False
|
||||
|
||||
data.update({'bridge.driver': request.form.get('bridge.driver')}) if request.form.get('bridge.driver') else False
|
||||
data.update({'bridge.external.interfaces': request.form.get('bridge.external.interfaces')}) if request.form.get('bridge.external.interfaces') else False
|
||||
data.update({'bridge.hwaddr': request.form.get('bridge.hwaddr')}) if request.form.get('bridge.hwaddr') else False
|
||||
data.update({'bridge.mode': request.form.get('bridge.mode')}) if request.form.get('bridge.mode') else False
|
||||
data.update({'bridge.mtu': request.form.get('bridge.mtu')}) if request.form.get('bridge.mtu') else False
|
||||
|
||||
data.update({'dns.domain': request.form.get('dns.domain')}) if request.form.get('dns.domain') else False
|
||||
data.update({'dns.mode': request.form.get('dns.mode')}) if request.form.get('dns.mode') else False
|
||||
data.update({'dns.nameservers': request.form.get('dns.nameservers')}) if request.form.get('dns.nameservers') else False
|
||||
data.update({'dns.search': request.form.get('dns.search')}) if request.form.get('dns.search') else False
|
||||
|
||||
data.update({'fan.overlay.subnet': request.form.get('fan.overlay.subnet')}) if request.form.get('fan.overlay.subnet') else False
|
||||
data.update({'fan.type': request.form.get('fan.type')}) if request.form.get('fan.type') else False
|
||||
data.update({'fan.underlay.subnet': request.form.get('fan.underlay.subnet')}) if request.form.get('fan.underlay.subnet') else False
|
||||
|
||||
data.update({'ipv4.address': request.form.get('ipv4.address')}) if request.form.get('ipv4.address') else False
|
||||
data.update({'ipv4.dhcp': request.form.get('ipv4.dhcp')}) if request.form.get('ipv4.dhcp') else False
|
||||
data.update({'ipv4.dhcp.expiry': request.form.get('ipv4.dhcp.expiry')}) if request.form.get('ipv4.dhcp.expiry') else False
|
||||
data.update({'ipv4.dhcp.gateway': request.form.get('ipv4.dhcp.gateway')}) if request.form.get('ipv4.dhcp.gateway') else False
|
||||
data.update({'ipv4.dhcp.ranges': request.form.get('ipv4.dhcp.ranges')}) if request.form.get('ipv4.dhcp.ranges') else False
|
||||
data.update({'ipv4.firewall': request.form.get('ipv4.firewall')}) if request.form.get('ipv4.firewall') else False
|
||||
data.update({'ipv4.nat.address': request.form.get('ipv4.nat.address')}) if request.form.get('ipv4.nat.address') else False
|
||||
data.update({'ipv4.nat': request.form.get('ipv4.nat')}) if request.form.get('ipv4.nat') else False
|
||||
data.update({'ipv4.nat.order': request.form.get('ipv4.nat.order')}) if request.form.get('ipv4.nat.order') else False
|
||||
data.update({'ipv4.ovn.ranges': request.form.get('ipv4.ovn.ranges')}) if request.form.get('ipv4.ovn.ranges') else False
|
||||
data.update({'ipv4.gateway': request.form.get('ipv4.gateway')}) if request.form.get('ipv4.gateway') else False
|
||||
data.update({'ipv4.routes.anycast': request.form.get('ipv4.routes.anycast')}) if request.form.get('ipv4.routes.anycast') else False
|
||||
data.update({'ipv4.routes': request.form.get('ipv4.routes')}) if request.form.get('ipv4.routes') else False
|
||||
data.update({'ipv4.routing': request.form.get('ipv4.routing')}) if request.form.get('ipv4.routing') else False
|
||||
|
||||
data.update({'ipv6.address': request.form.get('ipv6.address')}) if request.form.get('ipv6.address') else False
|
||||
data.update({'ipv6.dhcp': request.form.get('ipv6.dhcp')}) if request.form.get('ipv6.dhcp') else False
|
||||
data.update({'ipv6.dhcp.expiry': request.form.get('ipv6.dhcp.expiry')}) if request.form.get('ipv6.dhcp.expiry') else False
|
||||
data.update({'ipv6.dhcp.ranges': request.form.get('ipv6.dhcp.ranges')}) if request.form.get('ipv6.dhcp.ranges') else False
|
||||
data.update({'ipv6.dhcp.stateful': request.form.get('ipv6.dhcp.stateful')}) if request.form.get('ipv6.dhcp.stateful') else False
|
||||
data.update({'ipv6.firewall': request.form.get('ipv6.firewall')}) if request.form.get('ipv6.firewall') else False
|
||||
data.update({'ipv6.nat.address': request.form.get('ipv6.nat.address')}) if request.form.get('ipv6.nat.address') else False
|
||||
data.update({'ipv6.nat': request.form.get('ipv6.nat')}) if request.form.get('ipv6.nat') else False
|
||||
data.update({'ipv6.nat.order': request.form.get('ipv6.nat.order')}) if request.form.get('ipv6.nat.order') else False
|
||||
data.update({'ipv6.ovn.ranges': request.form.get('ipv6.ovn.ranges')}) if request.form.get('ipv6.ovn.ranges') else False
|
||||
data.update({'ipv6.gateway': request.form.get('ipv6.gateway')}) if request.form.get('ipv6.gateway') else False
|
||||
data.update({'ipv6.routes.anycast': request.form.get('ipv6.routes.anycast')}) if request.form.get('ipv6.routes.anycast') else False
|
||||
data.update({'ipv6.routes': request.form.get('ipv6.routes')}) if request.form.get('ipv6.routes') else False
|
||||
data.update({'ipv6.routing': request.form.get('ipv6.routing')}) if request.form.get('ipv6.routing') else False
|
||||
|
||||
data.update({'maas.subnet.ipv4': request.form.get('maas.subnet.ipv4')}) if request.form.get('maas.subnet.ipv4') else False
|
||||
data.update({'maas.subnet.ipv6': request.form.get('maas.subnet.ipv6')}) if request.form.get('maas.subnet.ipv6') else False
|
||||
|
||||
data.update({'raw.dnsmasq': request.form.get('raw.dnsmasq')}) if request.form.get('raw.dnsmasq') else False
|
||||
data.update({'ovn.ingress.mode': request.form.get('ovn.ingress.mode')}) if request.form.get('ovn.ingress.mode') else False
|
||||
|
||||
results = requests.post(url, verify=server.ssl_verify, cert=(client_cert, client_key), json=data)
|
||||
|
||||
return jsonify(results.json())
|
||||
|
|
|
@ -643,8 +643,8 @@ def api_virtual_machine_endpoint(endpoint):
|
|||
url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/virtual-machines/' + name + '/exec?project=' + project
|
||||
results = requests.post(url, verify=server.ssl_verify, cert=(client_cert, client_key), json=data)
|
||||
|
||||
# Sleep a second to give time for a second reading
|
||||
time.sleep(1)
|
||||
# Sleep to allow time for copy to complete
|
||||
time.sleep(.5)
|
||||
|
||||
#Get first /proc/stat information but from /tmp/stat
|
||||
url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/virtual-machines/' + name + '/files?project=' + project + '&path=/tmp/stat'
|
||||
|
@ -660,7 +660,8 @@ def api_virtual_machine_endpoint(endpoint):
|
|||
first_cpu_time = user_time + system_time + idle_time
|
||||
first_idle_time = idle_time
|
||||
|
||||
|
||||
# Sleep a second between reads
|
||||
time.sleep(1)
|
||||
|
||||
# Copy /proc/stat to /tmp/stat and then read that file as a work around
|
||||
data = {}
|
||||
|
@ -678,8 +679,8 @@ def api_virtual_machine_endpoint(endpoint):
|
|||
url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/virtual-machines/' + name + '/exec?project=' + project
|
||||
results = requests.post(url, verify=server.ssl_verify, cert=(client_cert, client_key), json=data)
|
||||
|
||||
# Sleep a second to give time for a second reading
|
||||
time.sleep(1)
|
||||
# Sleep to allow time for copy to complete
|
||||
time.sleep(.5)
|
||||
|
||||
#Get second /proc/stat information
|
||||
url = 'https://' + server.addr + ':' + str(server.port) + '/1.0/virtual-machines/' + name + '/files?project=' + project + '&path=/tmp/stat'
|
||||
|
|
|
@ -89,6 +89,16 @@ def network_acl():
|
|||
def network_acls():
|
||||
return render_template('network-acls.html', page_title='Network ACLs', page_user_id=current_user.id, page_username=current_user.username,)
|
||||
|
||||
@app.route("/network-zones")
|
||||
@login_required
|
||||
def network_zones():
|
||||
return render_template('network-zones.html', page_title='Network Zones', page_user_id=current_user.id, page_username=current_user.username,)
|
||||
|
||||
@app.route("/network")
|
||||
@login_required
|
||||
def network():
|
||||
return render_template('network.html', page_title='Network', page_user_id=current_user.id, page_username=current_user.username,)
|
||||
|
||||
@app.route("/networks")
|
||||
@login_required
|
||||
def networks():
|
||||
|
|
7
lxconsole/static/css/bootstrap/bootstrap-5.2.3.min.css
vendored
Normal file
7
lxconsole/static/css/bootstrap/bootstrap-5.2.3.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
5
lxconsole/static/css/datatables/dataTables.bootstrap5.min.css
vendored
Normal file
5
lxconsole/static/css/datatables/dataTables.bootstrap5.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
|
@ -62,3 +62,13 @@ code {
|
|||
.terminal .xterm-viewport {
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
td.details-control {
|
||||
text-align:center;
|
||||
color:#007bff ;
|
||||
cursor: pointer;
|
||||
}
|
||||
tr.shown td.details-control {
|
||||
text-align:center;
|
||||
color:#ff0000 ;
|
||||
}
|
7
lxconsole/static/js/bootstrap/bootstrap-5.2.3.bundle.min.js.js
vendored
Normal file
7
lxconsole/static/js/bootstrap/bootstrap-5.2.3.bundle.min.js.js
vendored
Normal file
File diff suppressed because one or more lines are too long
4
lxconsole/static/js/datatables/dataTables.bootstrap5.min.js
vendored
Normal file
4
lxconsole/static/js/datatables/dataTables.bootstrap5.min.js
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
/*! DataTables Bootstrap 5 integration
|
||||
* 2020 SpryMedia Ltd - datatables.net/license
|
||||
*/
|
||||
!function(t){var n,r;"function"==typeof define&&define.amd?define(["jquery","datatables.net"],function(e){return t(e,window,document)}):"object"==typeof exports?(n=require("jquery"),r=function(e,a){a.fn.dataTable||require("datatables.net")(e,a)},"undefined"==typeof window?module.exports=function(e,a){return e=e||window,a=a||n(e),r(e,a),t(a,0,e.document)}:(r(window,n),module.exports=t(n,window,window.document))):t(jQuery,window,document)}(function(x,e,r,o){"use strict";var i=x.fn.dataTable;return x.extend(!0,i.defaults,{dom:"<'row'<'col-sm-12 col-md-6'l><'col-sm-12 col-md-6'f>><'row dt-row'<'col-sm-12'tr>><'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",renderer:"bootstrap"}),x.extend(i.ext.classes,{sWrapper:"dataTables_wrapper dt-bootstrap5",sFilterInput:"form-control form-control-sm",sLengthSelect:"form-select form-select-sm",sProcessing:"dataTables_processing card",sPageButton:"paginate_button page-item"}),i.ext.renderer.pageButton.bootstrap=function(d,e,s,a,l,c){function u(e,a){for(var t,n,r=function(e){e.preventDefault(),x(e.currentTarget).hasClass("disabled")||b.page()==e.data.action||b.page(e.data.action).draw("page")},o=0,i=a.length;o<i;o++)if(t=a[o],Array.isArray(t))u(e,t);else{switch(f=p="",t){case"ellipsis":p="…",f="disabled";break;case"first":p=g.sFirst,f=t+(0<l?"":" disabled");break;case"previous":p=g.sPrevious,f=t+(0<l?"":" disabled");break;case"next":p=g.sNext,f=t+(l<c-1?"":" disabled");break;case"last":p=g.sLast,f=t+(l<c-1?"":" disabled");break;default:p=t+1,f=l===t?"active":""}p&&(n=-1!==f.indexOf("disabled"),n=x("<li>",{class:m.sPageButton+" "+f,id:0===s&&"string"==typeof t?d.sTableId+"_"+t:null}).append(x("<a>",{href:n?null:"#","aria-controls":d.sTableId,"aria-disabled":n?"true":null,"aria-label":w[t],role:"link","aria-current":"active"===f?"page":null,"data-dt-idx":t,tabindex:n?-1:d.iTabIndex,class:"page-link"}).html(p)).appendTo(e),d.oApi._fnBindAction(n,{action:t},r))}}var p,f,t,b=new i.Api(d),m=d.oClasses,g=d.oLanguage.oPaginate,w=d.oLanguage.oAria.paginate||{},e=x(e);try{t=e.find(r.activeElement).data("dt-idx")}catch(e){}var n=e.children("ul.pagination");n.length?n.empty():n=e.html("<ul/>").children("ul").addClass("pagination"),u(n,a),t!==o&&e.find("[data-dt-idx="+t+"]").trigger("focus")},i});
|
4
lxconsole/static/js/datatables/jquery.dataTables-1.13.6.min.js
vendored
Normal file
4
lxconsole/static/js/datatables/jquery.dataTables-1.13.6.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
10716
lxconsole/static/js/jquery/jquery-3.7.1.js
vendored
Normal file
10716
lxconsole/static/js/jquery/jquery-3.7.1.js
vendored
Normal file
File diff suppressed because it is too large
Load diff
|
@ -30,7 +30,6 @@ function configureNavbarForServers(){
|
|||
function configureSidebarForServers(){
|
||||
$("#clusterMembersLinkSidebar").hide()
|
||||
$("#clusterGroupsLinkSidebar").hide()
|
||||
$("#clusterGroupsLinkSidebar").hide()
|
||||
$("#instanceSidebarLinks").hide()
|
||||
$("#coreSidebarLinks").hide()
|
||||
$("#networkSidebarLinks").hide()
|
||||
|
@ -65,6 +64,7 @@ function applySidebarLinks() {
|
|||
$("#clusterGroupsLinkSidebar").attr("href", "cluster-groups?id=" + encodeURI(serverId) + "&project=" + encodeURI(project));
|
||||
$("#projectsLinkSidebar").attr("href", "projects?id=" + encodeURI(serverId) + "&project=" + encodeURI(project));
|
||||
$("#networkAclsLinkSidebar").attr("href", "network-acls?id=" + encodeURI(serverId) + "&project=" + encodeURI(project));
|
||||
$("#networkZonesLinkSidebar").attr("href", "network-zones?id=" + encodeURI(serverId) + "&project=" + encodeURI(project));
|
||||
$("#operationsLinkSidebar").attr("href", "operations?id=" + encodeURI(serverId) + "&project=" + encodeURI(project));
|
||||
$("#certificatesLinkSidebar").attr("href", "certificates?id=" + encodeURI(serverId) + "&project=" + encodeURI(project));
|
||||
$("#simplestreamsLinkSidebar").attr("href", "simplestreams?id=" + encodeURI(serverId) + "&project=" + encodeURI(project));
|
||||
|
@ -103,6 +103,10 @@ function applySidebarStyles() {
|
|||
$('#networkAclsSpan').css('color','#fff');
|
||||
$('#networkAclsIcon').css('color','#fff');
|
||||
}
|
||||
if (location.pathname == "/network-zones" || location.pathname == "/network-zone"){
|
||||
$('#networkZonesSpan').css('color','#fff');
|
||||
$('#networkZonesIcon').css('color','#fff');
|
||||
}
|
||||
if (location.pathname == "/operations"){
|
||||
$('#operationsSpan').css('color','#fff');
|
||||
$('#operationsIcon').css('color','#fff');
|
||||
|
|
|
@ -205,7 +205,6 @@
|
|||
if (data.error_code >= 400){
|
||||
alert(data.error);
|
||||
}
|
||||
$("#storagePoolNameEditInput").text("Name: " + name);
|
||||
$("#jsonInput").val(JSON.stringify(data.metadata, null, 2));
|
||||
$("#editModal").modal('show');
|
||||
});
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -4,21 +4,32 @@
|
|||
<link rel="icon" type="image/png" href="{{ url_for('static', filename='assets/img/logo-light.svg') }}">
|
||||
<title>lxconsole</title>
|
||||
|
||||
|
||||
<!-- Google Font: Source Sans Pro -->
|
||||
<link rel="stylesheet" href="../static/css/fonts/source_sans_pro.css">
|
||||
|
||||
<!-- Font Awesome -->
|
||||
<link rel="stylesheet" href="../static/plugins/fontawesome-free/css/all.min.css">
|
||||
|
||||
<!-- DataTables -->
|
||||
<link rel="stylesheet" href="../static/plugins/datatables-bs4/css/dataTables.bootstrap4.min.css">
|
||||
<link rel="stylesheet" href="../static/plugins/datatables-responsive/css/responsive.bootstrap4.min.css">
|
||||
<link rel="stylesheet" href="../static/plugins/datatables-buttons/css/buttons.bootstrap4.min.css">
|
||||
|
||||
<!-- Xterm.js style -->
|
||||
<link rel="stylesheet" href="../static/css/xterm/xterm.css"/>
|
||||
|
||||
<!-- Theme style -->
|
||||
<link rel="stylesheet" href="../static/dist/css/adminlte.min.css">
|
||||
|
||||
<!-- LXD Dashboard style -->
|
||||
<link rel="stylesheet" href="../static/css/styles.css">
|
||||
|
||||
<!-- Bootstrap 5 - https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/5.2.3/css/bootstrap.min.css -->
|
||||
<!-- <link rel="stylesheet" href="../static/css/bootstrap/bootstrap-5.2.3.min.css"> -->
|
||||
|
||||
<!-- Datatables Bootstrap 5 - https://cdn.datatables.net/1.13.6/css/dataTables.bootstrap5.min.css -->
|
||||
<!--<link rel="stylesheet" href="../static/css/datatables/dataTables.bootstrap5.min.css">-->
|
||||
|
||||
</head>
|
||||
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
|
||||
<footer class="main-footer">
|
||||
<div class="float-right d-none d-sm-block">
|
||||
Version 0.2.1
|
||||
Version 0.3.0
|
||||
</div>
|
||||
Copyright © 2020-Present <a href="https://penninglabs.com">Penning Labs</a>. All rights reserved.
|
||||
</footer>
|
||||
|
@ -48,9 +48,15 @@
|
|||
</div>
|
||||
<!-- ./wrapper -->
|
||||
|
||||
<!-- jQuery -->
|
||||
<script src="../static/plugins/jquery/jquery.min.js"></script>
|
||||
<!-- jQuery - https://code.jquery.com/jquery-3.7.1.js -->
|
||||
<script src="../static/js/jquery/jquery-3.7.1.js"></script>
|
||||
|
||||
<!-- jQuery Datatables - https://cdn.datatables.net/1.13.6/js/jquery.dataTables.min.js -->
|
||||
<!-- <script src="../static/js/datatables/jquery.dataTables-1.13.6.min.js"></script> -->
|
||||
|
||||
<!-- Datatables Bootstrap 5 - https://cdn.datatables.net/1.13.6/js/dataTables.bootstrap5.min.js -->
|
||||
<!-- <script src="../static/js/datatables/dataTables.bootstrap5.min.js"></script> -->
|
||||
|
||||
<!-- Bootstrap 4 -->
|
||||
<script src="../static/plugins/bootstrap/js/bootstrap.bundle.min.js"></script>
|
||||
|
||||
|
@ -76,6 +82,7 @@
|
|||
// url.search = search_params.toString();
|
||||
// location = url.toString();
|
||||
}
|
||||
|
||||
function changeServer(id){
|
||||
window.location.href = 'server?id=' + id;
|
||||
// var url = new URL(window.location);
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
<div class="col-12">
|
||||
<p>Lxconsole is an open source management console providing a web-based user interface capable of managing multiple LXD servers from a single location.</p>
|
||||
<p>
|
||||
<strong>Version</strong>: <span id="versionNumber">v0.2.1</span> <br />
|
||||
<strong>Version</strong>: <span id="versionNumber">v0.3.0</span> <br />
|
||||
<strong>License</strong>: AGPL-3.0 <br />
|
||||
<strong>URL</strong>: https://lxconsole.com <br />
|
||||
</p>
|
||||
|
|
160
lxconsole/templates/modals/network-zones.html
Normal file
160
lxconsole/templates/modals/network-zones.html
Normal file
|
@ -0,0 +1,160 @@
|
|||
<!-- Add Modal-->
|
||||
<div class="modal fade" id="addModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="exampleModalLabel">Add Network Zone</h5>
|
||||
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<ul class="nav nav-tabs" id="myTab" role="tablist">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" id="form-tab" data-toggle="tab" href="#form" role="tab" aria-controls="form" aria-selected="true">Form</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" id="json-tab" data-toggle="tab" href="#json" role="tab" aria-controls="json" aria-selected="false">JSON</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="tab-content" id="myTabContent">
|
||||
<div class="tab-pane fade show active" id="form" role="tabpanel" aria-labelledby="form-tab">
|
||||
<form id="addForm">
|
||||
<br />
|
||||
<div class="row">
|
||||
<label class="col-3 col-form-label text-right">Name: <span class="text-danger">*</span></label>
|
||||
<div class="col-7">
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control" placeholder="" name="name">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-1">
|
||||
<i class="far fa-sm fa-question-circle" title='(Required) - Enter in the name of the network zone. Zones must be globally unique, even across projects.'></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<label class="col-3 col-form-label text-right">Description: </label>
|
||||
<div class="col-7">
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control" placeholder="" name="description">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-1">
|
||||
<i class="far fa-sm fa-question-circle" title='Enter in a description for the network zone.'></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-secondary" type="button" data-dismiss="modal">Cancel</button>
|
||||
<a class="btn btn-primary" href="#" onclick="addItem()" data-dismiss="modal">Submit</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-pane fade" id="json" role="tabpanel" aria-labelledby="json-tab">
|
||||
<br />
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="form-group text-right">
|
||||
<pre>
|
||||
<textarea name="json" class="form-control" id="jsonCreateInput" rows="16" placeholder="Enter JSON data"></textarea>
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-secondary" type="button" data-dismiss="modal">Cancel</button>
|
||||
<a class="btn btn-primary" href="#" onclick="createItemUsingJSON()" data-dismiss="modal">Submit</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Edit Modal-->
|
||||
<div class="modal fade" id="editModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="exampleModalLabel">Edit Network Zone</h5>
|
||||
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<ul class="nav nav-tabs" id="myTab" role="tablist">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" id="json-edit-tab" data-toggle="tab" href="#json-edit" role="tab" aria-controls="json-edit" aria-selected="false">JSON</a>
|
||||
</li>
|
||||
<!-- <li class="nav-item">
|
||||
<a class="nav-link" id="rename-edit-tab" data-toggle="tab" href="#rename-edit" role="tab" aria-controls="rename-edit" aria-selected="true">Rename</a>
|
||||
</li> -->
|
||||
</ul>
|
||||
<div class="tab-content" id="myTabContent">
|
||||
<div class="tab-pane fade show active" id="json-edit" role="tabpanel" aria-labelledby="json-edit-tab">
|
||||
<br />
|
||||
<div class="row">
|
||||
<label class="col-4 col-form-label" id="itemNameEditInput"></label>
|
||||
<div class="col-12">
|
||||
<div class="form-group text-right">
|
||||
<pre>
|
||||
<textarea name="json" class="form-control" id="jsonInput" rows="16" ></textarea>
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-secondary" type="button" data-dismiss="modal">Cancel</button>
|
||||
<a class="btn btn-primary" href="#" onclick="updateItem()" data-dismiss="modal">Submit</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-pane fade" id="rename-edit" role="tabpanel" aria-labelledby="rename-edit-tab">
|
||||
<form id="renameForm">
|
||||
<br />
|
||||
<div class="row">
|
||||
<label class="col-2 col-form-label text-right">Name:</label>
|
||||
<div class="col-8">
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control" placeholder="" name="name">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-1">
|
||||
<i class="far fa-sm fa-question-circle" title='Enter in the new name of the network zone.'></i>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-secondary" type="button" data-dismiss="modal">Cancel</button>
|
||||
<a class="btn btn-primary" href="#" onclick="renameItem()" data-dismiss="modal">Submit</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Delete Modal-->
|
||||
<div class="modal fade" id="deleteModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="exampleModalLabel">Delete Network Zone</h5>
|
||||
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="mb-2" id="deleteQuestionText">
|
||||
Are you sure you want to delete this network zone?
|
||||
</div>
|
||||
<input type="hidden" id="networkZone" class="form-control" name="server_name">
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-secondary" type="button" data-dismiss="modal">Cancel</button>
|
||||
<a class="btn btn-primary" href="#" onclick="deleteItem()" data-dismiss="modal">Yes</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
535
lxconsole/templates/modals/network.html
Normal file
535
lxconsole/templates/modals/network.html
Normal file
|
@ -0,0 +1,535 @@
|
|||
<!-- Add Forward Modal-->
|
||||
<div class="modal fade" id="addForwardModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="exampleModalLabel">Add Network Forward</h5>
|
||||
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<ul class="nav nav-tabs" id="myTab" role="tablist">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" id="add-forward-form-tab" data-toggle="tab" href="#addForwardform" role="tab" aria-controls="add-forward-form-tab" aria-selected="true">Form</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" id="add-forward-json-tab" data-toggle="tab" href="#addForwardJson" role="tab" aria-controls="add-forward-json-tab" aria-selected="false">JSON</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="tab-content" id="myTabContent">
|
||||
<div class="tab-pane fade show active" id="addForwardform" role="tabpanel" aria-labelledby="form-tab">
|
||||
<form id="addForwardForm">
|
||||
<br />
|
||||
<div class="row">
|
||||
<label class="col-3 col-form-label text-right">Listen Address: <span class="text-danger">*</span></label>
|
||||
<div class="col-7">
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control" placeholder="" name="listen_address">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-1">
|
||||
<i class="far fa-sm fa-question-circle" title='(Required) - Enter in the name of the listening network address.'></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<label class="col-3 col-form-label text-right">Description: </label>
|
||||
<div class="col-7">
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control" placeholder="" name="description">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-1">
|
||||
<i class="far fa-sm fa-question-circle" title='Enter in a description for the network load balancer.'></i>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<h5>Port:</h5>
|
||||
<div class="row">
|
||||
<label class="col-3 col-form-label text-right">Description: </label>
|
||||
<div class="col-7">
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control" placeholder="" name="port_description">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-1">
|
||||
<i class="far fa-sm fa-question-circle" title='Enter in a description for the port.'></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<label class="col-3 col-form-label text-right">Listen Port: </label>
|
||||
<div class="col-7">
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control" placeholder="" name="port_listen_port">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-1">
|
||||
<i class="far fa-sm fa-question-circle" title='Enter in a description for the network load balancer.'></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<label class="col-3 col-form-label text-right">Protocol: </label>
|
||||
<div class="col-7">
|
||||
<div class="form-group">
|
||||
<select class="form-control" name="port_protocol">
|
||||
<option value="tcp">TCP</option>
|
||||
<option value="udp">UDP</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-1">
|
||||
<i class="far fa-sm fa-question-circle" title='Enter in a description for the network load balancer.'></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<label class="col-3 col-form-label text-right">Target Address: </label>
|
||||
<div class="col-7">
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control" placeholder="" name="port_target_address">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-1">
|
||||
<i class="far fa-sm fa-question-circle" title='Enter in a description for the network load balancer.'></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<label class="col-3 col-form-label text-right">Target Port: </label>
|
||||
<div class="col-7">
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control" placeholder="" name="port_target_port">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-1">
|
||||
<i class="far fa-sm fa-question-circle" title='Enter in a description for the network load balancer.'></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</form>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-secondary" type="button" data-dismiss="modal">Cancel</button>
|
||||
<a class="btn btn-primary" href="#" onclick="addItem('forward')" data-dismiss="modal">Submit</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-pane fade" id="addForwardJson" role="tabpanel" aria-labelledby="json-tab">
|
||||
<br />
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="form-group text-right">
|
||||
<pre>
|
||||
<textarea name="json" class="form-control" id="jsonCreateForwardInput" rows="16" placeholder="Enter JSON data"></textarea>
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-secondary" type="button" data-dismiss="modal">Cancel</button>
|
||||
<a class="btn btn-primary" href="#" onclick="createItemUsingJSON('forward')" data-dismiss="modal">Submit</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Add Load Balancer Modal-->
|
||||
<div class="modal fade" id="addLoadBalancerModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="exampleModalLabel">Add Network Load Balancer</h5>
|
||||
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<ul class="nav nav-tabs" id="myTab" role="tablist">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" id="form-tab" data-toggle="tab" href="#form" role="tab" aria-controls="form" aria-selected="true">Form</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" id="json-tab" data-toggle="tab" href="#json" role="tab" aria-controls="json" aria-selected="false">JSON</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="tab-content" id="myTabContent">
|
||||
<div class="tab-pane fade show active" id="form" role="tabpanel" aria-labelledby="form-tab">
|
||||
<form id="addLoadBalancerForm">
|
||||
<br />
|
||||
<div class="row">
|
||||
<label class="col-3 col-form-label text-right">Listen Address: <span class="text-danger">*</span></label>
|
||||
<div class="col-7">
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control" placeholder="" name="listen_address">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-1">
|
||||
<i class="far fa-sm fa-question-circle" title='(Required) - Enter in the name of the listening network address.'></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<label class="col-3 col-form-label text-right">Description: </label>
|
||||
<div class="col-7">
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control" placeholder="" name="description">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-1">
|
||||
<i class="far fa-sm fa-question-circle" title='Enter in a description for the network load balancer.'></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
<h5>Backend:</h5>
|
||||
<div class="row">
|
||||
<label class="col-3 col-form-label text-right">Description: </label>
|
||||
<div class="col-7">
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control" placeholder="" name="backend_description">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-1">
|
||||
<i class="far fa-sm fa-question-circle" title='Enter in a description for the port.'></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<label class="col-3 col-form-label text-right">Name: </label>
|
||||
<div class="col-7">
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control" placeholder="" name="backend_name">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-1">
|
||||
<i class="far fa-sm fa-question-circle" title='Enter in a description for the network load balancer.'></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<label class="col-3 col-form-label text-right">Target Address: </label>
|
||||
<div class="col-7">
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control" placeholder="" name="backend_target_address">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-1">
|
||||
<i class="far fa-sm fa-question-circle" title='Enter in a description for the network load balancer.'></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<label class="col-3 col-form-label text-right">Target Port: </label>
|
||||
<div class="col-7">
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control" placeholder="" name="backend_target_port">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-1">
|
||||
<i class="far fa-sm fa-question-circle" title='Enter in a description for the network load balancer.'></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
<h5>Port:</h5>
|
||||
<div class="row">
|
||||
<label class="col-3 col-form-label text-right">Description: </label>
|
||||
<div class="col-7">
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control" placeholder="" name="port_description">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-1">
|
||||
<i class="far fa-sm fa-question-circle" title='Enter in a description for the port.'></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<label class="col-3 col-form-label text-right">Listen Port: </label>
|
||||
<div class="col-7">
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control" placeholder="" name="port_listen_port">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-1">
|
||||
<i class="far fa-sm fa-question-circle" title='Enter in a description for the network load balancer.'></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<label class="col-3 col-form-label text-right">Protocol: </label>
|
||||
<div class="col-7">
|
||||
<div class="form-group">
|
||||
<select class="form-control" name="port_protocol">
|
||||
<option value="tcp">TCP</option>
|
||||
<option value="udp">UDP</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-1">
|
||||
<i class="far fa-sm fa-question-circle" title='Enter in a description for the network load balancer.'></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<label class="col-3 col-form-label text-right">Target Backend: </label>
|
||||
<div class="col-7">
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control" placeholder="" name="port_target_backend">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-1">
|
||||
<i class="far fa-sm fa-question-circle" title='Enter in a description for the network load balancer.'></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-secondary" type="button" data-dismiss="modal">Cancel</button>
|
||||
<a class="btn btn-primary" href="#" onclick="addItem('load_balancer')" data-dismiss="modal">Submit</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-pane fade" id="json" role="tabpanel" aria-labelledby="json-tab">
|
||||
<br />
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="form-group text-right">
|
||||
<pre>
|
||||
<textarea name="json" class="form-control" id="jsonCreateLoadBalancerInput" rows="16" placeholder="Enter JSON data"></textarea>
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-secondary" type="button" data-dismiss="modal">Cancel</button>
|
||||
<a class="btn btn-primary" href="#" onclick="createItemUsingJSON('load_balancer')" data-dismiss="modal">Submit</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Add Peer Modal-->
|
||||
<div class="modal fade" id="addPeerModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="exampleModalLabel">Add Network Peer</h5>
|
||||
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<ul class="nav nav-tabs" id="myTab" role="tablist">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" id="add-peer-form-tab" data-toggle="tab" href="#addPeerform" role="tab" aria-controls="add-peer-form-tab" aria-selected="true">Form</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" id="add-peer-json-tab" data-toggle="tab" href="#addPeerJson" role="tab" aria-controls="add-peer-json-tab" aria-selected="false">JSON</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="tab-content" id="myTabContent">
|
||||
<div class="tab-pane fade show active" id="addPeerform" role="tabpanel" aria-labelledby="form-tab">
|
||||
<form id="addPeerForm">
|
||||
<br />
|
||||
<div class="row">
|
||||
<label class="col-3 col-form-label text-right">Name: <span class="text-danger">*</span></label>
|
||||
<div class="col-7">
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control" placeholder="" name="name">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-1">
|
||||
<i class="far fa-sm fa-question-circle" title='(Required) - Enter in the name of the listening network address.'></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<label class="col-3 col-form-label text-right">Description: </label>
|
||||
<div class="col-7">
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control" placeholder="" name="description">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-1">
|
||||
<i class="far fa-sm fa-question-circle" title='Enter in a description for the network load balancer.'></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<label class="col-3 col-form-label text-right">Target Network: </label>
|
||||
<div class="col-7">
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control" placeholder="" name="target_network">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-1">
|
||||
<i class="far fa-sm fa-question-circle" title='Enter in a description for the network load balancer.'></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<label class="col-3 col-form-label text-right">Target Project: </label>
|
||||
<div class="col-7">
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control" placeholder="" name="target_project">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-1">
|
||||
<i class="far fa-sm fa-question-circle" title='Enter in a description for the network load balancer.'></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-secondary" type="button" data-dismiss="modal">Cancel</button>
|
||||
<a class="btn btn-primary" href="#" onclick="addItem('peer')" data-dismiss="modal">Submit</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-pane fade" id="addPeerJson" role="tabpanel" aria-labelledby="json-tab">
|
||||
<br />
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="form-group text-right">
|
||||
<pre>
|
||||
<textarea name="json" class="form-control" id="jsonCreatePeerInput" rows="16" placeholder="Enter JSON data"></textarea>
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-secondary" type="button" data-dismiss="modal">Cancel</button>
|
||||
<a class="btn btn-primary" href="#" onclick="createItemUsingJSON('peer')" data-dismiss="modal">Submit</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Edit Forward Modal-->
|
||||
<div class="modal fade" id="editForwardModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="exampleModalLabel">Edit Network Forward</h5>
|
||||
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<ul class="nav nav-tabs" id="myTab" role="tablist">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" id="json-edit-tab" data-toggle="tab" href="#json-edit" role="tab" aria-controls="json-edit" aria-selected="false">JSON</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="tab-content" id="myTabContent">
|
||||
<div class="tab-pane fade show active" id="json-edit" role="tabpanel" aria-labelledby="json-edit-tab">
|
||||
<br />
|
||||
<div class="row">
|
||||
<label class="col-4 col-form-label" id="forwardNameEditInput"></label>
|
||||
<div class="col-12">
|
||||
<div class="form-group text-right">
|
||||
<pre>
|
||||
<textarea name="json" class="form-control" id="forwardJsonInput" rows="16" ></textarea>
|
||||
</pre>
|
||||
<input type="hidden" id="forwardNameHiddenInput" name="forward_name_hidden">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-secondary" type="button" data-dismiss="modal">Cancel</button>
|
||||
<a class="btn btn-primary" href="#" onclick="updateForward()" data-dismiss="modal">Submit</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Edit Load Balancer Modal-->
|
||||
<div class="modal fade" id="editLoadBalancerModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="exampleModalLabel">Edit Network Load Balancer</h5>
|
||||
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<ul class="nav nav-tabs" id="myTab" role="tablist">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" id="json-edit-tab" data-toggle="tab" href="#json-edit" role="tab" aria-controls="json-edit" aria-selected="false">JSON</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="tab-content" id="myTabContent">
|
||||
<div class="tab-pane fade show active" id="json-edit" role="tabpanel" aria-labelledby="json-edit-tab">
|
||||
<br />
|
||||
<div class="row">
|
||||
<label class="col-4 col-form-label" id="loadBalancerNameEditInput"></label>
|
||||
<div class="col-12">
|
||||
<div class="form-group text-right">
|
||||
<pre>
|
||||
<textarea name="json" class="form-control" id="loadBalancerJsonInput" rows="16" ></textarea>
|
||||
</pre>
|
||||
<input type="hidden" id="loadBalancerNameHiddenInput" name="load_balancer_name_hidden">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-secondary" type="button" data-dismiss="modal">Cancel</button>
|
||||
<a class="btn btn-primary" href="#" onclick="updateLoadBalancer()" data-dismiss="modal">Submit</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Edit Peer Modal-->
|
||||
<div class="modal fade" id="editPeerModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="exampleModalLabel">Edit Network Peer</h5>
|
||||
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<ul class="nav nav-tabs" id="myTab" role="tablist">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" id="json-edit-tab" data-toggle="tab" href="#json-edit" role="tab" aria-controls="json-edit" aria-selected="false">JSON</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="tab-content" id="myTabContent">
|
||||
<div class="tab-pane fade show active" id="json-edit" role="tabpanel" aria-labelledby="json-edit-tab">
|
||||
<br />
|
||||
<div class="row">
|
||||
<label class="col-4 col-form-label" id="peerNameEditInput"></label>
|
||||
<div class="col-12">
|
||||
<div class="form-group text-right">
|
||||
<pre>
|
||||
<textarea name="json" class="form-control" id="peerJsonInput" rows="16" ></textarea>
|
||||
</pre>
|
||||
<input type="hidden" id="peerNameHiddenInput" name="peer_name_hidden">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-secondary" type="button" data-dismiss="modal">Cancel</button>
|
||||
<a class="btn btn-primary" href="#" onclick="updatePeer()" data-dismiss="modal">Submit</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -1889,7 +1889,7 @@
|
|||
<div class="modal-dialog modal-xl" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="exampleModalLabel">Edit Container</h5>
|
||||
<h5 class="modal-title" id="exampleModalLabel">Edit Virtual Machine</h5>
|
||||
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
|
|
|
@ -257,7 +257,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="col-1">
|
||||
<i class="far fa-sm fa-question-circle" title='Select the LXD cluster member or @group to deploy this container on. Default: none'></i>
|
||||
<i class="far fa-sm fa-question-circle" title='Select the LXD cluster member or @group to deploy this virtual machine on. Default: none'></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
243
lxconsole/templates/network-zones.html
Normal file
243
lxconsole/templates/network-zones.html
Normal file
|
@ -0,0 +1,243 @@
|
|||
{% extends "main.html" %}
|
||||
|
||||
{% block header %}
|
||||
<div class="row mb-2">
|
||||
<div class="col-sm-6">
|
||||
<h1>{{ page_title | safe }}</h1>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<a class="btn btn-outline-primary float-sm-right mr-4" href="#" data-toggle="modal" data-target="#addModal" title="Add Network Zone" aria-hidden="true">
|
||||
<i class="fas fa-plus fa-sm fa-fw"></i> Network Zone
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock header %}
|
||||
|
||||
{% block content %}
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Network Zones</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-tool" onclick="reloadPageContent()" title="Refresh">
|
||||
<i class="fas fa-sync"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<table class="table table-hover" id="myDataTable" width="100%" cellspacing="0">
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock content %}
|
||||
|
||||
{% block modal %}
|
||||
{% include 'modals/network-zones.html' %}
|
||||
{% endblock modal %}
|
||||
|
||||
{% block script %}
|
||||
<script>
|
||||
var reloadTime = 10000;
|
||||
const queryString = window.location.search;
|
||||
const urlParams = new URLSearchParams(queryString);
|
||||
const serverId = urlParams.get('id');
|
||||
const project = urlParams.get('project');
|
||||
var editedNetworkZone = ''
|
||||
applySidebarStyles();
|
||||
applySidebarLinks();
|
||||
populateSidebarLinks();
|
||||
populateNavbarLinks();
|
||||
|
||||
function reloadPageContent() {
|
||||
//Clear the automatic page reload
|
||||
clearTimeout(pageReloadTimeout);
|
||||
|
||||
//Reload the datatables content
|
||||
$('#myDataTable').DataTable().ajax.reload(null, false);
|
||||
|
||||
//Set the automatic page reload
|
||||
pageReloadTimeout = setTimeout(() => { reloadPageContent(); }, reloadTime);
|
||||
}
|
||||
|
||||
function loadPageContent(){
|
||||
|
||||
//Display the current project
|
||||
$("#selectedProject").text(project);
|
||||
|
||||
//Populate the Server dropdown
|
||||
$.getJSON("../api/servers/list_servers?id="+serverId, function (data) {
|
||||
data = data.data
|
||||
for (var index = 0; index < data.length; index++) {
|
||||
if (data[index].name == '')
|
||||
optionText = data[index].addr
|
||||
else
|
||||
optionText = data[index].name
|
||||
if (data[index].id == serverId)
|
||||
$('#serverListNav').append('<option value="' + data[index].id + '" selected="selected">' + optionText + '</option>');
|
||||
else
|
||||
$('#serverListNav').append('<option value="' + data[index].id + '">' + optionText + '</option>');
|
||||
}
|
||||
})
|
||||
|
||||
//Populate the Project dropdown
|
||||
$.getJSON("../api/projects/list_projects?id="+serverId+"&project="+project, function (data) {
|
||||
data = data.metadata
|
||||
for (var index = 0; index < data.length; index++) {
|
||||
optionText = data[index].replace('/1.0/projects/','');
|
||||
if (optionText == project)
|
||||
$('#projectListNav').append('<option value="' + optionText + '" selected="selected">' + optionText + '</option>');
|
||||
else
|
||||
$('#projectListNav').append('<option value="' + optionText + '">' + optionText + '</option>');
|
||||
}
|
||||
})
|
||||
|
||||
// Configure Datatable
|
||||
$('#myDataTable').DataTable({
|
||||
ajax: {
|
||||
url: "../api/network-zones/list_network_zones?id="+serverId+"&project=" + project + "&recursion=1",
|
||||
dataType: "json",
|
||||
dataSrc: "metadata",
|
||||
contentType: "application/json"
|
||||
},
|
||||
columns: [
|
||||
{ title: "Name", data: function (row, type, set) {
|
||||
if (row.hasOwnProperty('name')) {
|
||||
if (row.name)
|
||||
return row.name
|
||||
}
|
||||
return '-'
|
||||
},
|
||||
},
|
||||
{ title: "Description", data: function (row, type, set) {
|
||||
if (row.hasOwnProperty('description')) {
|
||||
if (row.description)
|
||||
return row.description
|
||||
}
|
||||
return '-'
|
||||
},
|
||||
},
|
||||
|
||||
{ title: "Actions", data: function (row, type, set) {
|
||||
links = ''
|
||||
if (row.hasOwnProperty('name')) {
|
||||
links += '<a href="#" onclick=editItem(\''+row.name+'\')><i class="fas fa-edit fa-lg" style="color:#ddd" title="Edit" aria-hidden="true"></i></a>' +
|
||||
' ' + ' ' +
|
||||
'<a href="#" onclick=confirmDeleteItem(\''+row.name+'\')><i class="fas fa-trash-alt fa-lg" style="color:#ddd" title="Delete" aria-hidden="true"></i></a>'
|
||||
}
|
||||
return links
|
||||
},
|
||||
},
|
||||
|
||||
],
|
||||
order: [],
|
||||
});
|
||||
|
||||
//Set reload page content
|
||||
pageReloadTimeout = setTimeout(() => { reloadPageContent(); }, reloadTime);
|
||||
|
||||
}
|
||||
|
||||
function addItem(){
|
||||
console.log("Info: adding new item");
|
||||
data = $('#addForm').serialize();
|
||||
$.post("../api/network-zones/add_network_zone?id="+serverId+"&project="+project, data, function (data) {
|
||||
console.log(data)
|
||||
if (data.error_code >= 400){
|
||||
alert(data.error);
|
||||
}
|
||||
//Sync type
|
||||
reloadPageContent();
|
||||
});
|
||||
}
|
||||
|
||||
function confirmDeleteItem(name){
|
||||
console.log("Info: confirming deletion of item " + name);
|
||||
$("#deleteQuestionText").text("Are you sure you want to remove the network zone " + name + "?");
|
||||
$("#networkZone").val(name);
|
||||
$("#deleteModal").modal('show');
|
||||
}
|
||||
|
||||
function createItemUsingJSON(){
|
||||
var json = $("#jsonCreateInput").val();
|
||||
console.log("Info: adding new network zone");
|
||||
$.post("../api/network-zones/add_network_zone?id="+serverId+"&project="+project, { json: json }, function (data) {
|
||||
console.log(data);
|
||||
if (data.error_code >= 400){
|
||||
alert(data.error);
|
||||
}
|
||||
//Sync type
|
||||
reloadPageContent();
|
||||
});
|
||||
}
|
||||
|
||||
function deleteItem(){
|
||||
name = $("#networkZone").val();
|
||||
console.log("Info: deleting item " + name);
|
||||
$.post("../api/network-zones/delete_network_zone?id=" + serverId + "&project=" + project, { name: name }, function (data) {
|
||||
console.log(data);
|
||||
if (data.error_code >= 400){
|
||||
alert(data.error);
|
||||
}
|
||||
//Sync type
|
||||
reloadPageContent();
|
||||
});
|
||||
}
|
||||
|
||||
function editItem(name){
|
||||
editedNetworkZone = name
|
||||
console.log("Info: loading network zone " + name);
|
||||
$.post("../api/network-zones/load_network_zone?id=" + serverId + "&project=" + project, { name: name }, function (data) {
|
||||
console.log(data);
|
||||
if (data.error_code >= 400){
|
||||
alert(data.error);
|
||||
}
|
||||
$("#jsonInput").val(JSON.stringify(data.metadata, null, 2));
|
||||
$("#editModal").modal('show');
|
||||
});
|
||||
}
|
||||
|
||||
function renameItem(){
|
||||
name = editedNetworkZone
|
||||
console.log("Info: renaming network zone");
|
||||
data = $('#renameForm').serialize();
|
||||
$.post("../api/network-zones/update_network_zone?id=" + serverId + "&project=" + project + "&name=" + encodeURI(name), data, function (data) {
|
||||
console.log(data)
|
||||
if (data.error_code >= 400){
|
||||
alert(data.error);
|
||||
}
|
||||
//Sync type
|
||||
reloadPageContent();
|
||||
});
|
||||
}
|
||||
|
||||
function updateItem(){
|
||||
name = editedNetworkZone
|
||||
var updatedJSON = $("#jsonInput").val();
|
||||
console.log("Info: updating netowrk zone");
|
||||
$.post("../api/network-zones/update_network_zone?id=" + serverId + "&project=" + project + "&name=" + encodeURI(name), { json: updatedJSON }, function (data) {
|
||||
console.log(data);
|
||||
if (data.error_code >= 400){
|
||||
alert(data.error);
|
||||
}
|
||||
//Sync type
|
||||
reloadPageContent();
|
||||
});
|
||||
}
|
||||
|
||||
$(document).ready(function(){
|
||||
|
||||
//If id or project variables are missing redirect to servers page
|
||||
if (!serverId || !project) {
|
||||
window.location.href = 'servers';
|
||||
}
|
||||
else {
|
||||
loadPageContent()
|
||||
operationStatusCheck()
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
{% endblock script %}
|
758
lxconsole/templates/network.html
Normal file
758
lxconsole/templates/network.html
Normal file
|
@ -0,0 +1,758 @@
|
|||
{% extends "main.html" %}
|
||||
|
||||
{% block header %}
|
||||
<div class="row mb-2">
|
||||
<div class="col-sm-6">
|
||||
<h1>{{ page_title | safe }} <span id="network_title"></span></h1>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
|
||||
<a class="btn btn-outline-primary dropdown-toggle float-sm-right ml-2 mr-4" href="#" role="button" id="dropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" title="Actions">
|
||||
Network Actions
|
||||
</a>
|
||||
<div class="dropdown-menu dropdown-menu-right shadow animated--fade-in" aria-labelledby="dropdownMenuLink">
|
||||
<a class="dropdown-item text-primary" href="#" data-toggle="modal" data-target="#addLoadBalancerModal" id="addLoadBalancer"><i class="fas fa-save fa-sm fa-fw mr-2"></i>Add Load Balancer</a>
|
||||
<a class="dropdown-item text-primary" href="#" data-toggle="modal" data-target="#addForwardModal" id="addForward"><i class="fas fa-save fa-sm fa-fw mr-2"></i>Add Forward</a>
|
||||
<a class="dropdown-item text-primary" href="#" data-toggle="modal" data-target="#addPeerModal" id="addPeer"><i class="fas fa-save fa-sm fa-fw mr-2"></i>Add Peer</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
{% endblock header %}
|
||||
|
||||
{% block content %}
|
||||
<div class="col-12">
|
||||
|
||||
<nav>
|
||||
<div class="nav nav-tabs" id="nav-page-tab" role="tablist">
|
||||
<a class="nav-item nav-link active" id="nav-home-tab" data-toggle="tab" href="#nav-home" role="tab" aria-controls="nav-home" aria-selected="true">Home</a>
|
||||
<a class="nav-item nav-link" id="nav-forwards-tab" data-toggle="tab" href="#nav-forwards" role="tab" aria-controls="nav-forwards" aria-selected="false">Forwards</a>
|
||||
<a class="nav-item nav-link" id="nav-load-balancers-tab" data-toggle="tab" href="#nav-load-balancers" role="tab" aria-controls="nav-load-balancers" aria-selected="false">Load Balancers</a>
|
||||
<a class="nav-item nav-link" id="nav-peers-tab" data-toggle="tab" href="#nav-peers" role="tab" aria-controls="nav-peers" aria-selected="false">Peers</a>
|
||||
</div>
|
||||
</nav>
|
||||
<div class="tab-content" id="nav-page-content">
|
||||
<div class="tab-pane fade show active" id="nav-home" role="tabpanel" aria-labelledby="nav-home-tab">
|
||||
<br />
|
||||
<div class="row">
|
||||
<div class="col-9">
|
||||
|
||||
<!-- DHCP Leases Card-->
|
||||
<div class="card" id="dhcpLeasesCard">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title text-primary" data-card-widget="collapse">
|
||||
DHCP Leases
|
||||
</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-tool" data-card-widget="collapse"><i class="fas fa-minus"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover" id="dhcpLeasesTable" width="100%" cellspacing="0">
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="col-3">
|
||||
|
||||
<div class="accordion" id="accordionExample">
|
||||
|
||||
<!-- Network State Card-->
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title text-primary" data-card-widget="collapse">
|
||||
Network State
|
||||
</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-tool" data-card-widget="collapse"><i class="fas fa-minus"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<table class="table table-sm h6">
|
||||
<tr><td class="pr-3">HWAddr:</td> <td><span id="hwaddr">-</span></td></tr>
|
||||
<tr><td class="pr-3">MTU:</td> <td><span id="mtu">-</span></td></tr>
|
||||
<tr><td class="pr-3">State:</td> <td><span id="state">-</span></td></tr>
|
||||
<tr><td class="pr-3">Type:</td> <td><span id="type">-</span></td></tr>
|
||||
<tr><td class="pr-3">Bond:</td> <td><span id="bond">-</span></td></tr>
|
||||
<tr><td class="pr-3">OVN:</td> <td><span id="ovn">-</span></td></tr>
|
||||
<tr><td class="pr-3">VLAN:</td> <td><span id="vlan">-</span></td></tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Network Counters Card-->
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title text-primary" data-card-widget="collapse">
|
||||
Network Counters
|
||||
</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-tool" data-card-widget="collapse"><i class="fas fa-minus"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<table class="table table-sm h6">
|
||||
<tr><td class="pr-3">bytes_received:</td> <td><span id="counters_bytes_received">-</span></td></tr>
|
||||
<tr><td class="pr-3">bytes_sent:</td> <td><span id="counters_bytes_sent">-</span></td></tr>
|
||||
<tr><td class="pr-3">packets_received:</td> <td><span id="packets_bytes_received">-</span></td></tr>
|
||||
<tr><td class="pr-3">packets_sent:</td> <td><span id="packets_bytes_sent">-</span></td></tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Network Bridge Card-->
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title text-primary" data-card-widget="collapse">
|
||||
Network Bridge
|
||||
</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-tool" data-card-widget="collapse"><i class="fas fa-minus"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<table class="table table-sm h6">
|
||||
<tr><td class="pr-3">forward_delay:</td> <td><span id="bridge_forward_delay">-</span></td></tr>
|
||||
<tr><td class="pr-3">id:</td> <td><span id="bridge_id">-</span></td></tr>
|
||||
<tr><td class="pr-3">stp:</td> <td><span id="bridge_stp">-</span></td></tr>
|
||||
<tr><td class="pr-3">upper_devices:</td> <td><span id="bridge_upper_devices">-</span></td></tr>
|
||||
<tr><td class="pr-3">vlan_default:</td> <td><span id="bridge_vlan_default">-</span></td></tr>
|
||||
<tr><td class="pr-3">vlan_filtering:</td> <td><span id="bridge_vlan_filtering">-</span></td></tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-pane fade" id="nav-forwards" role="tabpanel" aria-labelledby="nav-forwards-tab">
|
||||
<br />
|
||||
<div class="col-12">
|
||||
<!-- Forwards Card-->
|
||||
<div class="card" id="forwardsCard">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title text-primary" data-card-widget="collapse">
|
||||
Network Forwards <span class="text-secondary small">(Available only on Bridge or OVN networks)</span>
|
||||
</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-tool" data-card-widget="collapse"><i class="fas fa-minus"></i></button>
|
||||
<button type="button" class="btn btn-tool" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
<i class="fa fa-bars"></i>
|
||||
</button>
|
||||
<div class="dropdown-menu dropdown-menu-right">
|
||||
<a href="#" class="dropdown-item" data-toggle="modal" data-target="#addForwardModal" title="Create Forward">Create Forward</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover" id="forwardsTable" width="100%" cellspacing="0">
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="tab-pane fade" id="nav-load-balancers" role="tabpanel" aria-labelledby="nav-load-balancers-tab">
|
||||
<br />
|
||||
<div class="col-12">
|
||||
<!-- Load Balancers Card-->
|
||||
<div class="card" id="loadBalancersCard">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title text-primary" data-card-widget="collapse">
|
||||
Network Load Balancers <span class="text-secondary small">(Available only on OVN networks)</span>
|
||||
</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-tool" data-card-widget="collapse"><i class="fas fa-minus"></i></button>
|
||||
<button type="button" class="btn btn-tool" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
<i class="fa fa-bars"></i>
|
||||
</button>
|
||||
<div class="dropdown-menu dropdown-menu-right">
|
||||
<a href="#" class="dropdown-item" data-toggle="modal" data-target="#addLoadBalancerModal" title="Create Load Balancer">Create Load Balancer</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover" id="loadBalancersTable" width="100%" cellspacing="0">
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="tab-pane fade" id="nav-peers" role="tabpanel" aria-labelledby="nav-peers-tab">
|
||||
<br />
|
||||
<div class="col-12">
|
||||
<!-- Peers Card-->
|
||||
<div class="card" id="peersCard">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title text-primary" data-card-widget="collapse">
|
||||
Network Peers <span class="text-secondary small">(Available only on OVN networks)</span>
|
||||
</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-tool" data-card-widget="collapse"><i class="fas fa-plus"></i></button>
|
||||
<button type="button" class="btn btn-tool" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
<i class="fa fa-bars"></i>
|
||||
</button>
|
||||
<div class="dropdown-menu dropdown-menu-right">
|
||||
<a href="#" class="dropdown-item" data-toggle="modal" data-target="#addPeerModal" title="Create Peer">Create Peer</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover" id="peersTable" width="100%" cellspacing="0">
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
{% endblock content %}
|
||||
|
||||
{% block modal %}
|
||||
{% include 'modals/network.html' %}
|
||||
{% endblock modal %}
|
||||
|
||||
{% block script %}
|
||||
|
||||
<script>
|
||||
|
||||
var reloadTime = 10000;
|
||||
const queryString = window.location.search;
|
||||
const urlParams = new URLSearchParams(queryString);
|
||||
const serverId = urlParams.get('id');
|
||||
const project = urlParams.get('project');
|
||||
const network = urlParams.get('network');
|
||||
const network_type = urlParams.get('network_type');
|
||||
var editedNetwork
|
||||
|
||||
populateSidebarLinks();
|
||||
populateNavbarLinks();
|
||||
applySidebarStyles();
|
||||
applySidebarLinks();
|
||||
|
||||
function reloadPageContent() {
|
||||
|
||||
//Clear the automatic page reload
|
||||
clearTimeout(pageReloadTimeout);
|
||||
|
||||
//Load Network State
|
||||
loadNetworkState()
|
||||
|
||||
loadDhcpLeasesTable()
|
||||
loadLoadBalancersTable()
|
||||
loadForwardsTable()
|
||||
loadPeersTables()
|
||||
|
||||
//Set the automatic page reload
|
||||
pageReloadTimeout = setTimeout(() => { reloadPageContent(); }, reloadTime);
|
||||
}
|
||||
|
||||
function loadPageContent(){
|
||||
|
||||
//Populate the Server dropdown
|
||||
$.getJSON("../api/servers/list_servers?id="+serverId, function (data) {
|
||||
data = data.data
|
||||
for (var index = 0; index < data.length; index++) {
|
||||
if (data[index].name == '')
|
||||
optionText = data[index].addr
|
||||
else
|
||||
optionText = data[index].name
|
||||
if (data[index].id == serverId){
|
||||
$('#serverListNav').append('<option value="' + data[index].id + '" selected="selected">' + optionText + '</option>');
|
||||
}
|
||||
else
|
||||
$('#serverListNav').append('<option value="' + data[index].id + '">' + optionText + '</option>');
|
||||
}
|
||||
})
|
||||
|
||||
//Populate the Project dropdown
|
||||
$.getJSON("../api/projects/list_projects?id="+serverId+"&project="+project, function (data) {
|
||||
data = data.metadata
|
||||
for (var index = 0; index < data.length; index++) {
|
||||
optionText = data[index].replace('/1.0/projects/','');
|
||||
if (optionText == project)
|
||||
$('#projectListNav').append('<option value="' + optionText + '" selected="selected">' + optionText + '</option>');
|
||||
else
|
||||
$('#projectListNav').append('<option value="' + optionText + '">' + optionText + '</option>');
|
||||
}
|
||||
})
|
||||
|
||||
//Load Network State
|
||||
loadNetworkState()
|
||||
|
||||
//Load Home Tab Tables
|
||||
loadDhcpLeasesTable()
|
||||
|
||||
//Set reload page content
|
||||
pageReloadTimeout = setTimeout(() => { reloadPageContent(); }, reloadTime);
|
||||
|
||||
}
|
||||
|
||||
|
||||
function loadNetworkState() {
|
||||
$.get("../api/network/get_network_state?id="+serverId+"&project="+project+"&name="+network+"&recursion=1", function (data) {
|
||||
|
||||
data = data.metadata;
|
||||
console.log(data)
|
||||
|
||||
if (data.hasOwnProperty('hwaddr') && data.hwaddr) { $("#hwaddr").text(data.hwaddr); }
|
||||
if (data.hasOwnProperty('mtu') && data.mtu) { $("#mtu").text(data.mtu); }
|
||||
if (data.hasOwnProperty('state') && data.state) { $("#state").text(data.state); }
|
||||
if (data.hasOwnProperty('type') && data.type) { $("#type").text(data.type); }
|
||||
if (data.hasOwnProperty('bond') && data.bond) { $("#bond").text(data.bond); }
|
||||
if (data.hasOwnProperty('ovn') && data.ovn) { $("#ovn").text(data.ovn); }
|
||||
if (data.hasOwnProperty('vlan') && data.vlan) { $("#vlan").text(data.vlan); }
|
||||
|
||||
if (data.hasOwnProperty('counters') && data.counters){
|
||||
dataCounters = data.counters;
|
||||
if (dataCounters.hasOwnProperty('bytes_received') && dataCounters.bytes_received) { $("#counters_bytes_received").text(dataCounters['bytes_received']); }
|
||||
if (dataCounters.hasOwnProperty('bytes_sent') && dataCounters.bytes_sent) { $("#counters_bytes_sent").text(dataCounters['bytes_sent']); }
|
||||
if (dataCounters.hasOwnProperty('packets_received') && dataCounters.packets_received) { $("#packets_bytes_received").text(dataCounters['packets_received']); }
|
||||
if (dataCounters.hasOwnProperty('packets_sent') && dataCounters.packets_sent) { $("#packets_bytes_sent").text(dataCounters['packets_sent']); }
|
||||
}
|
||||
|
||||
if (data.hasOwnProperty('bridge') && data.bridge){
|
||||
dataBridge = data.bridge;
|
||||
if (dataBridge.hasOwnProperty('forward_delay') && dataBridge.forward_delay) { $("#bridge_forward_delay").text(dataBridge['forward_delay']); }
|
||||
if (dataBridge.hasOwnProperty('id') && dataBridge.id) { $("#bridge_id").text(dataBridge['id']); }
|
||||
if (dataBridge.hasOwnProperty('stp')) { $("#bridge_stp").text(dataBridge['stp']); } //Boolean
|
||||
if (dataBridge.hasOwnProperty('upper_devices') && dataBridge.upper_devices) { $("#bridge_upper_devices").text(dataBridge['upper_devices'].join(', ')); } //Array
|
||||
if (dataBridge.hasOwnProperty('id') && dataBridge.id) { $("#bridge_id").text(dataBridge['id']); }
|
||||
if (dataBridge.hasOwnProperty('vlan_default') && dataBridge.vlan_default) { $("#bridge_vlan_default").text(dataBridge['vlan_default']); }
|
||||
if (dataBridge.hasOwnProperty('vlan_filtering') && dataBridge.vlan_filtering) { $("#bridge_vlan_filtering").text(dataBridge['vlan_filtering']); }
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
function loadDhcpLeasesTable() {
|
||||
if ( ! $.fn.DataTable.isDataTable( '#dhcpLeasesTable' ) ) {
|
||||
//Load DHCP Leases Table
|
||||
$('#dhcpLeasesTable').DataTable({
|
||||
ajax: {
|
||||
url: "../api/network/list_network_leases?id="+serverId+"&project="+project+"&name="+network,
|
||||
dataType: "json",
|
||||
dataSrc: "metadata",
|
||||
contentType: "application/json"
|
||||
},
|
||||
rowId: 'id',
|
||||
stateSave: true,
|
||||
columns: [
|
||||
{ title: "Address", data: function (row, type, set) {
|
||||
if (row.hasOwnProperty('address')) {
|
||||
if (row.address)
|
||||
return row.address
|
||||
}
|
||||
return '-'
|
||||
},
|
||||
},
|
||||
{ title: "Hostname", data: function (row, type, set) {
|
||||
if (row.hasOwnProperty('hostname')) {
|
||||
if (row.hostname)
|
||||
return row.hostname
|
||||
}
|
||||
return '-'
|
||||
},
|
||||
},
|
||||
{ title: "HWAddr", data: function (row, type, set) {
|
||||
if (row.hasOwnProperty('hwaddr')) {
|
||||
if (row.hwaddr)
|
||||
return row.hwaddr
|
||||
}
|
||||
return '-'
|
||||
},
|
||||
},
|
||||
{ title: "Location", data: function (row, type, set) {
|
||||
if (row.hasOwnProperty('location')) {
|
||||
if (row.location)
|
||||
return row.location
|
||||
}
|
||||
return '-'
|
||||
},
|
||||
},
|
||||
{ title: "Type", data: function (row, type, set) {
|
||||
if (row.hasOwnProperty('type')) {
|
||||
if (row.type)
|
||||
return row.type
|
||||
}
|
||||
return '-'
|
||||
},
|
||||
},
|
||||
],
|
||||
order: [],
|
||||
});
|
||||
}
|
||||
else {
|
||||
$('#dhcpLeasesTable').DataTable().ajax.reload(null, false);
|
||||
}
|
||||
}
|
||||
|
||||
function loadLoadBalancersTable(){
|
||||
if ( ! $.fn.DataTable.isDataTable( '#loadBalancersTable' ) ) {
|
||||
//Load Load Balancers Table
|
||||
var loadBalancersTable = $('#loadBalancersTable').DataTable({
|
||||
ajax: {
|
||||
url: "../api/network/list_network_load_balancers?id="+serverId+"&project="+project+"&name="+network+"&recursion=1",
|
||||
dataType: "json",
|
||||
dataSrc: "metadata",
|
||||
contentType: "application/json"
|
||||
},
|
||||
stateSave: true,
|
||||
columns: [
|
||||
{ title: "Listen Address", data: function (row, type, set) {
|
||||
if (row.hasOwnProperty('listen_address')) {
|
||||
if (row.listen_address)
|
||||
return row.listen_address
|
||||
}
|
||||
return '-'
|
||||
},
|
||||
},
|
||||
{ title: "Description", data: function (row, type, set) {
|
||||
if (row.hasOwnProperty('description')) {
|
||||
if (row.description)
|
||||
return row.description
|
||||
}
|
||||
return '-'
|
||||
},
|
||||
},
|
||||
{ title: "Location", data: function (row, type, set) {
|
||||
if (row.hasOwnProperty('location')) {
|
||||
if (row.location)
|
||||
return row.location
|
||||
}
|
||||
return '-'
|
||||
},
|
||||
},
|
||||
{ title: "Actions", data: function (row, type, set) {
|
||||
links = ''
|
||||
if (row.hasOwnProperty('listen_address')) {
|
||||
if (row.listen_address){
|
||||
links = '<a href="#" onclick=editLoadBalancer(\''+row.listen_address+'\')><i class="fas fa-edit fa-lg" style="color:#ddd" title="Edit" aria-hidden="true"></i></a>' +
|
||||
' ' + ' ' +
|
||||
'<a href="#" onclick=deleteItem(\''+row.listen_address+'\',\'load_balancer\')><i class="fas fa-trash-alt fa-lg" style="color:#ddd" title="Delete" aria-hidden="true"></i></a>'
|
||||
}
|
||||
}
|
||||
return links
|
||||
},
|
||||
},
|
||||
],
|
||||
order: [],
|
||||
});
|
||||
}
|
||||
else {
|
||||
$('#loadBalancersTable').DataTable().ajax.reload(null, false);
|
||||
}
|
||||
}
|
||||
|
||||
function loadForwardsTable() {
|
||||
if ( ! $.fn.DataTable.isDataTable( '#forwardsTable' ) ) {
|
||||
//Load Forwards Table
|
||||
var forwardsTable = $('#forwardsTable').DataTable({
|
||||
ajax: {
|
||||
url: "../api/network/list_network_forwards?id="+serverId+"&project="+project+"&name="+network+"&recursion=1",
|
||||
dataType: "json",
|
||||
dataSrc: "metadata",
|
||||
contentType: "application/json"
|
||||
},
|
||||
stateSave: true,
|
||||
columns: [
|
||||
{ title: "Listen Address", data: function (row, type, set) {
|
||||
if (row.hasOwnProperty('listen_address')) {
|
||||
if (row.listen_address)
|
||||
return row.listen_address
|
||||
}
|
||||
return '-'
|
||||
},
|
||||
},
|
||||
{ title: "Description", data: function (row, type, set) {
|
||||
if (row.hasOwnProperty('description')) {
|
||||
if (row.description)
|
||||
return row.description
|
||||
}
|
||||
return '-'
|
||||
},
|
||||
},
|
||||
{ title: "Location", data: function (row, type, set) {
|
||||
if (row.hasOwnProperty('location')) {
|
||||
if (row.location)
|
||||
return row.location
|
||||
}
|
||||
return '-'
|
||||
},
|
||||
},
|
||||
{ title: "Actions", data: function (row, type, set) {
|
||||
links = ''
|
||||
if (row.hasOwnProperty('listen_address')) {
|
||||
if (row.listen_address){
|
||||
links = '<a href="#" onclick=editForward(\''+row.listen_address+'\')><i class="fas fa-edit fa-lg" style="color:#ddd" title="Edit" aria-hidden="true"></i></a>' +
|
||||
' ' + ' ' +
|
||||
'<a href="#" onclick=deleteItem(\''+row.listen_address+'\',\'forward\')><i class="fas fa-trash-alt fa-lg" style="color:#ddd" title="Delete" aria-hidden="true"></i></a>'
|
||||
}
|
||||
}
|
||||
return links
|
||||
},
|
||||
},
|
||||
],
|
||||
order: [],
|
||||
});
|
||||
}
|
||||
else {
|
||||
$('#forwardsTable').DataTable().ajax.reload(null, false);
|
||||
}
|
||||
}
|
||||
|
||||
function loadPeersTables() {
|
||||
if ( ! $.fn.DataTable.isDataTable( '#peersTable' ) ) {
|
||||
//Load Peers Table
|
||||
$('#peersTable').DataTable({
|
||||
ajax: {
|
||||
url: "../api/network/list_network_peers?id="+serverId+"&project="+project+"&name="+network+"&recursion=1",
|
||||
dataType: "json",
|
||||
dataSrc: "metadata",
|
||||
contentType: "application/json"
|
||||
},
|
||||
rowId: 'id',
|
||||
stateSave: true,
|
||||
columns: [
|
||||
{ title: "Name", data: function (row, type, set) {
|
||||
if (row.hasOwnProperty('name')) {
|
||||
if (row.name)
|
||||
return row.name
|
||||
}
|
||||
return '-'
|
||||
},
|
||||
},
|
||||
{ title: "Description", data: function (row, type, set) {
|
||||
if (row.hasOwnProperty('description')) {
|
||||
if (row.description)
|
||||
return row.description
|
||||
}
|
||||
return '-'
|
||||
},
|
||||
},
|
||||
{ title: "Status", data: function (row, type, set) {
|
||||
if (row.hasOwnProperty('status')) {
|
||||
if (row.status)
|
||||
return row.status
|
||||
}
|
||||
return '-'
|
||||
},
|
||||
},
|
||||
{ title: "Target Network", data: function (row, type, set) {
|
||||
if (row.hasOwnProperty('target_network')) {
|
||||
if (row.target_network)
|
||||
return row.target_network
|
||||
}
|
||||
return '-'
|
||||
},
|
||||
},
|
||||
{ title: "Target Project", data: function (row, type, set) {
|
||||
if (row.hasOwnProperty('target_project')) {
|
||||
if (row.target_project)
|
||||
return row.target_project
|
||||
}
|
||||
return '-'
|
||||
},
|
||||
},
|
||||
{ title: "Actions", data: function (row, type, set) {
|
||||
links = ''
|
||||
if (row.hasOwnProperty('name')) {
|
||||
if (row.name){
|
||||
links = '<a href="#" onclick=editPeer(\''+row.name+'\')><i class="fas fa-edit fa-lg" style="color:#ddd" title="Edit" aria-hidden="true"></i></a>' +
|
||||
' ' + ' ' +
|
||||
'<a href="#" onclick=deleteItem(\''+row.name+'\',\'peer\')><i class="fas fa-trash-alt fa-lg" style="color:#ddd" title="Delete" aria-hidden="true"></i></a>'
|
||||
}
|
||||
}
|
||||
return links
|
||||
},
|
||||
},
|
||||
],
|
||||
order: [],
|
||||
});
|
||||
}
|
||||
else {
|
||||
$('#peersTable').DataTable().ajax.reload(null, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
function addItem(type){
|
||||
console.log("Info: adding new " + type);
|
||||
if (type == 'forward')
|
||||
data = $('#addForwardForm').serialize();
|
||||
else if (type == 'load_balancer')
|
||||
data = $('#addLoadBalancerForm').serialize();
|
||||
else if (type == 'peer')
|
||||
data = $('#addPeerForm').serialize();
|
||||
else
|
||||
var json = {}
|
||||
|
||||
$.post("../api/network/add_network_" + type + "?id="+serverId+"&project="+project+"&network="+network, data, function (data) {
|
||||
console.log(data)
|
||||
if (data.error_code >= 400){
|
||||
alert(data.error);
|
||||
}
|
||||
//Sync type
|
||||
reloadPageContent();
|
||||
});
|
||||
}
|
||||
|
||||
function createItemUsingJSON(type){
|
||||
console.log("Info: adding new " + type);
|
||||
if (type == 'forward')
|
||||
var json = $("#jsonCreateForwardInput").val();
|
||||
else if (type == 'load_balancer')
|
||||
var json = $("#jsonCreateLoadBalancerInput").val();
|
||||
else if (type == 'peer')
|
||||
var json = $("#jsonCreatePeerInput").val();
|
||||
else
|
||||
var json = {}
|
||||
|
||||
$.post("../api/network/add_network?id="+serverId+"&project="+project+"&network="+network, { json: json }, function (data) {
|
||||
console.log(data);
|
||||
if (data.error_code >= 400){
|
||||
alert(data.error);
|
||||
}
|
||||
//Sync type
|
||||
reloadPageContent();
|
||||
});
|
||||
}
|
||||
|
||||
function deleteItem(name, type){
|
||||
console.log("Info: confirming deletion of " + type + " " + name);
|
||||
if (confirm("Are you sure you want to delete " + type + " " + name + "?") == true) {
|
||||
console.log("Info: deleting " + type + " " + name);
|
||||
$.post("../api/network/delete_network_" + type + "?id=" + serverId + "&project=" + project + "&network=" + network, { name: name }, function (data) {
|
||||
console.log(data);
|
||||
if (data.error_code >= 400){
|
||||
alert(data.error);
|
||||
}
|
||||
//Sync type
|
||||
setTimeout(() => { reloadPageContent(); }, 1000);
|
||||
operationStatusCheck()
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function editForward(name){
|
||||
console.log("Info: loading forward " + name);
|
||||
$.post("../api/network/load_network_forward?id=" + serverId + "&project=" + project + "&network=" + network, { name: name }, function (data) {
|
||||
console.log(data);
|
||||
if (data.error_code >= 400){
|
||||
alert(data.error);
|
||||
}
|
||||
$("#forwardJsonInput").val(JSON.stringify(data.metadata, null, 2));
|
||||
$("#forwardNameHiddenInput").val(name);
|
||||
$("#editForwardModal").modal('show');
|
||||
});
|
||||
}
|
||||
|
||||
function editLoadBalancer(name){
|
||||
console.log("Info: loading load balancer " + name);
|
||||
$.post("../api/network/load_network_load_balancer?id=" + serverId + "&project=" + project + "&network=" + network, { name: name }, function (data) {
|
||||
console.log(data);
|
||||
if (data.error_code >= 400){
|
||||
alert(data.error);
|
||||
}
|
||||
$("#loadBalancerJsonInput").val(JSON.stringify(data.metadata, null, 2));
|
||||
$("#loadBalancerNameHiddenInput").val(name);
|
||||
$("#editLoadBalancerModal").modal('show');
|
||||
});
|
||||
}
|
||||
|
||||
function editPeer(name){
|
||||
console.log("Info: loading peer " + name);
|
||||
$.post("../api/network/load_network_peer?id=" + serverId + "&project=" + project + "&network=" + network, { name: name }, function (data) {
|
||||
console.log(data);
|
||||
if (data.error_code >= 400){
|
||||
alert(data.error);
|
||||
}
|
||||
$("#peerJsonInput").val(JSON.stringify(data.metadata, null, 2));
|
||||
$("#peerNameHiddenInput").val(name);
|
||||
$("#editPeerModal").modal('show');
|
||||
});
|
||||
}
|
||||
|
||||
function updateForward(){
|
||||
var name = $("#forwardNameHiddenInput").val();
|
||||
var updatedJSON = $("#forwardJsonInput").val();
|
||||
console.log("Info: updating forward " + name);
|
||||
$.post("../api/network/update_network_forward?id=" + serverId + "&project=" + project + "&network=" + network + "&name=" + encodeURI(name), { json: updatedJSON }, function (data) {
|
||||
console.log(data);
|
||||
if (data.error_code >= 400){
|
||||
alert(data.error);
|
||||
}
|
||||
//Sync type
|
||||
reloadPageContent();
|
||||
});
|
||||
}
|
||||
|
||||
function updateLoadBalancer(){
|
||||
var name = $("#loadBalancerNameHiddenInput").val();
|
||||
var updatedJSON = $("#loadBalancerJsonInput").val();
|
||||
console.log("Info: updating load balancer " + name);
|
||||
$.post("../api/network/update_network_load_balancer?id=" + serverId + "&project=" + project + "&network=" + network + "&name=" + encodeURI(name), { json: updatedJSON }, function (data) {
|
||||
console.log(data);
|
||||
if (data.error_code >= 400){
|
||||
alert(data.error);
|
||||
}
|
||||
//Sync type
|
||||
reloadPageContent();
|
||||
});
|
||||
}
|
||||
|
||||
function updatePeer(){
|
||||
var name = $("#peerNameHiddenInput").val();
|
||||
var updatedJSON = $("#peerJsonInput").val();
|
||||
console.log("Info: updating peer " + name);
|
||||
$.post("../api/network/update_network_peer?id=" + serverId + "&project=" + project + "&network=" + network + "&name=" + encodeURI(name), { json: updatedJSON }, function (data) {
|
||||
console.log(data);
|
||||
if (data.error_code >= 400){
|
||||
alert(data.error);
|
||||
}
|
||||
//Sync type
|
||||
reloadPageContent();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
$(document).ready(function(){
|
||||
|
||||
//If id or project variables are missing redirect to servers page
|
||||
if (!serverId || !project) {
|
||||
window.location.href = 'servers';
|
||||
}
|
||||
else {
|
||||
$("#network_title").text(network);
|
||||
loadPageContent()
|
||||
operationStatusCheck()
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
{% endblock script %}
|
|
@ -103,13 +103,14 @@
|
|||
columns: [
|
||||
{ title: "Name", data: function (row, type, set) {
|
||||
if (row.hasOwnProperty('name')) {
|
||||
if (row.name && row.managed && row.type)
|
||||
return '<a href="../network?id=' + serverId + '&project=' + project + '&network=' + row.name + '&network_type=' + row.type + '">' + row.name + '</a>';
|
||||
if (row.name)
|
||||
return row.name
|
||||
}
|
||||
return '-'
|
||||
},
|
||||
},
|
||||
|
||||
{ title: "Description", data: function (row, type, set) {
|
||||
if (row.hasOwnProperty('description')) {
|
||||
if (row.description)
|
||||
|
@ -501,6 +502,7 @@
|
|||
else {
|
||||
loadPageContent()
|
||||
operationStatusCheck()
|
||||
changeNetworkTypeInput()
|
||||
}
|
||||
|
||||
});
|
||||
|
|
|
@ -30,15 +30,7 @@
|
|||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" id="clusterGroupsLinkSidebar" href="cluster-groups" style="display: none;">
|
||||
<i id="clusterGroupsIcon" class="nav-icon fas fa-layer-group"></i>
|
||||
<p id="clusterGroupsSpan">
|
||||
Cluster Groups
|
||||
</p>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" id="clusterGroupsLinkSidebar" href="cluster-groups" style="display: none;">
|
||||
<i id="clusterGroupsIcon" class="nav-icon fas fa-layer-group"></i>
|
||||
<i id="clusterGroupsIcon" class="nav-icon fab fa-hive"></i>
|
||||
<p id="clusterGroupsSpan">
|
||||
Cluster Groups
|
||||
</p>
|
||||
|
@ -118,37 +110,14 @@
|
|||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" id="networkForwardsLinkSidebar" href="network-forwards" style="display: none;">
|
||||
<i id="networkForwardsIcon" class="nav-icon fas fa-shield-alt"></i>
|
||||
<p id="networkForwardsSpan">
|
||||
Network Forwards
|
||||
</p>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" id="networkLoadBalancersLinkSidebar" href="network-load-balancers" style="display: none;">
|
||||
<i id="networkLoadBalancersIcon" class="nav-icon fas fa-shield-alt"></i>
|
||||
<p id="networkLoadBalancersSpan">
|
||||
Network Load Balancers
|
||||
</p>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" id="networkPeersLinkSidebar" href="network-peers" style="display: none;">
|
||||
<i id="networkPeersIcon" class="nav-icon fas fa-shield-alt"></i>
|
||||
<p id="networkPeersSpan">
|
||||
Network Peers
|
||||
</p>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" id="networkZonesLinkSidebar" href="network-zones" style="display: none;">
|
||||
<i id="networkZonesIcon" class="nav-icon fas fa-shield-alt"></i>
|
||||
<a class="nav-link" id="networkZonesLinkSidebar" href="network-zones">
|
||||
<i id="networkZonesIcon" class="nav-icon fas fa-globe"></i>
|
||||
<p id="networkZonesSpan">
|
||||
Network Zones
|
||||
</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
<ul id="additionalSidebarLinks" class="nav nav-pills nav-sidebar flex-column user-panel py-2" style="display: none;" data-widget="treeview" role="menu" data-accordion="false">
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,9 +1,10 @@
|
|||
flask
|
||||
flask-sqlalchemy
|
||||
flask-bcrypt
|
||||
flask-login
|
||||
flask-login==0.6.2
|
||||
flask-wtf
|
||||
email-validator
|
||||
requests
|
||||
pyOpenSSL
|
||||
gunicorn
|
||||
gunicorn
|
||||
werkzeug==2.3.0
|
||||
|
|
|
@ -1,10 +1,5 @@
|
|||
# 0.3.0
|
||||
- Add network-zones
|
||||
- Add network-forwards
|
||||
- Add network-load-balancers
|
||||
- Add network peers
|
||||
|
||||
# 0.4.0
|
||||
- Convert to bootstrap 5
|
||||
- Add dark theme option
|
||||
- Add bootstrap toast notifications
|
||||
- Add warnings
|
||||
|
@ -18,7 +13,7 @@
|
|||
- Add logs page
|
||||
|
||||
# 0.7.0
|
||||
- Add expandable datatables rows where appropriate for additional information
|
||||
- Add offcanvas sidebars where appropriate for additional information
|
||||
- Include rename tasks in tables with edit form on new tab
|
||||
|
||||
# 1.0.0
|
||||
|
|
Loading…
Reference in a new issue