Skip to content

Commit 6366585

Browse files
committed
registry service
1 parent fdee139 commit 6366585

File tree

5 files changed

+135
-0
lines changed

5 files changed

+135
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
venv/

files/service_registry.service

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
[Unit]
2+
Description=Dragon Cafe Service Registry
3+
4+
[Service]
5+
User=root
6+
Group=root
7+
8+
WorkingDirectory=/home/student/dragon-cafe
9+
ExecStart=/home/student/dragon-cafe/venv/bin/python3 service_registry.py
10+
11+
StandardOutput=syslog
12+
StandardError=syslog
13+
SyslogIdentifier=dragon-cafe-sr
14+
15+
[Install]
16+
WantedBy=multi-user.target

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ jinja2==3.0.1
33
beautifulsoup4==4.9.3
44
bs4==0.0.1
55
requests==2.25.1
6+
aiosqlite==0.17.0

service_registry.db

12 KB
Binary file not shown.

service_registry.py

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
#!/usr/bin/env python3
2+
3+
from aiohttp import web
4+
import os
5+
import aiosqlite
6+
import datetime
7+
import random
8+
import subprocess
9+
import jinja2
10+
import pwd
11+
import grp
12+
13+
PORT = os.getenv("SR_PORT", 55555)
14+
HOST = os.getenv("SR_HOST", "0.0.0.0")
15+
DB_NAME = os.getenv("SR_DB_NAME", "service_registry.db")
16+
17+
18+
def routes(app: web.Application) -> None:
19+
app.add_routes(
20+
[
21+
web.get("/add/{service}/{ip}/{port}", add_service),
22+
web.get("/remove/{service}/{ip}/{port}", remove_service),
23+
web.get("/heartbeat/{service}/{ip}/{port}", heartbeat),
24+
web.get("/get/{service}", get_service),
25+
web.get("/get_one/{service}", get_one_service)
26+
]
27+
)
28+
return None
29+
30+
31+
async def add_service(request):
32+
service = request.match_info.get('service')
33+
ip = request.match_info.get('ip')
34+
port = request.match_info.get('port')
35+
print(f"Adding the {service} service")
36+
async with aiosqlite.connect(DB_NAME) as db:
37+
sql = f"CREATE TABLE IF NOT EXISTS {service} (ip CHAR(16), port INT, heartbeat CHAR(50), alive BOOL);"
38+
await db.execute(sql)
39+
await db.commit()
40+
now = datetime.datetime.now()
41+
sql2 = f"INSERT INTO {service} (ip, port, heartbeat, alive) VALUES ('{ip}', '{port}', '{now}', 'TRUE');"
42+
try:
43+
await db.execute(sql2)
44+
await db.commit()
45+
txt = ""
46+
except aiosqlite.IntegrityError as err:
47+
txt = f"{service} service already exists"
48+
return web.Response(text=txt)
49+
50+
51+
async def heartbeat(request):
52+
service = request.match_info.get('service')
53+
ip = request.match_info.get('ip')
54+
port = request.match_info.get('port')
55+
print(f"Adding heartbeat")
56+
async with aiosqlite.connect(DB_NAME) as db:
57+
now = datetime.datetime.now()
58+
sql = f"UPDATE {service} set heartbeat = '{now}' where ip like '{ip}' AND port like '{port}';"
59+
await db.execute(sql)
60+
await db.commit()
61+
return web.Response()
62+
63+
64+
async def remove_service(request):
65+
service = request.match_info.get('service')
66+
ip = request.match_info.get('ip')
67+
port = request.match_info.get('port')
68+
print(f"Removing {ip} from the {service} service")
69+
async with aiosqlite.connect(DB_NAME) as db:
70+
now = datetime.datetime.now()
71+
sql = f"UPDATE {service} set heartbeat = '{now}', alive = 'FALSE' where ip like '{ip}' AND port like '{port}';"
72+
print(sql)
73+
await db.execute(sql)
74+
await db.commit()
75+
return web.Response()
76+
77+
78+
async def get_service(request):
79+
service = request.match_info.get('service')
80+
async with aiosqlite.connect(DB_NAME) as db:
81+
sql = f"SELECT DISTINCT ip,port from {service} where alive = 'TRUE';"
82+
resp = await db.execute(sql)
83+
await db.commit()
84+
fetched = await resp.fetchall()
85+
services = {'endpoints': fetched}
86+
return web.json_response(services)
87+
88+
89+
async def get_one_service(request):
90+
service = request.match_info.get('service')
91+
async with aiosqlite.connect(DB_NAME) as db:
92+
sql = f"SELECT ip,port from {service} where alive = 'TRUE';"
93+
resp = await db.execute(sql)
94+
await db.commit()
95+
fetched = await resp.fetchall()
96+
chosen = random.choice(fetched)
97+
services = {'endpoints': chosen}
98+
return web.json_response(services)
99+
100+
101+
def main():
102+
"""
103+
This is the main process for the aiohttp server.
104+
This works by instantiating the app as a web.Application(),
105+
then applying the setup function we built in our routes
106+
function to add routes to our app, then by starting the async
107+
event loop with web.run_app().
108+
"""
109+
110+
print("This aiohttp web server is starting up!")
111+
app = web.Application()
112+
routes(app)
113+
web.run_app(app, host=HOST, port=PORT)
114+
115+
116+
if __name__ == "__main__":
117+
main()

0 commit comments

Comments
 (0)