Add library for dashboard API 23/26723/1
authormaxbr <maxbr@mi.fu-berlin.de>
Thu, 5 Jan 2017 11:34:37 +0000 (12:34 +0100)
committermaxbr <maxbr@mi.fu-berlin.de>
Thu, 5 Jan 2017 11:34:37 +0000 (12:34 +0100)
JIRA: PHAROS-265

The DashboardAPI class can be used to query and update dashboard data.

Change-Id: I584a3cc500ff1d67011c18af4e73e504126310a2
Signed-off-by: maxbr <maxbr@mi.fu-berlin.de>
tools/pharos-dashboard/dashboard_api/__init__.py [new file with mode: 0644]
tools/pharos-dashboard/dashboard_api/api.py [new file with mode: 0644]
tools/pharos-dashboard/src/api/migrations/__init__.py [new file with mode: 0644]
tools/pharos-dashboard/src/api/serializers.py
tools/pharos-dashboard/src/api/urls.py
tools/pharos-dashboard/src/api/views.py
tools/pharos-dashboard/src/pharos_dashboard/settings.py

diff --git a/tools/pharos-dashboard/dashboard_api/__init__.py b/tools/pharos-dashboard/dashboard_api/__init__.py
new file mode 100644 (file)
index 0000000..ce1acf3
--- /dev/null
@@ -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/tools/pharos-dashboard/dashboard_api/api.py b/tools/pharos-dashboard/dashboard_api/api.py
new file mode 100644 (file)
index 0000000..d40e0aa
--- /dev/null
@@ -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/tools/pharos-dashboard/src/api/migrations/__init__.py b/tools/pharos-dashboard/src/api/migrations/__init__.py
new file mode 100644 (file)
index 0000000..b5914ce
--- /dev/null
@@ -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
+##############################################################################
+
+
index 78e6020..f8f02a2 100644 (file)
 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
index dfbe1ac..a4a4b2f 100644 (file)
@@ -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)),
index 2595e5e..84fa1b5 100644 (file)
@@ -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')
index 2c4e8cc..084f878 100644 (file)
@@ -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
+}