From c809d70c68494543f1930b7f5ece08f56a4a4041 Mon Sep 17 00:00:00 2001 From: Will Nilges Date: Fri, 29 Jul 2022 22:00:02 -0400 Subject: [PATCH 1/5] Remove old TODO --- proxstar/vnc.py | 1 - 1 file changed, 1 deletion(-) diff --git a/proxstar/vnc.py b/proxstar/vnc.py index bd4305a..a91bc27 100644 --- a/proxstar/vnc.py +++ b/proxstar/vnc.py @@ -45,7 +45,6 @@ def get_vnc_targets(): def add_vnc_target(node, port): # TODO (willnilges): This doesn't throw an error if the target file is wrong. - # TODO (willnilges): This will duplicate targets targets = get_vnc_targets() target = next((target for target in targets if target['host'] == f'{node}:{port}'), None) if target: From 8d4a7d52a9f67bd5bb2f1589e92d49773fdba49f Mon Sep 17 00:00:00 2001 From: Will Nilges Date: Fri, 29 Jul 2022 22:24:52 -0400 Subject: [PATCH 2/5] Remove SSH functionality to Proxmox --- Dockerfile | 2 +- HACKING/.env.template | 3 --- HACKING/lint.sh | 0 config.py | 4 ---- proxstar/__init__.py | 11 ----------- proxstar/proxmox.py | 18 ------------------ proxstar/vnc.py | 20 -------------------- requirements.txt | 1 - 8 files changed, 1 insertion(+), 58 deletions(-) create mode 100755 HACKING/lint.sh diff --git a/Dockerfile b/Dockerfile index 82075b6..138f24d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,5 +7,5 @@ COPY start_worker.sh start_scheduler.sh . COPY .git ./.git COPY *.py . COPY proxstar ./proxstar -RUN touch proxmox_ssh_key targets && chmod a+w proxmox_ssh_key targets # This is some OKD shit. +RUN touch targets && chmod a+w targets # This is some OKD shit. ENTRYPOINT ddtrace-run gunicorn proxstar:app --bind=0.0.0.0:8080 diff --git a/HACKING/.env.template b/HACKING/.env.template index 0e0371a..264ed24 100644 --- a/HACKING/.env.template +++ b/HACKING/.env.template @@ -26,9 +26,6 @@ PROXSTAR_PROXMOX_USER=api@pve PROXSTAR_PROXMOX_PASS= # Password for proxstar user PROXSTAR_PROXMOX_ISO_STORAGE=nfs-iso PROXSTAR_PROXMOX_VM_STORAGE=ceph -PROXSTAR_PROXMOX_SSH_USER=root -PROXSTAR_PROXMOX_SSH_KEY="" # Ask an RTP. This is gonna look like a certificate. -PROXSTAR_PROXMOX_SSH_KEY_PASS= # Password for above certificate # STARRS PROXSTAR_STARRS_DB_HOST=proxstar-postgres diff --git a/HACKING/lint.sh b/HACKING/lint.sh new file mode 100755 index 0000000..e69de29 diff --git a/config.py b/config.py index 4632f92..6865dda 100644 --- a/config.py +++ b/config.py @@ -37,10 +37,6 @@ PROXMOX_PASS = environ.get('PROXSTAR_PROXMOX_PASS', '') PROXMOX_ISO_STORAGE = environ.get('PROXSTAR_PROXMOX_ISO_STORAGE', 'nfs-iso') PROXMOX_VM_STORAGE = environ.get('PROXSTAR_PROXMOX_VM_STORAGE', 'ceph') -PROXMOX_SSH_USER = environ.get('PROXSTAR_PROXMOX_SSH_USER', '') -PROXMOX_SSH_KEY = environ.get('PROXSTAR_PROXMOX_SSH_KEY', '') -PROXMOX_SSH_KEY_PASS = environ.get('PROXSTAR_PROXMOX_SSH_KEY_PASS', '') - # STARRS STARRS_DB_HOST = environ.get('PROXSTAR_STARRS_DB_HOST', '') STARRS_DB_NAME = environ.get('PROXSTAR_DB_NAME', 'starrs') diff --git a/proxstar/__init__.py b/proxstar/__init__.py index d3c1d6e..e1b889b 100644 --- a/proxstar/__init__.py +++ b/proxstar/__init__.py @@ -77,12 +77,6 @@ environment=app.config['SENTRY_ENV'], ) -if not os.path.exists('proxmox_ssh_key'): - with open('proxmox_ssh_key', 'w') as ssh_key_file: - ssh_key_file.write(app.config['PROXMOX_SSH_KEY']) - -ssh_tunnels = [] - auth = get_auth(app) redis_conn = Redis(app.config['REDIS_HOST'], app.config['REDIS_PORT']) @@ -630,11 +624,6 @@ def health(): def exit_handler(): stop_websockify() - for tunnel in ssh_tunnels: - try: - tunnel.stop() - except: - pass atexit.register(exit_handler) diff --git a/proxstar/proxmox.py b/proxstar/proxmox.py index 867af28..c310a72 100644 --- a/proxstar/proxmox.py +++ b/proxstar/proxmox.py @@ -23,24 +23,6 @@ def connect_proxmox(): raise -def connect_proxmox_ssh(): - for host in app.config['PROXMOX_HOSTS']: - try: - proxmox = ProxmoxAPI( - host, - user=app.config['PROXMOX_SSH_USER'], - private_key_file='proxmox_ssh_key', - password=app.config['PROXMOX_SSH_KEY_PASS'], - backend='ssh_paramiko', - ) - proxmox.version.get() - return proxmox - except: - if app.config['PROXMOX_HOSTS'].index(host) == (len(app.config['PROXMOX_HOSTS']) - 1): - logging.error('unable to connect to any of the given Proxmox servers') - raise - - def get_node_least_mem(proxmox): nodes = proxmox.nodes.get() sorted_nodes = sorted(nodes, key=lambda x: ('mem' not in x, x.get('mem', None))) diff --git a/proxstar/vnc.py b/proxstar/vnc.py index a91bc27..25c9e82 100644 --- a/proxstar/vnc.py +++ b/proxstar/vnc.py @@ -6,7 +6,6 @@ from deprecated import deprecated import requests from flask import current_app as app -from sshtunnel import SSHTunnelForwarder from proxstar import logging from proxstar.util import gen_password @@ -102,22 +101,3 @@ def open_vnc_session(vmid, node, proxmox_user, proxmox_pass): ).json()['data'] return urllib.parse.quote_plus(vncproxy_response_data['ticket']), vncproxy_response_data['port'] - - -@deprecated('No longer in use') -def start_ssh_tunnel(node, port): - """Forwards a port on a node - to the proxstar container - """ - port = int(port) - - server = SSHTunnelForwarder( - node, - ssh_username=app.config['PROXMOX_SSH_USER'], - ssh_pkey='proxmox_ssh_key', - ssh_private_key_password=app.config['PROXMOX_SSH_KEY_PASS'], - remote_bind_address=('127.0.0.1', port), - local_bind_address=('127.0.0.1', port), - ) - server.start() - return server diff --git a/requirements.txt b/requirements.txt index a70ebcf..ca69f24 100644 --- a/requirements.txt +++ b/requirements.txt @@ -19,7 +19,6 @@ rq==1.10.1 rq-dashboard==0.6.1 rq-scheduler==0.10.0 sqlalchemy==1.3.22 -sshtunnel==0.2.2 tenacity==5.0.2 websockify==0.9.0 pylint==2.13.9 From aa1c4834f407192412a81085372035bf52127a4d Mon Sep 17 00:00:00 2001 From: Will Nilges Date: Fri, 29 Jul 2022 22:55:18 -0400 Subject: [PATCH 3/5] Remove deprecated library No, seriously --- HACKING/lint.sh | 0 proxstar/vnc.py | 1 - requirements.txt | 1 - 3 files changed, 2 deletions(-) delete mode 100755 HACKING/lint.sh diff --git a/HACKING/lint.sh b/HACKING/lint.sh deleted file mode 100755 index e69de29..0000000 diff --git a/proxstar/vnc.py b/proxstar/vnc.py index 25c9e82..536f39d 100644 --- a/proxstar/vnc.py +++ b/proxstar/vnc.py @@ -3,7 +3,6 @@ import time import urllib.parse -from deprecated import deprecated import requests from flask import current_app as app diff --git a/requirements.txt b/requirements.txt index ca69f24..240c261 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,6 @@ black~=21.9b0 csh-ldap==2.4.0 click~=7.1.2 ddtrace~=1.2.1 -deprecated==1.2.13 flask==1.1.4 jinja2==2.11.3 flask-pyoidc==1.3.0 From 433c845a35a8c402ef4becc33e5ffa5580af4189 Mon Sep 17 00:00:00 2001 From: Will Nilges Date: Sun, 31 Jul 2022 00:12:06 -0400 Subject: [PATCH 4/5] Use Redis to link VNC tokens to VMID --- HACKING/build_env.sh | 2 ++ proxstar/__init__.py | 14 ++++++++++---- proxstar/tasks.py | 2 +- proxstar/vnc.py | 11 +++++++++-- 4 files changed, 22 insertions(+), 7 deletions(-) create mode 100755 HACKING/build_env.sh diff --git a/HACKING/build_env.sh b/HACKING/build_env.sh new file mode 100755 index 0000000..0590705 --- /dev/null +++ b/HACKING/build_env.sh @@ -0,0 +1,2 @@ +#!/bin/bash +podman build . --tag=proxstar diff --git a/proxstar/__init__.py b/proxstar/__init__.py index e1b889b..33e43fe 100644 --- a/proxstar/__init__.py +++ b/proxstar/__init__.py @@ -252,6 +252,9 @@ def vm_power(vmid, action): connect_proxmox() if user.rtp or int(vmid) in user.allowed_vms: vm = VM(vmid) + vnc_token_key = f'vnc_token|{vmid}' + vnc_token = redis_conn.get(vnc_token_key).decode('utf-8') # For deleting the token from redis later + print(f'vnc_token = {vnc_token}') if action == 'start': vmconfig = vm.config usage_check = user.check_usage(vmconfig['cores'], vmconfig['memory'], 0) @@ -260,16 +263,18 @@ def vm_power(vmid, action): vm.start() elif action == 'stop': vm.stop() - # TODO (willnilges): Replace with remove target function or something - # send_stop_ssh_tunnel(vmid) + delete_vnc_target(token=vnc_token) + redis_conn.delete(vnc_token_key) elif action == 'shutdown': vm.shutdown() - # send_stop_ssh_tunnel(vmid) + delete_vnc_target(token=vnc_token) + redis_conn.delete(vnc_token_key) elif action == 'reset': vm.reset() elif action == 'suspend': vm.suspend() - # send_stop_ssh_tunnel(vmid) + delete_vnc_target(token=vnc_token) + redis_conn.delete(vnc_token_key) elif action == 'resume': vm.resume() return '', 200 @@ -290,6 +295,7 @@ def vm_console(vmid): ) node = f'{vm.node}.csh.rit.edu' token = add_vnc_target(node, vnc_port) + redis_conn.set(f'vnc_token|{vmid}', str(token)) # Store the VNC token in Redis. return { 'host': app.config['VNC_HOST'], 'port': app.config['VNC_PORT'], diff --git a/proxstar/tasks.py b/proxstar/tasks.py index 0e928a8..0063e6e 100644 --- a/proxstar/tasks.py +++ b/proxstar/tasks.py @@ -6,6 +6,7 @@ import requests from flask import Flask from rq import get_current_job +from redis import Redis from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker @@ -32,7 +33,6 @@ config = os.path.join(app.config.get('ROOT_DIR', os.getcwd()), 'config.py') app.config.from_pyfile(config) - def connect_db(): engine = create_engine(app.config['SQLALCHEMY_DATABASE_URI']) Base.metadata.bind = engine diff --git a/proxstar/vnc.py b/proxstar/vnc.py index 536f39d..1e92856 100644 --- a/proxstar/vnc.py +++ b/proxstar/vnc.py @@ -56,15 +56,22 @@ def add_vnc_target(node, port): return token -def delete_vnc_target(node, port): +def delete_vnc_target(node=None, port=None, token=None): targets = get_vnc_targets() - target = next((target for target in targets if target['host'] == f'{node}:{port}'), None) + if node is not None and port is not None: + target = next((target for target in targets if target['host'] == f'{node}:{port}'), None) + elif token is not None: + target = next((target for target in targets if target['token'] == f'{token}'), None) + else: + raise ValueError("Need either a node and port, or a token.") if target: targets.remove(target) target_file = open(app.config['WEBSOCKIFY_TARGET_FILE'], 'w') for target in targets: target_file.write(f"{target['token']}: {target['host']}\n") target_file.close() + else: + raise LookupError("Target does not exist") def open_vnc_session(vmid, node, proxmox_user, proxmox_pass): From 125d7fae51fb183ec9426ab9f4f374b0083a83d2 Mon Sep 17 00:00:00 2001 From: Will Nilges Date: Fri, 12 Aug 2022 00:42:53 -0400 Subject: [PATCH 5/5] Remove target from targets file in tasks This probably isn't necessary and will probably error out.... --- proxstar/__init__.py | 6 +++--- proxstar/tasks.py | 13 ++++++++++++- proxstar/vnc.py | 4 ++-- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/proxstar/__init__.py b/proxstar/__init__.py index 33e43fe..4fd552c 100644 --- a/proxstar/__init__.py +++ b/proxstar/__init__.py @@ -253,8 +253,8 @@ def vm_power(vmid, action): if user.rtp or int(vmid) in user.allowed_vms: vm = VM(vmid) vnc_token_key = f'vnc_token|{vmid}' - vnc_token = redis_conn.get(vnc_token_key).decode('utf-8') # For deleting the token from redis later - print(f'vnc_token = {vnc_token}') + # For deleting the token from redis later + vnc_token = redis_conn.get(vnc_token_key).decode('utf-8') if action == 'start': vmconfig = vm.config usage_check = user.check_usage(vmconfig['cores'], vmconfig['memory'], 0) @@ -295,7 +295,7 @@ def vm_console(vmid): ) node = f'{vm.node}.csh.rit.edu' token = add_vnc_target(node, vnc_port) - redis_conn.set(f'vnc_token|{vmid}', str(token)) # Store the VNC token in Redis. + redis_conn.set(f'vnc_token|{vmid}', str(token)) # Store the VNC token in Redis. return { 'host': app.config['VNC_HOST'], 'port': app.config['VNC_PORT'], diff --git a/proxstar/tasks.py b/proxstar/tasks.py index 0063e6e..96ccffb 100644 --- a/proxstar/tasks.py +++ b/proxstar/tasks.py @@ -23,6 +23,7 @@ from proxstar.starrs import get_next_ip, register_starrs, delete_starrs from proxstar.user import User, get_vms_for_rtp from proxstar.vm import VM, clone_vm, create_vm +from proxstar.vnc import delete_vnc_target logging.basicConfig(format='%(asctime)s %(levelname)s %(message)s', level=logging.INFO) @@ -33,6 +34,7 @@ config = os.path.join(app.config.get('ROOT_DIR', os.getcwd()), 'config.py') app.config.from_pyfile(config) + def connect_db(): engine = create_engine(app.config['SQLALCHEMY_DATABASE_URI']) Base.metadata.bind = engine @@ -150,7 +152,16 @@ def process_expiring_vms_task(): vm.name, vm.id ) ) - # send_stop_ssh_tunnel(vm.id) # TODO (willnilges): Remove target from targets file + try: + redis_conn = Redis(app.config['REDIS_HOST'], app.config['REDIS_PORT']) + vmid = vm['vmid'] + vnc_token_key = f'vnc_token|{vmid}' + vnc_token = redis_conn.get(vnc_token_key).decode('utf-8') + delete_vnc_target(token=vnc_token) + redis_conn.delete(vnc_token_key) + except Exception as e: # pylint: disable=W0703 + print(f'ERROR: Could not delete target from targets file: {e}') + delete_vm_task(vm.id) if expiring_vms: send_vm_expire_email(pool, expiring_vms) diff --git a/proxstar/vnc.py b/proxstar/vnc.py index 1e92856..7df87cf 100644 --- a/proxstar/vnc.py +++ b/proxstar/vnc.py @@ -63,7 +63,7 @@ def delete_vnc_target(node=None, port=None, token=None): elif token is not None: target = next((target for target in targets if target['token'] == f'{token}'), None) else: - raise ValueError("Need either a node and port, or a token.") + raise ValueError('Need either a node and port, or a token.') if target: targets.remove(target) target_file = open(app.config['WEBSOCKIFY_TARGET_FILE'], 'w') @@ -71,7 +71,7 @@ def delete_vnc_target(node=None, port=None, token=None): target_file.write(f"{target['token']}: {target['host']}\n") target_file.close() else: - raise LookupError("Target does not exist") + raise LookupError('Target does not exist') def open_vnc_session(vmid, node, proxmox_user, proxmox_pass):