add config model
This commit is contained in:
parent
9b52184910
commit
a187ad8ee8
@ -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)
|
||||||
|
@ -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"
|
||||||
|
57
ffplayout/api/serializers.py
Normal file
57
ffplayout/api/serializers.py
Normal 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
|
@ -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
|
||||||
|
@ -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.
@ -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 = (
|
||||||
|
@ -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')),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user