add config model

This commit is contained in:
Jonathan Baecker 2020-04-15 18:10:16 +02:00
parent 9b52184910
commit a187ad8ee8
8 changed files with 160 additions and 21 deletions

View File

@ -1,3 +1,13 @@
from django.contrib import admin from django.contrib import admin
# Register your models here. from api.models import GuiSettings
class GuiSettingsAdmin(admin.ModelAdmin):
class Meta:
model = GuiSettings
fields = '__all__'
admin.site.register(GuiSettings, GuiSettingsAdmin)

View File

@ -1,3 +1,34 @@
import psutil
from django.db import models from django.db import models
# Create your models here.
class GuiSettings(models.Model):
"""
Here we manage the settings for the web GUI:
- Player URL
- settings for the statistics
"""
addrs = psutil.net_if_addrs()
addrs = [(i, i) for i in addrs.keys()]
player_url = models.CharField(max_length=255)
playout_config = models.CharField(max_length=255)
net_interface = models.CharField(
max_length=20,
choices=addrs,
default=None,
)
media_disk = models.CharField(max_length=255)
def save(self, *args, **kwargs):
if self.pk is not None:
super(GuiSettings, self).save(*args, **kwargs)
def delete(self, *args, **kwargs):
if not self.related_query.all():
super(GuiSettings, self).delete(*args, **kwargs)
class Meta:
verbose_name_plural = "guisettings"

View File

@ -0,0 +1,57 @@
from django.contrib.auth.models import User
from rest_framework import serializers
from api.models import GuiSettings
class UserSerializer(serializers.ModelSerializer):
confirm_password = serializers.CharField(write_only=False, required=False)
new_password = serializers.CharField(write_only=True, required=False)
old_password = serializers.CharField(write_only=True, required=False)
class Meta:
model = User
fields = ['username', 'old_password',
'new_password', 'confirm_password', 'email']
def update(self, instance, validated_data):
instance.password = validated_data.get('password', instance.password)
if not validated_data['new_password']:
raise serializers.ValidationError({'new_password': 'not found'})
if not validated_data['old_password']:
raise serializers.ValidationError({'old_password': 'not found'})
if not instance.check_password(validated_data['old_password']):
raise serializers.ValidationError(
{'old_password': 'wrong password'})
if validated_data['new_password'] != \
validated_data['confirm_password']:
raise serializers.ValidationError(
{'passwords': 'passwords do not match'})
if validated_data['new_password'] == \
validated_data['confirm_password'] and \
instance.check_password(validated_data['old_password']):
# instance.password = validated_data['new_password']
instance.set_password(validated_data['new_password'])
instance.save()
return instance
return instance
class GuiSettingsSerializer(serializers.ModelSerializer):
class Meta:
model = GuiSettings
fields = '__all__'
def get_fields(self, *args, **kwargs):
fields = super().get_fields(*args, **kwargs)
request = self.context.get('request')
if request is not None and not request.parser_context.get('kwargs'):
fields.pop('id', None)
return fields

View File

@ -7,19 +7,24 @@ import psutil
import yaml import yaml
from pymediainfo import MediaInfo from pymediainfo import MediaInfo
from django.conf import settings from api.models import GuiSettings
from natsort import natsorted from natsort import natsorted
def read_yaml(): def read_yaml():
if os.path.isfile(settings.FFPLAYOUT_CONFIG): config = GuiSettings.objects.filter(id=1).values()[0]
with open(settings.FFPLAYOUT_CONFIG, 'r') as config_file:
if os.path.isfile(config['playout_config']):
with open(config['playout_config'], 'r') as config_file:
return yaml.safe_load(config_file) return yaml.safe_load(config_file)
def write_yaml(data): def write_yaml(data):
if os.path.isfile(settings.FFPLAYOUT_CONFIG): config = GuiSettings.objects.filter(id=1).values()[0]
with open(settings.FFPLAYOUT_CONFIG, 'w') as outfile:
if os.path.isfile(config['playout_config']):
with open(config['playoutConfig'], 'w') as outfile:
yaml.dump(data, outfile, default_flow_style=False, yaml.dump(data, outfile, default_flow_style=False,
sort_keys=False, indent=4) sort_keys=False, indent=4)
@ -43,7 +48,7 @@ def sizeof_fmt(num, suffix='B'):
class SystemStats: class SystemStats:
def __init__(self): def __init__(self):
pass self.config = GuiSettings.objects.filter(id=1).values()[0]
def all(self): def all(self):
return { return {
@ -83,7 +88,7 @@ class SystemStats:
} }
def disk(self): def disk(self):
root = psutil.disk_usage(settings.MEDIA_DISK) root = psutil.disk_usage(self.config['media_disk'])
return { return {
'disk_total': [root.total, sizeof_fmt(root.total)], 'disk_total': [root.total, sizeof_fmt(root.total)],
'disk_used': [root.used, sizeof_fmt(root.used)], 'disk_used': [root.used, sizeof_fmt(root.used)],
@ -102,20 +107,20 @@ class SystemStats:
def net_speed(self): def net_speed(self):
net = psutil.net_if_stats() net = psutil.net_if_stats()
if settings.NET_INTERFACE not in net: if self.config['net_interface'] not in net:
return { return {
'net_speed_send': 'no network interface set!', 'net_speed_send': 'no network interface set!',
'net_speed_recv': 'no network interface set!' 'net_speed_recv': 'no network interface set!'
} }
net = psutil.net_io_counters(pernic=True)[settings.NET_INTERFACE] net = psutil.net_io_counters(pernic=True)[self.config['net_interface']]
send_start = net.bytes_sent send_start = net.bytes_sent
recv_start = net.bytes_recv recv_start = net.bytes_recv
sleep(1) sleep(1)
net = psutil.net_io_counters(pernic=True)[settings.NET_INTERFACE] net = psutil.net_io_counters(pernic=True)[self.config['net_interface']]
send_end = net.bytes_sent send_end = net.bytes_sent
recv_end = net.bytes_recv recv_end = net.bytes_recv
@ -160,7 +165,8 @@ def get_media_path(dir=None):
for track in media_info.tracks: for track in media_info.tracks:
if track.track_type == 'General': if track.track_type == 'General':
try: try:
duration = float(track.to_data()["duration"]) / 1000 duration = float(
track.to_data()["duration"]) / 1000
break break
except KeyError: except KeyError:
pass pass

View File

@ -1,14 +1,48 @@
import os import os
from urllib.parse import unquote from urllib.parse import unquote
from django.contrib.auth.models import User
from django_filters import rest_framework as filters
from rest_framework import viewsets
from rest_framework.parsers import FileUploadParser, JSONParser from rest_framework.parsers import FileUploadParser, JSONParser
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework.views import APIView from rest_framework.views import APIView
from api.models import GuiSettings
from api.serializers import GuiSettingsSerializer, UserSerializer
from .utils import (SystemStats, get_media_path, read_json, read_yaml, from .utils import (SystemStats, get_media_path, read_json, read_yaml,
write_yaml) write_yaml)
class CurrentUserView(APIView):
def get(self, request):
serializer = UserSerializer(request.user)
return Response(serializer.data)
class UserFilter(filters.FilterSet):
class Meta:
model = User
fields = ['username']
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
filter_backends = (filters.DjangoFilterBackend,)
filterset_class = UserFilter
class GuiSettingsViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows media to be viewed.
"""
queryset = GuiSettings.objects.all()
serializer_class = GuiSettingsSerializer
class Config(APIView): class Config(APIView):
""" """
read and write config from ffplayout engine read and write config from ffplayout engine
@ -17,7 +51,7 @@ class Config(APIView):
parser_classes = [JSONParser] parser_classes = [JSONParser]
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
if 'config' in request.GET.dict(): if 'configPlayout' in request.GET.dict():
yaml_input = read_yaml() yaml_input = read_yaml()
if yaml_input: if yaml_input:
@ -72,10 +106,11 @@ class Statistics(APIView):
""" """
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
stats = SystemStats()
if 'stats' in request.GET.dict() and request.GET.dict()['stats'] \ if 'stats' in request.GET.dict() and request.GET.dict()['stats'] \
and hasattr(SystemStats(), request.GET.dict()['stats']): and hasattr(stats, request.GET.dict()['stats']):
return Response( return Response(
getattr(SystemStats(), request.GET.dict()['stats'])()) getattr(stats, request.GET.dict()['stats'])())
else: else:
return Response({"success": False}) return Response({"success": False})

Binary file not shown.

View File

@ -38,6 +38,7 @@ INSTALLED_APPS = [
'django.contrib.sessions', 'django.contrib.sessions',
'django.contrib.messages', 'django.contrib.messages',
'django.contrib.staticfiles', 'django.contrib.staticfiles',
'django_filters',
'rest_framework', 'rest_framework',
'corsheaders', 'corsheaders',
'api' 'api'
@ -112,11 +113,7 @@ REST_FRAMEWORK = {
], ],
'DEFAULT_PERMISSION_CLASSES': ( 'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated', 'rest_framework.permissions.IsAuthenticated',
), )
'DEFAULT_PAGINATION_CLASS': (
'rest_framework.pagination.LimitOffsetPagination',
),
'PAGE_SIZE': 50
} }
CORS_ORIGIN_WHITELIST = ( CORS_ORIGIN_WHITELIST = (

View File

@ -25,6 +25,8 @@ from rest_framework_simplejwt.views import (
) )
router = routers.DefaultRouter() router = routers.DefaultRouter()
router.register(r'users', views.UserViewSet)
router.register(r'guisettings', views.GuiSettingsViewSet, 'guisettings')
urlpatterns = [ urlpatterns = [
path('admin/', admin.site.urls), path('admin/', admin.site.urls),
@ -32,6 +34,7 @@ urlpatterns = [
path('api/config/', views.Config.as_view()), path('api/config/', views.Config.as_view()),
path('api/playlist/', views.Playlist.as_view()), path('api/playlist/', views.Playlist.as_view()),
path('api/stats/', views.Statistics.as_view()), path('api/stats/', views.Statistics.as_view()),
path('api/current/user/', views.CurrentUserView.as_view()),
path('api/media/', views.Media.as_view()), path('api/media/', views.Media.as_view()),
path('api-auth/', include( path('api-auth/', include(
'rest_framework.urls', namespace='rest_framework')), 'rest_framework.urls', namespace='rest_framework')),