mirror of
				https://gitlab.ub.uni-bielefeld.de/sfb1288inf/nopaque.git
				synced 2025-11-04 12:22:47 +00:00 
			
		
		
		
	Add delete functions for jobs and users.
This commit is contained in:
		@@ -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'))
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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,8 +145,13 @@ 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)
 | 
					
 | 
				
			||||||
 | 
					    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()
 | 
					            job = Job.query.filter_by(id=job_id).first()
 | 
				
			||||||
 | 
					            logger.warning('Job object is: {}'.format(job))
 | 
				
			||||||
            logger.warning('Job status: {}'.format(job.status))
 | 
					            logger.warning('Job status: {}'.format(job.status))
 | 
				
			||||||
            job.flag_for_stop()
 | 
					            job.flag_for_stop()
 | 
				
			||||||
            logger.warning('Job status: {}'.format(job.status))
 | 
					            logger.warning('Job status: {}'.format(job.status))
 | 
				
			||||||
@@ -155,7 +160,12 @@ def delete_job(job_id):
 | 
				
			|||||||
                db.session.refresh(job)
 | 
					                db.session.refresh(job)
 | 
				
			||||||
                if job.status == 'deleted':
 | 
					                if job.status == 'deleted':
 | 
				
			||||||
                    logger.warning('Job status is deleted.')
 | 
					                    logger.warning('Job status is deleted.')
 | 
				
			||||||
            time.sleep(5)  # Wait 5 seconds before deleteing job and job files
 | 
					                    job.delete_job()
 | 
				
			||||||
            job.delete_job()  # See delete_job() method for further explanation
 | 
					 | 
				
			||||||
                    deleted = True
 | 
					                    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'))
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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>
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user