From 0f779323898999cc6269ee2f9183de75e1eedab0 Mon Sep 17 00:00:00 2001 From: maxbr Date: Thu, 5 Jan 2017 12:34:37 +0100 Subject: Add library for dashboard API JIRA: PHAROS-265 The DashboardAPI class can be used to query and update dashboard data. Change-Id: I584a3cc500ff1d67011c18af4e73e504126310a2 Signed-off-by: maxbr --- pharos-dashboard/dashboard_api/__init__.py | 8 ++ pharos-dashboard/dashboard_api/api.py | 91 +++++++++++++++++++++++ pharos-dashboard/src/api/migrations/__init__.py | 10 +++ pharos-dashboard/src/api/serializers.py | 20 +++-- pharos-dashboard/src/api/urls.py | 1 + pharos-dashboard/src/api/views.py | 12 ++- pharos-dashboard/src/pharos_dashboard/settings.py | 11 ++- 7 files changed, 140 insertions(+), 13 deletions(-) create mode 100644 pharos-dashboard/dashboard_api/__init__.py create mode 100644 pharos-dashboard/dashboard_api/api.py create mode 100644 pharos-dashboard/src/api/migrations/__init__.py diff --git a/pharos-dashboard/dashboard_api/__init__.py b/pharos-dashboard/dashboard_api/__init__.py new file mode 100644 index 0000000..ce1acf3 --- /dev/null +++ b/pharos-dashboard/dashboard_api/__init__.py @@ -0,0 +1,8 @@ +############################################################################## +# Copyright (c) 2016 Max Breitenfeldt and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## \ No newline at end of file diff --git a/pharos-dashboard/dashboard_api/api.py b/pharos-dashboard/dashboard_api/api.py new file mode 100644 index 0000000..d40e0aa --- /dev/null +++ b/pharos-dashboard/dashboard_api/api.py @@ -0,0 +1,91 @@ +############################################################################## +# Copyright (c) 2016 Max Breitenfeldt and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + + +import logging + +import requests + +URLS = { + 'resources': '/api/resources/', + 'servers': '/api/servers/', + 'bookings': '/api/bookings', + 'resource_status': '/api/resource_status/', +} + +class DashboardAPI(object): + def __init__(self, dashboard_url, api_token='', verbose=False): + self._api_token = api_token + self._verbose = verbose + self._resources_url = dashboard_url + URLS['resources'] + self._servers_url = dashboard_url + URLS['servers'] + self._bookings_url = dashboard_url + URLS['bookings'] + self._resources_status_url = dashboard_url + URLS['resource_status'] + self._logger = logging.getLogger(__name__) + + def get_all_resources(self): + return self._get_json(self._resources_url) + + def get_resource(self, id='', name='', url=''): + if url != '': + return self._get_json(url)[0] + url = self._resources_url + self._url_parameter(id=id, name=name) + return self._get_json(url)[0] + + def get_all_bookings(self): + return self._get_json(self._bookings_url) + + def get_resource_bookings(self, resource_id): + url = self._bookings_url + self._url_parameter(resource_id=resource_id) + return self._get_json(url) + + def get_booking(self, id): + url = self._bookings_url + self._url_parameter(id=id) + return self._get_json(url)[0] + + def post_resource_status(self, resource_id, type, title, content): + data = { + 'resource': resource_id, + 'type': type, + 'title': title, + 'content': content + } + return self._post_json(self._resources_status_url, data) + + def get_url(self, url): + return self._get_json(url) + + def _url_parameter(self, **kwargs): + res = '' + prefix = '?' + for key, val in kwargs.items(): + res += prefix + key + '=' + str(val) + prefix = '&' + return res + + def _get_json(self, url): + try: + response = requests.get(url) + if self._verbose: + print('Get JSON: ' + url) + print(response.status_code, response.content) + return response.json() + except requests.exceptions.RequestException as e: + self._logger.exception(e) + except ValueError as e: + self._logger.exception(e) + + def _post_json(self, url, json): + if self._api_token == '': + raise Exception('Need api token to POST data.') + response = requests.post(url, json, headers={'Authorization': 'Token ' + self._api_token}) + if self._verbose: + print('Post JSON: ' + url) + print(response.status_code, response.content) + return response.status_code diff --git a/pharos-dashboard/src/api/migrations/__init__.py b/pharos-dashboard/src/api/migrations/__init__.py new file mode 100644 index 0000000..b5914ce --- /dev/null +++ b/pharos-dashboard/src/api/migrations/__init__.py @@ -0,0 +1,10 @@ +############################################################################## +# Copyright (c) 2016 Max Breitenfeldt and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + + diff --git a/pharos-dashboard/src/api/serializers.py b/pharos-dashboard/src/api/serializers.py index 78e6020..f8f02a2 100644 --- a/pharos-dashboard/src/api/serializers.py +++ b/pharos-dashboard/src/api/serializers.py @@ -11,22 +11,30 @@ from rest_framework import serializers from booking.models import Booking -from dashboard.models import Server, Resource +from dashboard.models import Server, Resource, ResourceStatus -class BookingSerializer(serializers.HyperlinkedModelSerializer): +class BookingSerializer(serializers.ModelSerializer): + installer_name = serializers.RelatedField(source='installer', read_only=True) + scenario_name = serializers.RelatedField(source='scenario', read_only=True) + class Meta: model = Booking - fields = ('id', 'resource', 'start', 'end', 'purpose') + fields = ('id', 'resource_id', 'start', 'end', 'installer_name', 'scenario_name', 'purpose') -class ServerSerializer(serializers.HyperlinkedModelSerializer): +class ServerSerializer(serializers.ModelSerializer): class Meta: model = Server - fields = ('id', 'resource', 'name', 'model', 'cpu', 'ram', 'storage') + fields = ('id', 'resource_id', 'name', 'model', 'cpu', 'ram', 'storage') -class ResourceSerializer(serializers.HyperlinkedModelSerializer): +class ResourceSerializer(serializers.ModelSerializer): class Meta: model = Resource fields = ('id', 'name', 'description', 'url', 'server_set') + +class ResourceStatusSerializer(serializers.ModelSerializer): + class Meta: + model = ResourceStatus + fields = ('id', 'resource', 'timestamp','type', 'title', 'content') \ No newline at end of file diff --git a/pharos-dashboard/src/api/urls.py b/pharos-dashboard/src/api/urls.py index dfbe1ac..a4a4b2f 100644 --- a/pharos-dashboard/src/api/urls.py +++ b/pharos-dashboard/src/api/urls.py @@ -32,6 +32,7 @@ router = routers.DefaultRouter() router.register(r'resources', ResourceViewSet) router.register(r'servers', ServerViewSet) router.register(r'bookings', BookingViewSet) +router.register(r'resource_status', ResourceStatusViewSet) urlpatterns = [ url(r'^', include(router.urls)), diff --git a/pharos-dashboard/src/api/views.py b/pharos-dashboard/src/api/views.py index 2595e5e..84fa1b5 100644 --- a/pharos-dashboard/src/api/views.py +++ b/pharos-dashboard/src/api/views.py @@ -15,15 +15,15 @@ from django.views import View from rest_framework import viewsets from rest_framework.authtoken.models import Token -from api.serializers import ResourceSerializer, ServerSerializer, BookingSerializer +from api.serializers import * from booking.models import Booking -from dashboard.models import Resource, Server +from dashboard.models import Resource, Server, ResourceStatus class BookingViewSet(viewsets.ModelViewSet): queryset = Booking.objects.all() serializer_class = BookingSerializer - filter_fields = ('resource', 'user') + filter_fields = ('resource', 'id') class ServerViewSet(viewsets.ModelViewSet): @@ -35,7 +35,11 @@ class ServerViewSet(viewsets.ModelViewSet): class ResourceViewSet(viewsets.ModelViewSet): queryset = Resource.objects.all() serializer_class = ResourceSerializer - filter_fields = ('name',) + filter_fields = ('name', 'id') + +class ResourceStatusViewSet(viewsets.ModelViewSet): + queryset = ResourceStatus.objects.all() + serializer_class = ResourceStatusSerializer @method_decorator(login_required, name='dispatch') diff --git a/pharos-dashboard/src/pharos_dashboard/settings.py b/pharos-dashboard/src/pharos_dashboard/settings.py index 2c4e8cc..084f878 100644 --- a/pharos-dashboard/src/pharos_dashboard/settings.py +++ b/pharos-dashboard/src/pharos_dashboard/settings.py @@ -5,7 +5,7 @@ from datetime import timedelta BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # SECURITY WARNING: don't run with debug turned on in production! -DEBUG = os.environ['DEBUG'] +DEBUG = False # Application definition @@ -25,6 +25,7 @@ INSTALLED_APPS = [ 'bootstrap3', 'crispy_forms', 'rest_framework', + 'rest_framework.authtoken', ] MIDDLEWARE = [ @@ -131,7 +132,11 @@ REST_FRAMEWORK = { 'DEFAULT_PERMISSION_CLASSES': [ 'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly' ], - 'DEFAULT_FILTER_BACKENDS': ('rest_framework.filters.DjangoFilterBackend',) + 'DEFAULT_FILTER_BACKENDS': ('rest_framework.filters.DjangoFilterBackend',), + 'DEFAULT_AUTHENTICATION_CLASSES': ( + 'rest_framework.authentication.SessionAuthentication', + 'rest_framework.authentication.TokenAuthentication', + ) } MEDIA_ROOT = '/media' @@ -173,4 +178,4 @@ CELERYBEAT_SCHEDULE = { 'task': 'dashboard.tasks.database_cleanup', 'schedule': timedelta(hours=24) }, -} \ No newline at end of file +} -- cgit 1.2.3-korg