1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
<h1 align="center">
<img src="../../docs/images/logo.png" width="100" alt="OpenDC">
<br>
OpenDC Web Server
</h1>
<p align="center">
Collaborative Datacenter Simulation and Exploration for Everybody
</p>
<br>
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](../../opendc-api-spec.yml).
This document explains a high-level view of the web server architecture ([jump](#architecture)), and describes how to
set up the web server for local development ([jump](#setup-for-local-development)).
## 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.

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:
* `Database API`: Wraps database access functionality used by `Models` to read themselves from/write themselves into the
database.
* `Exceptions`: Holds definitions for exceptions used throughout the web server.
* `Parameter Checker`: Recursively checks whether required `Request` parameters are present and correctly typed.
* `REST`: Parses HTTP messages into `Request` objects, and calls the appropriate `API` endpoint to get
a `Response` object to return to the `Main Server Loop`.
### 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 api/projects`, for example, would be located at the `endpoint.py` inside
the `projects` package (so at `api/projects/endpoint.py`).
An `endpoint.py` file 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 `Parameter 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 generic CRUD operations. Extensions of `model`, such as a `User` or `Project`, specify some
more specific operations and their collection metadata.
`Endpoint`s 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.
### Local Setup
#### Install requirements
Make sure you have Python 3.7+ installed (if not, get it [here](https://www.python.org/)), as well as pip (if not, get
it [here](https://pip.pypa.io/en/stable/installing/)). Then run the following to install the requirements.
```bash
pip install -r requirements.txt
```
The web server also requires a running MongoDB instance. We recommend setting this up through docker, by
running `docker-compose build` and `docker-compose up` in the [`mongodb` directory](../../database) of the main OpenDC
repository.
#### Get and configure the code
Clone OpenDC and follow the [instructions in the main repository](../../) to set up a Google OAuth ID and environment
variables.
**Important:** Be sure to set up environment variables according to those instructions, in a `.env` file.
#### Set up the database
You can selectively run only the database services from the standard OpenDC `docker-compose` setup (in the root
directory):
```bash
docker-compose build mongo mongo-express
docker-compose up mongo mongo-express
```
This will set you up with a running MongoDB instance and a visual inspection tool running
on [localhost:8082](http://localhost:8082), with which you can view and manipulate the database. Add the simulator
images to the command lists above if you want to test simulation capabilities, as well.
### Local Development
Run the server.
```bash
python3 -m flask run --port 8081
```
When editing the web server code, restart the server (`CTRL` + `c` followed by `python app.py` in the console running
the server) to see the result of your changes.
#### Code Style
To format all files, run `format.sh` in this directory. The script uses `yapf` internally to format everything
automatically.
To check if code style is up to modern standards, run `check.sh` in this directory. The script uses `pylint` internally.
#### Testing
Run `pytest opendc` in this directory to run all tests.
|