Coder Social home page Coder Social logo

atlarge-research / opendc-web-server Goto Github PK

View Code? Open in Web Editor NEW
4.0 13.0 2.0 273 KB

Python web server for the OpenDC project.

Home Page: https://github.com/atlarge-research/opendc

License: MIT License

Python 99.42% HTML 0.58%
python web-server flask socket-io websocket-server opendc tu-delft

opendc-web-server's Introduction

We are moving towards a mono-repo code model in v2.0 of OpenDC.
See the main repo for the latest version, which now has the code previously contained in this sub-repo embedded in it.

OpenDC
OpenDC Web Server

Collaborative Datacenter Simulation and Exploration for Everybody

The OpenDC web server is the bridge between OpenDC's frontend and database. It is built with Flask/SocketIO in Python and implements the OpenAPI-compliant OpenDC API specification.

This document explains a high-level view of the web server architecture (jump), and describes how to set up the web server for local development (jump).

Architecture

The following diagram shows a high-level view of the architecture of the OpenDC web server. Squared-off colored boxes indicate packages (colors become more saturated as packages are nested); rounded-off boxes indicate individual components; dotted lines indicate control flow; and solid lines indicate data flow.

OpenDC Web Server Component Diagram

The OpenDC API is implemented by the Main Server Loop, which is the only component in the base package.

Util Package

The Util package handles several miscellaneous tasks:

  • REST: Parses SockerIO messages into Request objects, and calls the appropriate API endpoint to get a Response object to return to the Main Server Loop.
  • Param Checker: Recursively checks whether required Request parameters are present and correctly typed.
  • Exceptions: Holds definitions for exceptions used throughout the web server.
  • Database API: Wraps SQLite functionality used by Models to read themselves from/ write themselves into the database.

API Package

The API package contains the logic for the HTTP methods in each API endpoint. Packages are structured to mirror the API: the code for the endpoint GET simulations/authorizations, for example, would be located at the Endpoint inside the authorizations package, inside the simulations package (so at api/simulations/authorizations/endpoint.py).

An Endpoint contains methods for each HTTP method it supports, which takes a request as input (such as def GET(request):). Typically, such a method checks whether the parameters were passed correctly (using the Param Checker); fetches some model from the database; checks whether the data exists and is accessible by the user who made the request; possibly modifies this data and writes it back to the database; and returns a JSON representation of the model.

The REST component dynamically imports the appropriate method from the appropriate Endpoint, according to request it receives, and executes it.

Models Package

The Models package contains the logic for mapping Python objects to their database representations. This involves an abstract model which has methods to read, insert, update and delete objects. Extensions of model, such as a User or Simulation, specify some metadata such as their tabular representation in the database and how they map to a JSON object, which the code in model uses in the database interaction methods.

Endpoints import these Models and use them to execute requests.

Setup for Local Development

The following steps will guide you through setting up the OpenDC web server locally for development. To test individual endpoints, edit static/index.html. This guide was tested and developed on Windows 10.

Local Setup

Install requirements

Make sure you have Python 2.7 installed (if not, get it here), as well as pip (if not, get it here). Then run the following to install the requirements.

python setup.py install

The web server also requires MariaDB >= 10.1. Instructions to install MariaDB can be found here. The Docker image can be found here.

Get the code

Clone both this repository and the main OpenDC repository, from the same base directory.

git clone https://github.com/atlarge-research/opendc-web-server.git
git clone https://github.com/atlarge-research/opendc.git

Set up the database

The database can be rebuilt by using the schema.sql file from main opendc repository.

Configure OpenDC

Create a file config.json in opendc-web-server, containing:

{
	"ROOT_DIR": "BASE_DIRECTORY",
	"OAUTH_CLIENT_ID": "OAUTH_CLIENT_ID",
	"FLASK_SECRET": "FLASK_SECRET",
	"MYSQL_DATABASE": "opendc",
	"MYSQL_USER": "opendc",
	"MYSQL_PASSWORD": "opendcpassword",
	"MYSQL_HOST": "127.0.0.1",
	"MYSQL_PORT": 3306
}

Make the following replacements:

  • Replace BASE_DIRECTORY with the base directory in which you cloned opendc and opendc-web-server.
  • Replace OAUTH_CLIENT_ID with your OAuth client ID (see the OpenDC README).
  • Replace FLASK_SECRET, come up with some string.
  • Replace the MYSQL_* variables with the correct settings for accessing the MariaDB database that was just created.

In opendc-web-server/static/index.html, add your own OAUTH_CLIENT_ID in content= on line 2.

Set up Postman and OpenDC account

To easily make HTTP requests to the web server, we recommend Postman (get it here).

Once Postman is installed and set up, Import the OpenDC requests collection (OpenDC.postman_collection.json). In the Collections tab, expand OpenDC and click Create New User. This should open the request in the Builder pane.

Navigate to http://localhost:8081/my-auth-token and copy the authentication token on this page to your clipboard. In the Postman Builder pane, navigate to the Headers (2) tab, and paste the authentication token as value for the auth-token header. (This token expires every hour - refresh the auth token page to get a new token.)

(Optional: navigate to the Body tab and change the email address to the gmail address you used to get an authentication token.)

Click Send in Postman to send your request and see the server's response. If it's a 200, your account is set up!

Local Development

Run the server.

cd opendc-web-server
python main.py config.json

To try a different query, use the Postman Builder to edit the method, path, body, query parameters, etc. Create New Simulation is provided as an additional example.

When editing the web server code, restart the server (CTRL + c followed by python main.py config.json in the console running the server) to see the result of your changes.

opendc-web-server's People

Contributors

fabianishere avatar gandreadis avatar leonoverweel avatar sacheendra avatar

Stargazers

 avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

opendc-web-server's Issues

Instruction order in web-server setup could be better

In the setup instructions for the opendc web server you are told to navigate to localhost:8081/my-auth-token in order to set up postman, but you only get told to run the server after you've set up postman. It might be clearer to switch the order around.

Connection pool exhausted after multiple failures

Today I had to restart the opendc.org webserver, since we were unable to make any API request due to the database connection pool being exhausted:

 [2018-11-27 10:18:48,275] ERROR in app: Exception on /tokensignin [POST]
Traceback (most recent call last):
   File "/usr/local/lib/python2.7/dist-packages/Flask-1.0.2-py2.7.egg/flask/app.py", line 2292, in wsgi_app
     response = self.full_dispatch_request()
   File "/usr/local/lib/python2.7/dist-packages/Flask-1.0.2-py2.7.egg/flask/app.py", line 1815, in full_dispatch_request
     rv = self.handle_user_exception(e)
   File "/usr/local/lib/python2.7/dist-packages/Flask-1.0.2-py2.7.egg/flask/app.py", line 1718, in handle_user_exception
     reraise(exc_type, exc_value, tb)
   File "/usr/local/lib/python2.7/dist-packages/Flask-1.0.2-py2.7.egg/flask/app.py", line 1813, in full_dispatch_request
     rv = self.dispatch_request()
   File "/usr/local/lib/python2.7/dist-packages/Flask-1.0.2-py2.7.egg/flask/app.py", line 1799, in dispatch_request
     return self.view_functions[rule.endpoint](**req.view_args)
   File "opendc-web-server/main.py", line 69, in sign_in
     user = User.from_google_id(idinfo['sub'])
   File "/opendc/opendc-web-server/opendc/models/user.py", line 23, in from_google_id
     user = cls._from_database('SELECT * FROM users WHERE google_id = %s', (google_id,))
   File "/opendc/opendc-web-server/opendc/models/model.py", line 166, in _from_database
     model_from_database = database.fetchone(statement, values)
   File "/opendc/opendc-web-server/opendc/util/database.py", line 47, in fetchone
     connection = CONNECTION_POOL.get_connection()
   File "build/bdist.linux-x86_64/egg/mysql/connector/pooling.py", line 310, in get_connection
     "Failed getting connection; pool exhausted")
 PoolError: Failed getting connection; pool exhausted

This only occurred after several error responses (such as OccupiedTilePosition) and leads me to believe we are not properly returning connections to their pool after an error occurs.

`[Errno 32] Broken pipe` on early client disconnect

Sometimes the server throws the following stack trace:

Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/eventlet/wsgi.py", line 515, in handle_one_response
    write(b''.join(towrite))
  File "/usr/local/lib/python2.7/dist-packages/eventlet/wsgi.py", line 462, in write
    wfile.flush()
  File "/usr/lib/python2.7/socket.py", line 307, in flush
    self._sock.sendall(view[write_offset:write_offset+buffer_size])
  File "/usr/local/lib/python2.7/dist-packages/eventlet/greenio/base.py", line 390, in sendall
    tail = self.send(data, flags)
  File "/usr/local/lib/python2.7/dist-packages/eventlet/greenio/base.py", line 384, in send
    return self._send_loop(self.fd.send, data, flags)
  File "/usr/local/lib/python2.7/dist-packages/eventlet/greenio/base.py", line 371, in _send_loop
    return send_method(data, *args)
error: [Errno 32] Broken pipe

Problem is probably a client disconnecting early, or the socket closing some other way. See http://stackoverflow.com/questions/11866792/how-to-prevent-errno-32-broken-pipe.

Implement batch simulation state fetching

To ensure that the frontend can fetch states in reasonable chunks, the webserver should support fetching states in batches of predefined size. This would also need to be reflected in the API specification.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.