2020-07-28 20:19:52 +02:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
from flask import request, jsonify, current_app, abort, Response
|
|
|
|
from flask_classful import FlaskView, route
|
|
|
|
from model import db, Default, AIModel, AIModelType
|
|
|
|
from minio.error import NoSuchKey
|
|
|
|
from schemas import AIModelSchema, DefaultSchema, InfoSchema
|
|
|
|
from marshmallow.exceptions import ValidationError
|
2020-10-02 03:28:40 +02:00
|
|
|
from utils import multipart_required, storage, ensure_buckets
|
2020-07-28 20:19:52 +02:00
|
|
|
|
|
|
|
|
|
|
|
class CNNView(FlaskView):
|
2020-09-14 02:05:14 +02:00
|
|
|
route_base = 'cnn'
|
|
|
|
|
2020-07-28 20:19:52 +02:00
|
|
|
aimodel_schema = AIModelSchema(many=False)
|
|
|
|
info_schema = InfoSchema(many=False)
|
|
|
|
|
2020-10-02 03:28:40 +02:00
|
|
|
@multipart_required
|
2020-07-28 20:19:52 +02:00
|
|
|
def post(self):
|
|
|
|
|
|
|
|
# get important data from the request
|
|
|
|
try:
|
|
|
|
info = self.info_schema.loads(request.form.get('info'))
|
|
|
|
except ValidationError as e:
|
|
|
|
abort(400, str(e))
|
|
|
|
|
|
|
|
# check for conflict
|
|
|
|
m = AIModel.query.filter_by(id=info['id']).first()
|
|
|
|
if m:
|
|
|
|
abort(409)
|
|
|
|
|
|
|
|
# get and validate file
|
|
|
|
model_file = request.files['modelFile']
|
|
|
|
|
|
|
|
if model_file.content_length <= 0:
|
|
|
|
abort(411, f"Content length for modelFile is not a positive integer or missing.")
|
|
|
|
|
|
|
|
weights_file = request.files['weightsFile']
|
|
|
|
|
|
|
|
if weights_file.content_length <= 0:
|
|
|
|
abort(411, f"Content length for weightsFile is not a positive integer or missing.")
|
|
|
|
|
|
|
|
# create bucket if necessary
|
|
|
|
ensure_buckets()
|
|
|
|
|
2020-09-14 02:25:31 +02:00
|
|
|
# Create the entry in the db
|
2020-10-02 03:28:40 +02:00
|
|
|
m = AIModel(id=info['id'], type=AIModelType.cnn, target_class_name=info['target_class_name'])
|
2020-09-14 02:25:31 +02:00
|
|
|
|
2020-07-28 20:19:52 +02:00
|
|
|
# Put files into MinIO
|
|
|
|
storage.connection.put_object(current_app.config['MINIO_CNN_BUCKET_NAME'], "model/" + str(m.id), model_file,
|
|
|
|
model_file.content_length, content_type=model_file.content_type)
|
|
|
|
|
|
|
|
storage.connection.put_object(current_app.config['MINIO_CNN_BUCKET_NAME'], "weights/" + str(m.id), weights_file,
|
|
|
|
weights_file.content_length, content_type=weights_file.content_type)
|
|
|
|
|
|
|
|
db.session.add(m)
|
|
|
|
db.session.commit()
|
|
|
|
|
|
|
|
return jsonify(self.aimodel_schema.dump(m)), 200
|
|
|
|
|
|
|
|
def delete(self, _id: str):
|
|
|
|
|
|
|
|
if _id == "$default":
|
2020-10-02 03:28:40 +02:00
|
|
|
default = Default.query.filter_by(type=AIModelType.cnn).first_or_404()
|
2020-07-28 20:19:52 +02:00
|
|
|
m = default.aimodel
|
|
|
|
else:
|
2020-10-02 03:28:40 +02:00
|
|
|
m = AIModel.query.filter_by(type=AIModelType.cnn, id=_id).first_or_404()
|
2020-07-28 20:19:52 +02:00
|
|
|
|
|
|
|
storage.connection.remove_object(current_app.config['MINIO_CNN_BUCKET_NAME'], "weights/" + str(m.id))
|
|
|
|
storage.connection.remove_object(current_app.config['MINIO_CNN_BUCKET_NAME'], "model/" + str(m.id))
|
|
|
|
|
|
|
|
db.session.delete(m)
|
|
|
|
db.session.commit()
|
|
|
|
|
|
|
|
return '', 204
|
|
|
|
|
2020-10-02 03:28:40 +02:00
|
|
|
@route('<_id>/file')
|
|
|
|
def get_file(self, _id: str):
|
2020-07-28 20:19:52 +02:00
|
|
|
|
2020-10-02 03:28:40 +02:00
|
|
|
if _id == "$default":
|
|
|
|
default = Default.query.filter_by(type=AIModelType.cnn).first_or_404()
|
|
|
|
m = default.aimodel
|
|
|
|
else:
|
|
|
|
m = AIModel.query.filter_by(type=AIModelType.cnn, id=_id).first_or_404()
|
2020-07-28 20:19:52 +02:00
|
|
|
|
2020-10-02 03:28:40 +02:00
|
|
|
if "weights" in request.args:
|
|
|
|
path = "weights/" + str(m.id)
|
|
|
|
else:
|
|
|
|
path = "model/" + str(m.id)
|
2020-07-28 20:19:52 +02:00
|
|
|
|
2020-10-02 03:28:40 +02:00
|
|
|
try:
|
|
|
|
data = storage.connection.get_object(current_app.config['MINIO_CNN_BUCKET_NAME'], path)
|
|
|
|
except NoSuchKey:
|
|
|
|
abort(500, "The ID is stored in the database but not int the Object Store")
|
2020-07-28 20:19:52 +02:00
|
|
|
|
2020-10-02 03:28:40 +02:00
|
|
|
return Response(data.stream(), mimetype=data.headers['Content-type'])
|