diff --git a/README.md b/README.md index 55f6995f..e591d825 100644 --- a/README.md +++ b/README.md @@ -81,7 +81,14 @@ This REST API is built using the `flask-restful` package and has been containeri In order to run the Flask GCBM API, navigate to the `local/rest_api_gcbm` please follow the following steps: - 1. `docker build --build-arg BUILD_TYPE=RELEASE --build-arg NUM_CPU=4 -t gcbm-api .` -2. `docker run --rm -p 8080:8080 gcbm-api` + +To run instruction 2, the zip file, `GCBM_Demo_Run.zip` present in the root of the directory must be unzipped. + +2. `docker run -v path-to-unzipped-folder:/gcbm_files --rm -p 8080:8080 gcbm-api` + +For example, if the location of the unzipped folder is `/home/GCBM`, instruction 2 will be given as : + +2. `docker run -v /home/GCBM:/gcbm_files --rm -p 8080:8080 gcbm-api` Currently the REST API has the following endpoints available for access:- diff --git a/local/rest_api_gcbm/app.py b/local/rest_api_gcbm/app.py index fd8ec8b2..8010ed42 100644 --- a/local/rest_api_gcbm/app.py +++ b/local/rest_api_gcbm/app.py @@ -44,6 +44,12 @@ logger.addHandler(c_handler) +# The path of the volume is referenced here +INPUT_FOLDER = "../gcbm_files/" +LAYERS = os.path.join(INPUT_FOLDER, "layers/tiled") +INPUT_DATABASE = os.path.join(INPUT_FOLDER, "input_database") +CONFIG = os.path.join(INPUT_FOLDER, "config") + ### swagger specific ### SWAGGER_URL = '/swagger' API_URL = '/static/swagger.json' @@ -157,7 +163,7 @@ def gcbm_new(): return {'data': message}, 200 -@app.route('/gcbm/upload', methods=['POST']) +@app.route("/gcbm/upload", methods=["POST"]) def gcbm_upload(): """ Upload files for GCBM Dynamic implementation of FLINT @@ -179,7 +185,6 @@ def gcbm_upload(): title = request.form.get('title') or 'simulation' # Sanitize title title = ''.join(c for c in title if c.isalnum()) - # Create project directory project_dir = f'{title}' if not os.path.exists(f'{os.getcwd()}/input/{project_dir}'): @@ -189,51 +194,48 @@ def gcbm_upload(): # Function to flatten paths def fix_path(path): return os.path.basename(path.replace('\\', '/')) - # Process configuration files - if 'config_files' in request.files: - for file in request.files.getlist('config_files'): + if os.path.isdir(CONFIG): + for file in os.listdir(CONFIG): # Fix paths in provider_config - if file.filename == 'provider_config.json': - provider_config = json.load(file) - provider_config['Providers']['SQLite']['path'] = fix_path( - provider_config['Providers']['SQLite']['path']) - layers = [] - for layer in provider_config['Providers']['RasterTiled']['layers']: - layer['layer_path'] = fix_path(layer['layer_path']) - layers.append(layer) - provider_config['Providers']['RasterTiled']['layers'] = layers - with open(f'{os.getcwd()}/input/{project_dir}/provider_config.json', 'w') as pcf: - json.dump(provider_config, pcf) - # Fix paths in modules_output - elif file.filename == 'modules_output.json': - modules_output = json.load(file) - modules_output['Modules']['CBMAggregatorSQLiteWriter']['settings']['databasename'] = 'output/gcbm_output.db' - modules_output['Modules']['WriteVariableGeotiff']['settings']['output_path'] = 'output' - with open(f'{os.getcwd()}/input/{project_dir}/modules_output.json', 'w') as mof: - json.dump(modules_output, mof) - else: - # Save file immediately - file.save(f'{os.getcwd()}/input/{project_dir}/{file.filename}') + if os.path.isfile(os.path.join(CONFIG, file)): + file_reader = open(os.path.join(CONFIG, file)) + if file == 'provider_config.json': + provider_config = json.load(file_reader) + provider_config['Providers']['SQLite']['path'] = fix_path( + provider_config['Providers']['SQLite']['path']) + layers = [] + for layer in provider_config['Providers']['RasterTiled']['layers']: + layer['layer_path'] = fix_path(layer['layer_path']) + layers.append(layer) + provider_config['Providers']['RasterTiled']['layers'] = layers + with open(f'{os.getcwd()}/input/{project_dir}/provider_config.json', 'w') as pcf: + json.dump(provider_config, pcf, indent=4) + # Fix paths in modules_output + elif file == 'modules_output.json': + modules_output = json.load(file_reader) + modules_output['Modules']['CBMAggregatorSQLiteWriter']['settings']['databasename'] = 'output/gcbm_output.db' + modules_output['Modules']['WriteVariableGeotiff']['settings']['output_path'] = 'output' + with open(f'{os.getcwd()}/input/{project_dir}/modules_output.json', 'w') as mof: + json.dump(modules_output, mof, indent=4) + else: + # Copy file immediately to the new location from the mounted volume + shutil.copy(os.path.join(CONFIG, file), f'{os.getcwd()}/input/{project_dir}/{file}') + file_reader.close() else: return {'error': 'Missing configuration file'}, 400 - - # Save input - if 'input' in request.files: - for file in request.files.getlist('input'): - # Save file immediately - file.save(f'{os.getcwd()}/input/{project_dir}/{file.filename}') + if os.path.isdir(LAYERS): + for file in os.listdir(LAYERS): + # Copy file immediately to the new location from the mounted volume + shutil.copy(os.path.join(LAYERS, file), f'{os.getcwd()}/input/{project_dir}/{file}') else: return {'error': 'Missing input'}, 400 - - # Save db - if 'db' in request.files: - for file in request.files.getlist('db'): - # Save file immediately - file.save(f'{os.getcwd()}/input/{project_dir}/{file.filename}') + if os.path.isdir(INPUT_DATABASE): + for file in os.listdir(INPUT_DATABASE): + # Copy file immediately to the new location from the mounted volume + shutil.copy(os.path.join(INPUT_DATABASE, file), f'{os.getcwd()}/input/{project_dir}/{file}') else: return {'error': 'Missing database'}, 400 - return {"data": "All files uploaded sucessfully. Proceed to the next step of the API at gcbm/dynamic."}, 200