mirror of
https://github.com/ComputerScienceHouse/proxstar.git
synced 2025-03-09 15:40:09 +00:00
Black
This commit is contained in:
parent
1134939d3c
commit
98d1408693
4 changed files with 54 additions and 13 deletions
|
@ -17,6 +17,13 @@ It is available to house members at [proxstar.csh.rit.edu](https://proxstar.csh.
|
||||||
|
|
||||||
1. [Fork](https://help.github.com/en/articles/fork-a-repo) this repository
|
1. [Fork](https://help.github.com/en/articles/fork-a-repo) this repository
|
||||||
- Optionally create a new [git branch](https://git-scm.com/book/en/v2/Git-Branching-Branches-in-a-Nutshell) if your change is more than a small tweak (`git checkout -b BRANCH-NAME-HERE`)
|
- Optionally create a new [git branch](https://git-scm.com/book/en/v2/Git-Branching-Branches-in-a-Nutshell) if your change is more than a small tweak (`git checkout -b BRANCH-NAME-HERE`)
|
||||||
|
2. Create a Virtualenv to do your work in.
|
||||||
|
```
|
||||||
|
mkdir venv
|
||||||
|
python3.8 -m venv venv
|
||||||
|
source venv/bin/activate
|
||||||
|
```
|
||||||
|
|
||||||
3. Make your changes locally, commit, and push to your fork
|
3. Make your changes locally, commit, and push to your fork
|
||||||
- If you want to test locally, you should copy `config.py` to `config_local.py`, and talk to an RTP about filling in secrets.
|
- If you want to test locally, you should copy `config.py` to `config_local.py`, and talk to an RTP about filling in secrets.
|
||||||
- Lint and format your local changes with `pylint proxstar` and `black proxstar`
|
- Lint and format your local changes with `pylint proxstar` and `black proxstar`
|
||||||
|
|
|
@ -13,7 +13,17 @@ from redis import Redis
|
||||||
from rq_scheduler import Scheduler
|
from rq_scheduler import Scheduler
|
||||||
from sqlalchemy import create_engine
|
from sqlalchemy import create_engine
|
||||||
from sqlalchemy.orm import sessionmaker
|
from sqlalchemy.orm import sessionmaker
|
||||||
from flask import Flask, render_template, request, redirect, session, abort, url_for, jsonify, Response
|
from flask import (
|
||||||
|
Flask,
|
||||||
|
render_template,
|
||||||
|
request,
|
||||||
|
redirect,
|
||||||
|
session,
|
||||||
|
abort,
|
||||||
|
url_for,
|
||||||
|
jsonify,
|
||||||
|
Response,
|
||||||
|
)
|
||||||
import sentry_sdk
|
import sentry_sdk
|
||||||
from sentry_sdk.integrations.flask import FlaskIntegration
|
from sentry_sdk.integrations.flask import FlaskIntegration
|
||||||
from sentry_sdk.integrations.rq import RqIntegration
|
from sentry_sdk.integrations.rq import RqIntegration
|
||||||
|
@ -135,6 +145,7 @@ if 'cleanup_vnc' not in scheduler:
|
||||||
interval=3600,
|
interval=3600,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def add_rq_dashboard_auth(blueprint):
|
def add_rq_dashboard_auth(blueprint):
|
||||||
@blueprint.before_request
|
@blueprint.before_request
|
||||||
@auth.oidc_auth
|
@auth.oidc_auth
|
||||||
|
@ -159,6 +170,7 @@ def forbidden(e):
|
||||||
user = User(session['userinfo']['preferred_username'])
|
user = User(session['userinfo']['preferred_username'])
|
||||||
return render_template('403.html', user=user, e=e), 403
|
return render_template('403.html', user=user, e=e), 403
|
||||||
|
|
||||||
|
|
||||||
@app.route('/')
|
@app.route('/')
|
||||||
@app.route('/user/<string:user_view>')
|
@app.route('/user/<string:user_view>')
|
||||||
@auth.oidc_auth
|
@auth.oidc_auth
|
||||||
|
@ -287,15 +299,23 @@ def vm_console(vmid):
|
||||||
if user.rtp or int(vmid) in user.allowed_vms:
|
if user.rtp or int(vmid) in user.allowed_vms:
|
||||||
# import pdb; pdb.set_trace()
|
# import pdb; pdb.set_trace()
|
||||||
vm = VM(vmid)
|
vm = VM(vmid)
|
||||||
vnc_ticket, vnc_port = open_vnc_session(vmid, vm.node, app.config['PROXMOX_USER'], app.config['PROXMOX_PASS'])
|
vnc_ticket, vnc_port = open_vnc_session(
|
||||||
|
vmid, vm.node, app.config['PROXMOX_USER'], app.config['PROXMOX_PASS']
|
||||||
|
)
|
||||||
node = f'{vm.node}.csh.rit.edu'
|
node = f'{vm.node}.csh.rit.edu'
|
||||||
token = add_vnc_target(node, vnc_port)
|
token = add_vnc_target(node, vnc_port)
|
||||||
# return {'host' : node, 'port' : vnc_port, 'token' : token, 'password' : vnc_ticket}, 200
|
# return {'host' : node, 'port' : vnc_port, 'token' : token, 'password' : vnc_ticket}, 200
|
||||||
return {'host' : app.config['VNC_HOST'], 'port' : 8081, 'token' : token, 'password' : vnc_ticket}, 200
|
return {
|
||||||
|
'host': app.config['VNC_HOST'],
|
||||||
|
'port': 8081,
|
||||||
|
'token': token,
|
||||||
|
'password': vnc_ticket,
|
||||||
|
}, 200
|
||||||
|
|
||||||
else:
|
else:
|
||||||
return '', 403
|
return '', 403
|
||||||
|
|
||||||
|
|
||||||
@app.route('/vm/<string:vmid>/cpu/<int:cores>', methods=['POST'])
|
@app.route('/vm/<string:vmid>/cpu/<int:cores>', methods=['POST'])
|
||||||
@auth.oidc_auth
|
@auth.oidc_auth
|
||||||
def vm_cpu(vmid, cores):
|
def vm_cpu(vmid, cores):
|
||||||
|
|
|
@ -272,19 +272,28 @@ class VM:
|
||||||
# )
|
# )
|
||||||
|
|
||||||
def configure_vnc_in_vm_config(self, ssh_user, ssh_pass):
|
def configure_vnc_in_vm_config(self, ssh_user, ssh_pass):
|
||||||
""" Sets the vm up for VNC. Enables it to open a socket on localhost
|
"""Sets the vm up for VNC. Enables it to open a socket on localhost
|
||||||
with a pre-determined password, which proxstar can then proxy to a noVNC
|
with a pre-determined password, which proxstar can then proxy to a noVNC
|
||||||
instance.
|
instance.
|
||||||
"""
|
"""
|
||||||
# proxmox = connect_proxmox()
|
# proxmox = connect_proxmox()
|
||||||
config = f'args: -object secret,id=secvnc{self.id},data={self.id} -vnc 127.0.0.1:{int(self.id)+5900},password-secret=secvnc{self.id}'
|
config = f'args: -object secret,id=secvnc{self.id},data={self.id} -vnc 127.0.0.1:{int(self.id)+5900},password-secret=secvnc{self.id}'
|
||||||
path = f'/etc/pve/local/qemu-server/{self.id}.conf'
|
path = f'/etc/pve/local/qemu-server/{self.id}.conf'
|
||||||
with paramiko.SSHClient() as ssh:
|
with paramiko.SSHClient() as ssh:
|
||||||
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||||
ssh.connect(self.node, port=22, username=ssh_user, key_filename='proxmox_ssh_key', passphrase=ssh_pass)
|
ssh.connect(
|
||||||
ssh.exec_command(f"if grep -- '{config}' {path}; then echo identical config found; else sed -i /dev/null '/-vnc/d' {path}") #YOLO
|
self.node,
|
||||||
ssh.exec_command(f"if grep -- '-vnc' {path}; then echo found config; else echo {config} >> {path}; fi")
|
port=22,
|
||||||
|
username=ssh_user,
|
||||||
|
key_filename='proxmox_ssh_key',
|
||||||
|
passphrase=ssh_pass,
|
||||||
|
)
|
||||||
|
ssh.exec_command(
|
||||||
|
f"if grep -- '{config}' {path}; then echo identical config found; else sed -i /dev/null '/-vnc/d' {path}"
|
||||||
|
) # YOLO
|
||||||
|
ssh.exec_command(
|
||||||
|
f"if grep -- '-vnc' {path}; then echo found config; else echo {config} >> {path}; fi"
|
||||||
|
)
|
||||||
|
|
||||||
@retry(wait=wait_fixed(2), stop=stop_after_attempt(5))
|
@retry(wait=wait_fixed(2), stop=stop_after_attempt(5))
|
||||||
def eject_iso(self):
|
def eject_iso(self):
|
||||||
|
|
|
@ -37,6 +37,7 @@ def get_vnc_targets():
|
||||||
target_file.close()
|
target_file.close()
|
||||||
return targets
|
return targets
|
||||||
|
|
||||||
|
|
||||||
def add_vnc_target(node, port):
|
def add_vnc_target(node, port):
|
||||||
# TODO (willnilges): This doesn't throw an error if the target file is wrong.
|
# TODO (willnilges): This doesn't throw an error if the target file is wrong.
|
||||||
# TODO (willnilges): This will duplicate targets
|
# TODO (willnilges): This will duplicate targets
|
||||||
|
@ -52,6 +53,7 @@ def add_vnc_target(node, port):
|
||||||
target_file.close()
|
target_file.close()
|
||||||
return token
|
return token
|
||||||
|
|
||||||
|
|
||||||
def delete_vnc_target(node, port):
|
def delete_vnc_target(node, port):
|
||||||
targets = get_vnc_targets()
|
targets = get_vnc_targets()
|
||||||
target = next((target for target in targets if target['host'] == f'{node}:{port}'), None)
|
target = next((target for target in targets if target['host'] == f'{node}:{port}'), None)
|
||||||
|
@ -62,8 +64,9 @@ def delete_vnc_target(node, port):
|
||||||
target_file.write(f"{target['token']}: {target['host']}\n")
|
target_file.write(f"{target['token']}: {target['host']}\n")
|
||||||
target_file.close()
|
target_file.close()
|
||||||
|
|
||||||
|
|
||||||
def open_vnc_session(vmid, node, proxmox_user, proxmox_pass):
|
def open_vnc_session(vmid, node, proxmox_user, proxmox_pass):
|
||||||
""" Pings the Proxmox API to request a VNC Proxy connection. Authenticates
|
"""Pings the Proxmox API to request a VNC Proxy connection. Authenticates
|
||||||
against the API using a Uname/Pass, gets a few tokens back, then uses those
|
against the API using a Uname/Pass, gets a few tokens back, then uses those
|
||||||
tokens to open the VNC Proxy. Use these to connect to the VM's host with
|
tokens to open the VNC Proxy. Use these to connect to the VM's host with
|
||||||
websockify proxy.
|
websockify proxy.
|
||||||
|
@ -91,17 +94,18 @@ def open_vnc_session(vmid, node, proxmox_user, proxmox_pass):
|
||||||
timeout=5,
|
timeout=5,
|
||||||
params=proxy_params,
|
params=proxy_params,
|
||||||
headers={"CSRFPreventionToken": csrf_prevention_token},
|
headers={"CSRFPreventionToken": csrf_prevention_token},
|
||||||
cookies={"PVEAuthCookie": ticket}
|
cookies={"PVEAuthCookie": ticket},
|
||||||
).json()["data"]
|
).json()["data"]
|
||||||
|
|
||||||
return urllib.parse.quote_plus(vncproxy_response_data['ticket']), vncproxy_response_data['port']
|
return urllib.parse.quote_plus(vncproxy_response_data['ticket']), vncproxy_response_data['port']
|
||||||
|
|
||||||
|
|
||||||
def start_ssh_tunnel(node, port):
|
def start_ssh_tunnel(node, port):
|
||||||
"""Forwards a port on a node
|
"""Forwards a port on a node
|
||||||
to the proxstar container
|
to the proxstar container
|
||||||
"""
|
"""
|
||||||
port = int(port)
|
port = int(port)
|
||||||
|
|
||||||
server = SSHTunnelForwarder(
|
server = SSHTunnelForwarder(
|
||||||
node,
|
node,
|
||||||
ssh_username=app.config['PROXMOX_SSH_USER'],
|
ssh_username=app.config['PROXMOX_SSH_USER'],
|
||||||
|
@ -113,6 +117,7 @@ def start_ssh_tunnel(node, port):
|
||||||
server.start()
|
server.start()
|
||||||
return server
|
return server
|
||||||
|
|
||||||
|
|
||||||
def stop_ssh_tunnel(vmid, ssh_tunnels):
|
def stop_ssh_tunnel(vmid, ssh_tunnels):
|
||||||
# Tear down the SSH tunnel and VNC target entry for a given VM
|
# Tear down the SSH tunnel and VNC target entry for a given VM
|
||||||
port = 5900 + int(vmid)
|
port = 5900 + int(vmid)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue