diff --git a/.gitignore b/.gitignore index b8a48286d71a54c4c7ffcdde683791fc3ecd0fd8..320a1ab2d7e059389dd2084a6548325cdcac9c80 100644 --- a/.gitignore +++ b/.gitignore @@ -1,174 +1,9 @@ -# Created by https://www.gitignore.io/api/macos,django,virtualenv,visualstudiocode -# Edit at https://www.gitignore.io/?templates=macos,django,virtualenv,visualstudiocode - -### Django ### -*.log -*.pot -*.pyc -__pycache__/ -local_settings.py -db.sqlite3 -db.sqlite3-journal -media - -# If your build process includes running collectstatic, then you probably don't need or want to include staticfiles/ -# in your Git repository. Update and uncomment the following line accordingly. -# <django-project-name>/staticfiles/ - -### Django.Python Stack ### -# Byte-compiled / optimized / DLL files -*.py[cod] -*$py.class - -# C extensions -*.so - -# Distribution / packaging -.Python -build/ -develop-eggs/ -dist/ -downloads/ -eggs/ -.eggs/ -lib/ -lib64/ -parts/ -sdist/ -var/ -wheels/ -pip-wheel-metadata/ -share/python-wheels/ -*.egg-info/ -.installed.cfg -*.egg -MANIFEST - -# PyInstaller -# Usually these files are written by a python script from a template -# before PyInstaller builds the exe, so as to inject date/other infos into it. -*.manifest -*.spec - -# Installer logs -pip-log.txt -pip-delete-this-directory.txt - -# Unit test / coverage reports -htmlcov/ -.tox/ -.nox/ -.coverage -.coverage.* -.cache -nosetests.xml -coverage.xml -*.cover -.hypothesis/ -.pytest_cache/ - -# Translations -*.mo - -# Scrapy stuff: -.scrapy - -# Sphinx documentation -docs/_build/ - -# PyBuilder -target/ - -# pyenv -.python-version - -# pipenv -# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. -# However, in case of collaboration, if having platform-specific dependencies or dependencies -# having no cross-platform support, pipenv may install dependencies that don't work, or not -# install all needed dependencies. -#Pipfile.lock - -# celery beat schedule file -celerybeat-schedule - -# SageMath parsed files -*.sage.py - -# Spyder project settings -.spyderproject -.spyproject - -# Rope project settings -.ropeproject - -# Mr Developer -.mr.developer.cfg -.project -.pydevproject - -# mkdocs documentation -/site - -# mypy -.mypy_cache/ -.dmypy.json -dmypy.json - -# Pyre type checker -.pyre/ - -### macOS ### -# General -.DS_Store -.AppleDouble -.LSOverride - -# Icon must end with two \r -Icon - -# Thumbnails -._* - -# Files that might appear in the root of a volume -.DocumentRevisions-V100 -.fseventsd -.Spotlight-V100 -.TemporaryItems -.Trashes -.VolumeIcon.icns -.com.apple.timemachine.donotpresent - -# Directories potentially created on remote AFP share -.AppleDB -.AppleDesktop -Network Trash Folder -Temporary Items -.apdisk - -### VirtualEnv ### -# Virtualenv -# http://iamzed.com/2009/05/07/a-primer-on-virtualenv/ -[Bb]in -[Ii]nclude -[Ll]ib -[Ll]ib64 -[Ll]ocal -[Ss]cripts -pyvenv.cfg -.env -.venv -env/ -venv/ -ENV/ -env.bak/ -venv.bak/ -pip-selfcheck.json +# Created by https://www.gitignore.io/api/visualstudiocode +# Edit at https://www.gitignore.io/?templates=visualstudiocode ### VisualStudioCode ### .vscode -.vscode/* !.vscode/settings.json !.vscode/tasks.json !.vscode/launch.json @@ -178,4 +13,4 @@ pip-selfcheck.json # Ignore all local history of files .history -# End of https://www.gitignore.io/api/macos,django,virtualenv,visualstudiocode +# End of https://www.gitignore.io/api/visualstudiocode \ No newline at end of file diff --git a/README.md b/README.md index 7067ec03df771fb0ca4616ccfafc9b945bafd105..807ab0849d80e7fb20acbfe79690951454284cc4 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,7 @@ -Grader NG +# Sofita ``` -docker run --rm -d -p 6379:6379 --name test-redis redis +archive -> archive +graderng -> web and backend +gradersdaplugin -> plugin for moodle ``` - -``` -docker run --rm -d -p 27017:27017 --name=test-mongo mongo -``` - -``` -celery -A graderng worker --loglevel=info -``` - -## Requirements - -Use `sqlparse==0.2.4` diff --git a/graderng/.dockerignore b/graderng/.dockerignore new file mode 100644 index 0000000000000000000000000000000000000000..b8a48286d71a54c4c7ffcdde683791fc3ecd0fd8 --- /dev/null +++ b/graderng/.dockerignore @@ -0,0 +1,181 @@ + +# Created by https://www.gitignore.io/api/macos,django,virtualenv,visualstudiocode +# Edit at https://www.gitignore.io/?templates=macos,django,virtualenv,visualstudiocode + +### Django ### +*.log +*.pot +*.pyc +__pycache__/ +local_settings.py +db.sqlite3 +db.sqlite3-journal +media + +# If your build process includes running collectstatic, then you probably don't need or want to include staticfiles/ +# in your Git repository. Update and uncomment the following line accordingly. +# <django-project-name>/staticfiles/ + +### Django.Python Stack ### +# Byte-compiled / optimized / DLL files +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +pip-wheel-metadata/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# pyenv +.python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# celery beat schedule file +celerybeat-schedule + +# SageMath parsed files +*.sage.py + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# Mr Developer +.mr.developer.cfg +.project +.pydevproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +### macOS ### +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### VirtualEnv ### +# Virtualenv +# http://iamzed.com/2009/05/07/a-primer-on-virtualenv/ +[Bb]in +[Ii]nclude +[Ll]ib +[Ll]ib64 +[Ll]ocal +[Ss]cripts +pyvenv.cfg +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ +pip-selfcheck.json + +### VisualStudioCode ### +.vscode +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json + +### VisualStudioCode Patch ### +# Ignore all local history of files +.history + +# End of https://www.gitignore.io/api/macos,django,virtualenv,visualstudiocode diff --git a/graderng/.gitignore b/graderng/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..b8a48286d71a54c4c7ffcdde683791fc3ecd0fd8 --- /dev/null +++ b/graderng/.gitignore @@ -0,0 +1,181 @@ + +# Created by https://www.gitignore.io/api/macos,django,virtualenv,visualstudiocode +# Edit at https://www.gitignore.io/?templates=macos,django,virtualenv,visualstudiocode + +### Django ### +*.log +*.pot +*.pyc +__pycache__/ +local_settings.py +db.sqlite3 +db.sqlite3-journal +media + +# If your build process includes running collectstatic, then you probably don't need or want to include staticfiles/ +# in your Git repository. Update and uncomment the following line accordingly. +# <django-project-name>/staticfiles/ + +### Django.Python Stack ### +# Byte-compiled / optimized / DLL files +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +pip-wheel-metadata/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# pyenv +.python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# celery beat schedule file +celerybeat-schedule + +# SageMath parsed files +*.sage.py + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# Mr Developer +.mr.developer.cfg +.project +.pydevproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +### macOS ### +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### VirtualEnv ### +# Virtualenv +# http://iamzed.com/2009/05/07/a-primer-on-virtualenv/ +[Bb]in +[Ii]nclude +[Ll]ib +[Ll]ib64 +[Ll]ocal +[Ss]cripts +pyvenv.cfg +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ +pip-selfcheck.json + +### VisualStudioCode ### +.vscode +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json + +### VisualStudioCode Patch ### +# Ignore all local history of files +.history + +# End of https://www.gitignore.io/api/macos,django,virtualenv,visualstudiocode diff --git a/graderng/Dockerfile b/graderng/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..076c37a25a2ef22514140b7d63d4caeb9ac00e02 --- /dev/null +++ b/graderng/Dockerfile @@ -0,0 +1,18 @@ +FROM openjdk:8-alpine3.9 + +RUN apk update \ + && apk add --no-cache bash git make gcc libcap-dev musl-dev diffutils \ + python3 py3-pillow + +ENV ISOLATE_VERSION v1.8.1 +RUN git clone --branch $ISOLATE_VERSION --depth 1 https://github.com/ioi/isolate \ + && cd isolate \ + && make install + +RUN mkdir /graderng +COPY . /graderng +WORKDIR /graderng + +RUN pip3 install -r requirements.txt + +ENTRYPOINT ["./entrypoint.sh"] diff --git a/graderng/README.md b/graderng/README.md new file mode 100644 index 0000000000000000000000000000000000000000..0a3f5c95ca6053bc58db82ac6a2f80e771e78083 --- /dev/null +++ b/graderng/README.md @@ -0,0 +1,116 @@ +# Grader-NG + +Data Structures and Algorithms Grader + +## Development + +1. Make sure Docker already installed and virtual environment already created. + +1. Install Pillow and its dependencies. + + ``` + pip install Pillow + ``` + +1. Install all requirements. + + ``` + pip install -r requirements.txt + ``` + +1. Run MongoDB. + + ``` + docker run --rm -d -p 27017:27017 --name=test-mongo mongo + ``` + +1. Run Redis. + + ``` + docker run --rm -d -p 6379:6379 --name test-redis redis + ``` + +1. Run worker. + + ``` + celery -A graderng worker --loglevel=info + ``` + +## Production + +1. Install `docker` and `docker-compose`. + +1. Create `.env` file. + + ``` + DJANGO_SECRET_KEY=thisissecretkey + DJANGO_ENV=debug + DJANGO_MEDIA_LOCATION=/home/user/blablabla + + MONGO_DATA_LOCATION=/home/user/mongo/gogogogo + MONGO_DBNAME=sofita + MONGO_USERNAME=mongousername + MONGO_PASSWORD=mongopassword + MONGO_HOST=mongo + MONGO_PORT=27017 + + REDIS_PASSWORD=redispwd + REDIS_HOST=redis + REDIS_PORT=6379 + + SCELE_URL=http://172.20.0.1/webservice/rest/server.php + SCELE_TOKEN=887bfe50daa8b8e518dd38e3832199b6 + ``` + +1. Run all services. + + ``` + docker-compose up -d + ``` + +1. Create superuser. + + ``` + docker-compose exec web python3 manage.py createsuperuser + ``` + +1. Generate token for SCELE. + +1. Add `grader_url` and `grader_token` variable to `config.php` at SCELE. + + ``` + $CFG->grader_url = "<grader_url>" + $CFG->grader_token = "<grader_token>" + ``` + +## Apache + +1. Enable proxy. + + ``` + sudo a2enmod proxy + sudo service apache2 restart + ``` + +1. Modify apache2 config `/etc/apache2/sites-available/000-default.conf`. + + ``` + <VirtualHost *:80> + ProxyPreserveHost On + + ProxyPass / http://127.0.0.1:8080/ + ProxyPassReverse / http://127.0.0.1:8080/ + </VirtualHost> + ``` + +1. Restart service. + + ``` + sudo service apache2 restart + ``` + +## Important Notes + +1. Use `sqlparse==0.2.4` +2. Server cannot access internet. Use `squid` to create proxy. +3. Server use [ouroboros](https://github.com/pyouroboros/ouroboros) to update container automatically. diff --git a/graderng/app/__init__.py b/graderng/app/__init__.py index edf4a77dbeeba263ca32eb541e0f88f240b1f469..58d70c0eabbaa815f8fe2446843f768e8b7db57c 100644 --- a/graderng/app/__init__.py +++ b/graderng/app/__init__.py @@ -4,4 +4,7 @@ from django.conf import settings redis_connection_pool = redis.ConnectionPool( - host=settings.REDIS_HOST, port=settings.REDIS_PORT, db=1) + host=settings.REDIS_HOST, + port=settings.REDIS_PORT, + password=settings.REDIS_PASSWORD, + db=1) diff --git a/graderng/docker-compose.yml b/graderng/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..6120e98ec83d230fa28a2340e1165fe2627bdb8f --- /dev/null +++ b/graderng/docker-compose.yml @@ -0,0 +1,38 @@ +version: "3.7" +services: + web: + build: . + depends_on: + - redis + - mongo + env_file: .env + ports: + - 8080:8080 + privileged: true + volumes: + - ${DJANGO_MEDIA_LOCATION}:/graderng/media + + worker: + build: . + depends_on: + - redis + - mongo + - web + command: ["celery"] + env_file: .env + privileged: true + volumes: + - ${DJANGO_MEDIA_LOCATION}:/graderng/media + + redis: + image: redis:5.0.6 + command: redis-server --requirepass ${REDIS_PASSWORD} + + mongo: + image: mongo:4.2.1 + environment: + MONGO_INITDB_ROOT_USERNAME: ${MONGO_USERNAME} + MONGO_INITDB_ROOT_PASSWORD: ${MONGO_PASSWORD} + MONGO_INITDB_DATABASE: ${MONGO_DBNAME} + volumes: + - ${MONGO_DATA_LOCATION}:/data/db diff --git a/graderng/entrypoint.sh b/graderng/entrypoint.sh new file mode 100755 index 0000000000000000000000000000000000000000..ccde3a1922c88660b07380930075de73ceaedad2 --- /dev/null +++ b/graderng/entrypoint.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +if [ "$1" == "celery" ]; then + celery -A graderng worker +else + python3 manage.py collectstatic --noinput + python3 manage.py migrate + gunicorn graderng.wsgi --workers 3 --bind 0.0.0.0:8080 +fi diff --git a/graderng/graderng/settings.py b/graderng/graderng/settings.py index e7396354c1dd6d0af762130b1090be124d307b88..1d102af61cc9e3b4419fb8b0d1cbd8011a617111 100644 --- a/graderng/graderng/settings.py +++ b/graderng/graderng/settings.py @@ -21,7 +21,7 @@ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = os.environ.get( - 'SECRET_KEY', '#d6a5ogl)__t+h8!jx)$0vi)wk7znxscg)58hm+ljncg=@^j6k') + 'DJANGO_SECRET_KEY', '#d6a5ogl)__t+h8!jx)$0vi)wk7znxscg)58hm+ljncg=@^j6k') # SECURITY WARNING: don't run with debug turned on in production! DEBUG = (os.environ.get("DJANGO_ENV", "debug") == "debug") @@ -46,6 +46,9 @@ INSTALLED_APPS = [ MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', + + 'whitenoise.middleware.WhiteNoiseMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', @@ -81,7 +84,11 @@ WSGI_APPLICATION = 'graderng.wsgi.application' DATABASES = { 'default': { 'ENGINE': 'djongo', - 'NAME': 'test-mongo', + 'NAME': os.environ.get('MONGO_DBNAME', 'test-mongo'), + 'USER': os.environ.get('MONGO_USERNAME'), + 'PASSWORD': os.environ.get('MONGO_PASSWORD'), + 'HOST': os.environ.get('MONGO_HOST'), + 'PORT': int(os.environ.get('MONGO_PORT', 27017)) } } @@ -144,17 +151,17 @@ FILEBROWSER_MAX_UPLOAD_SIZE = 100 * 1024 * 1024 # Redis -REDIS_HOST = "localhost" +REDIS_PASSWORD = os.environ.get("REDIS_PASSWORD") -REDIS_PORT = 6379 +REDIS_HOST = os.environ.get("REDIS_HOST", "localhost") -REDIS_PASSWORD = os.environ.get("REDIS_PASSWORD") +REDIS_PORT = os.environ.get("REDIS_PORT", 6379) # Celery -CELERY_BROKER_URL = os.environ.get( - "CELERY_BROKER_URL", "redis://localhost:6379/0") +CELERY_BROKER_URL = "redis://:{}@{}:{}/0".format( + REDIS_PASSWORD, REDIS_HOST, REDIS_PORT) # SCELE diff --git a/graderng/requirements.txt b/graderng/requirements.txt index b538ada1faef1a4d74418edcba37f06802b61ef7..76bcda1768d80cea0ec626abe8478f4ce6e07e46 100644 --- a/graderng/requirements.txt +++ b/graderng/requirements.txt @@ -3,7 +3,8 @@ django-filebrowser-no-grappelli==3.7.8 Django==2.2.6 djangorestframework==3.10.3 djongo==1.2.36 -Pillow==6.2.1 +gunicorn==20.0.0 redis==3.3.11 requests==2.22.0 sqlparse==0.2.4 +whitenoise==4.1.4