osmo-lpmgd/osmocom/lpmgd/rest_server.py

115 lines
3.9 KiB
Python

import json
# (C) 2023 by Harald Welte <laforge@osmocom.org>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from typing import List
from klein import Klein
import osmocom.lpmgd.model as model
def set_headers(request):
request.setHeader('Content-Type', 'application/json')
class ApiError:
def __init__(self, msg:str, sw=None):
self.msg = msg
self.sw = sw
def __str__(self):
d = {'error': {'message':self.msg}}
if self.sw:
d['error']['status_word'] = self.sw
return json.dumps(d)
class PwrMgmtRestServer:
app = Klein()
def __init__(self, resources: List[model.Resource]):
self.resources = {r.name: r for r in resources}
@app.handle_errors(KeyError)
def key_error(self, request, failure):
set_headers(request)
request.setResponseCode(404)
return str(ApiError("Unknown resource"))
@app.route('/api/v1/resource', methods=['GET'])
def resource_list(self, request):
out = []
for r in self.resources.values():
r.determine_status()
out.append(r.to_dict())
set_headers(request)
return json.dumps(out)
@app.route('/api/v1/resource/<resrc>/status', methods=['GET'])
def resource_status(self, request, resrc):
resource = self.resources[resrc]
resource.determine_status()
set_headers(request)
return json.dumps(resource.to_dict())
@app.route('/api/v1/resource/<resrc>/obtain_usage_token', methods=['POST'])
def resource_obtain_token(self, request, resrc):
resource = self.resources[resrc]
try:
content = json.loads(request.content.read())
user_name = content['user_name']
usage = content['usage']
duration_s = content['duration_seconds']
except:
set_headers(request)
request.setResponseCode(400)
return str(ApiError("Malformed Request"))
token = resource.usage_token_get(user_name, usage, duration_s)
set_headers(request)
return json.dumps(token.to_dict())
@app.route('/api/v1/resource/<resrc>/token', methods=['GET'])
def token_list(self, request, resrc):
resource = self.resources[resrc]
token_list = [t.to_dict() for t in resource.usage_tokens.values()]
set_headers(request)
request.setResponseCode(200)
return json.dumps(token_list)
@app.route('/api/v1/resource/<resrc>/token/<token_uuid>', methods=['GET'])
def token_get(self, request, resrc, token_uuid):
resource = self.resources[resrc]
# find token within resource
token = resource.usage_token_find(token_uuid)
if not token:
request.setResponseCode(404)
return
set_headers(request)
request.setResponseCode(200)
return json.dumps(token.to_dict())
@app.route('/api/v1/resource/<resrc>/token/<token_uuid>/release', methods=['GET'])
def token_release(self, request, resrc, token_uuid):
resource = self.resources[resrc]
# find token within resource
token = resource.usage_token_find(token_uuid)
if not token:
request.setResponseCode(404)
return
resource.usage_token_put(token)
#set_headers(request)
request.setResponseCode(200)