Add delete functions for jobs and users.

This commit is contained in:
Stephan Porada 2019-09-17 14:36:15 +02:00
parent 683b59bb47
commit 09f7d7ac68
4 changed files with 67 additions and 25 deletions

View File

@ -1,10 +1,14 @@
from flask import flash, redirect, render_template, request, url_for from flask import (flash, redirect, render_template, request, url_for,
current_app)
from flask_login import current_user, login_required, login_user, logout_user from flask_login import current_user, login_required, login_user, logout_user
from . import auth from . import auth
from .. import db from .. import db
from .forms import ChangePasswordForm, LoginForm, PasswordResetForm, PasswordResetRequestForm, RegistrationForm, EditProfileForm from .forms import (ChangePasswordForm, LoginForm, PasswordResetForm,
PasswordResetRequestForm, RegistrationForm, EditProfileForm)
from ..email import send_email from ..email import send_email
from ..models import User, Job from ..models import User, Job
import logging
import threading
@auth.route('/login', methods=['GET', 'POST']) @auth.route('/login', methods=['GET', 'POST'])
@ -165,8 +169,30 @@ def settings():
@auth.route('/settings/delete_self', methods=['GET', 'POST']) @auth.route('/settings/delete_self', methods=['GET', 'POST'])
@login_required @login_required
def delete_self(): def delete_self():
user = current_user logger = logging.getLogger(__name__)
db.session.delete(user)
def background_delete(app, current_user_id):
with app.app_context():
logger.warning('Called by delete_thread.')
logger.warning('User id is: {}.'.format(current_user_id))
jobs = Job.query.join(User).filter_by(id=current_user_id).all()
logger.warning('Jobs to delete are: {}'.format(jobs))
for job in jobs:
job.flag_for_stop()
logger.warning('Job status: {}'.format(job.status))
deleted = False
while deleted is False:
db.session.refresh(job)
if job.status == 'deleted':
logger.warning('Job status is deleted.')
job.delete_job()
deleted = True
delete_thread = threading.Thread(target=background_delete,
args=(current_app._get_current_object(),
current_user.id))
delete_thread.start()
db.session.delete(current_user)
db.session.commit() db.session.commit()
flash('Your account has been deleted!') flash('Your account has been deleted!')
return redirect(url_for('main.index')) return redirect(url_for('main.index'))

View File

@ -7,7 +7,7 @@ from .. import db
from ..models import Corpus, Job from ..models import Corpus, Job
import os import os
import logging import logging
import time import threading
@main.route('/') @main.route('/')
@ -145,17 +145,27 @@ def job_download(job_id):
@login_required @login_required
def delete_job(job_id): def delete_job(job_id):
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
logger.warning(job_id)
job = Job.query.filter_by(id=job_id).first() def background_delete(job_id, app):
logger.warning('Job status: {}'.format(job.status)) with app.app_context():
job.flag_for_stop() logger.warning('Called by delete_thread.')
logger.warning('Job status: {}'.format(job.status)) logger.warning('Job id is: {}.'.format(job_id))
deleted = False job = Job.query.filter_by(id=job_id).first()
while deleted is False: logger.warning('Job object is: {}'.format(job))
db.session.refresh(job) logger.warning('Job status: {}'.format(job.status))
if job.status == 'deleted': job.flag_for_stop()
logger.warning('Job status is deleted.') logger.warning('Job status: {}'.format(job.status))
time.sleep(5) # Wait 5 seconds before deleteing job and job files deleted = False
job.delete_job() # See delete_job() method for further explanation while deleted is False:
deleted = True db.session.refresh(job)
if job.status == 'deleted':
logger.warning('Job status is deleted.')
job.delete_job()
deleted = True
delete_thread = threading.Thread(target=background_delete,
args=(job_id,
current_app._get_current_object()))
delete_thread.start()
flash('Job has been deleted!')
return redirect(url_for('main.dashboard')) return redirect(url_for('main.dashboard'))

View File

@ -300,18 +300,23 @@ class Job(db.Model):
def delete_job(self): def delete_job(self):
""" """
Delete job with given job id from database. Also delete associated job Delete job with given job id from database. Also delete associated job
files. Wait 5 seconds after service has been flaged for stopping and files. Contianers are still running for a few seconds after
deleted. This method can only be used if the containers have been the associated service has been removed. This is the reason for the
totally stopped. Contianers are still running for a few seconds after while loop. The loop checks if the file path to all the job files still
the associated service has been removed. exists and removes it again and again till the container did shutdown
for good.
See: https://docs.docker.com/engine/swarm/swarm-tutorial/delete-service/ See: https://docs.docker.com/engine/swarm/swarm-tutorial/delete-service/
""" """
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
delete_path = os.path.join('/mnt/opaque/', str(self.user_id), 'jobs', delete_path = os.path.join('/mnt/opaque/', str(self.user_id), 'jobs',
str(self.id)) str(self.id))
logger.warning('Delete path is: {}'.format(delete_path)) logger.warning('Delete path is: {}'.format(delete_path))
if os.path.exists(delete_path): while os.path.exists(delete_path):
shutil.rmtree(delete_path) try:
shutil.rmtree(delete_path, ignore_errors=True)
logger.warning('Path does still exist.')
except OSError:
pass
db.session.delete(self) db.session.delete(self)
db.session.commit() db.session.commit()

View File

@ -76,7 +76,8 @@
<div id="modal-confirm-delete" class="modal"> <div id="modal-confirm-delete" class="modal">
<div class="modal-content"> <div class="modal-content">
<h4>Confirm deletion</h4> <h4>Confirm deletion</h4>
<p>Do you really want to delete the current selected user ({{selected_user.username}})?</p> <p>Do you really want to delete the current selected user ({{selected_user.username}})?
All associated jobs and job files will be permanently deleted.</p>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<a href="{{url_for('admin.admin_delete_user', user_id=selected_user.id)}}" class="modal-close waves-effect waves-green btn red"><i class="material-icons left">delete</i>Delete User</a></a> <a href="{{url_for('admin.admin_delete_user', user_id=selected_user.id)}}" class="modal-close waves-effect waves-green btn red"><i class="material-icons left">delete</i>Delete User</a></a>