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 . import auth
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 ..models import User, Job
import logging
import threading
@auth.route('/login', methods=['GET', 'POST'])
@ -165,8 +169,30 @@ def settings():
@auth.route('/settings/delete_self', methods=['GET', 'POST'])
@login_required
def delete_self():
user = current_user
db.session.delete(user)
logger = logging.getLogger(__name__)
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()
flash('Your account has been deleted!')
return redirect(url_for('main.index'))

View File

@ -7,7 +7,7 @@ from .. import db
from ..models import Corpus, Job
import os
import logging
import time
import threading
@main.route('/')
@ -145,8 +145,13 @@ def job_download(job_id):
@login_required
def delete_job(job_id):
logger = logging.getLogger(__name__)
logger.warning(job_id)
def background_delete(job_id, app):
with app.app_context():
logger.warning('Called by delete_thread.')
logger.warning('Job id is: {}.'.format(job_id))
job = Job.query.filter_by(id=job_id).first()
logger.warning('Job object is: {}'.format(job))
logger.warning('Job status: {}'.format(job.status))
job.flag_for_stop()
logger.warning('Job status: {}'.format(job.status))
@ -155,7 +160,12 @@ def delete_job(job_id):
db.session.refresh(job)
if job.status == 'deleted':
logger.warning('Job status is deleted.')
time.sleep(5) # Wait 5 seconds before deleteing job and job files
job.delete_job() # See delete_job() method for further explanation
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'))

View File

@ -300,18 +300,23 @@ class Job(db.Model):
def delete_job(self):
"""
Delete job with given job id from database. Also delete associated job
files. Wait 5 seconds after service has been flaged for stopping and
deleted. This method can only be used if the containers have been
totally stopped. Contianers are still running for a few seconds after
the associated service has been removed.
files. Contianers are still running for a few seconds after
the associated service has been removed. This is the reason for the
while loop. The loop checks if the file path to all the job files still
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/
"""
logger = logging.getLogger(__name__)
delete_path = os.path.join('/mnt/opaque/', str(self.user_id), 'jobs',
str(self.id))
logger.warning('Delete path is: {}'.format(delete_path))
if os.path.exists(delete_path):
shutil.rmtree(delete_path)
while os.path.exists(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.commit()

View File

@ -76,7 +76,8 @@
<div id="modal-confirm-delete" class="modal">
<div class="modal-content">
<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 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>