mirror of
https://github.com/netbox-community/netbox.git
synced 2025-08-26 09:16:10 -06:00
Add API endpoint to sync data sources
This commit is contained in:
parent
15ca5e2326
commit
685e457d6f
@ -1,7 +1,14 @@
|
|||||||
|
from django.contrib.contenttypes.models import ContentType
|
||||||
|
from django.shortcuts import get_object_or_404
|
||||||
|
|
||||||
|
from rest_framework.decorators import action
|
||||||
|
from rest_framework.exceptions import PermissionDenied
|
||||||
|
from rest_framework.response import Response
|
||||||
from rest_framework.routers import APIRootView
|
from rest_framework.routers import APIRootView
|
||||||
|
|
||||||
from core import filtersets
|
from core import filtersets
|
||||||
from core.models import *
|
from core.models import *
|
||||||
|
from extras.models import JobResult
|
||||||
from netbox.api.viewsets import NetBoxModelViewSet
|
from netbox.api.viewsets import NetBoxModelViewSet
|
||||||
from utilities.utils import count_related
|
from utilities.utils import count_related
|
||||||
from . import serializers
|
from . import serializers
|
||||||
@ -26,6 +33,20 @@ class DataSourceViewSet(NetBoxModelViewSet):
|
|||||||
serializer_class = serializers.DataSourceSerializer
|
serializer_class = serializers.DataSourceSerializer
|
||||||
filterset_class = filtersets.DataSourceFilterSet
|
filterset_class = filtersets.DataSourceFilterSet
|
||||||
|
|
||||||
|
@action(detail=True, methods=['post'])
|
||||||
|
def sync(self, request, pk):
|
||||||
|
"""
|
||||||
|
Enqueue a job to synchronize the DataSource.
|
||||||
|
"""
|
||||||
|
if not request.user.has_perm('extras.sync_datasource'):
|
||||||
|
raise PermissionDenied("Syncing data sources requires the core.sync_datasource permission.")
|
||||||
|
|
||||||
|
datasource = get_object_or_404(DataSource, pk=pk)
|
||||||
|
datasource.enqueue_sync_job(request)
|
||||||
|
serializer = serializers.DataSourceSerializer(datasource, context={'request': request})
|
||||||
|
|
||||||
|
return Response(serializer.data)
|
||||||
|
|
||||||
|
|
||||||
class DataFileViewSet(NetBoxModelViewSet):
|
class DataFileViewSet(NetBoxModelViewSet):
|
||||||
queryset = DataFile.objects.defer('data').prefetch_related('source')
|
queryset = DataFile.objects.defer('data').prefetch_related('source')
|
||||||
|
@ -5,11 +5,14 @@ import tempfile
|
|||||||
from fnmatch import fnmatchcase
|
from fnmatch import fnmatchcase
|
||||||
from urllib.parse import quote, urlunparse, urlparse
|
from urllib.parse import quote, urlunparse, urlparse
|
||||||
|
|
||||||
|
from django.contrib.contenttypes.models import ContentType
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
from django.utils.module_loading import import_string
|
||||||
from django.utils.translation import gettext as _
|
from django.utils.translation import gettext as _
|
||||||
|
|
||||||
|
from extras.models import JobResult
|
||||||
from netbox.models import ChangeLoggedModel
|
from netbox.models import ChangeLoggedModel
|
||||||
from utilities.files import sha256_hash
|
from utilities.files import sha256_hash
|
||||||
from utilities.querysets import RestrictedQuerySet
|
from utilities.querysets import RestrictedQuerySet
|
||||||
@ -88,6 +91,30 @@ class DataSource(ChangeLoggedModel):
|
|||||||
def get_status_color(self):
|
def get_status_color(self):
|
||||||
return DataSourceStatusChoices.colors.get(self.status)
|
return DataSourceStatusChoices.colors.get(self.status)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def ready_for_sync(self):
|
||||||
|
return self.enabled and self.status not in (
|
||||||
|
DataSourceStatusChoices.QUEUED,
|
||||||
|
DataSourceStatusChoices.SYNCING
|
||||||
|
)
|
||||||
|
|
||||||
|
def enqueue_sync_job(self, request):
|
||||||
|
"""
|
||||||
|
Enqueue a background job to synchronize the DataSource by calling sync().
|
||||||
|
"""
|
||||||
|
# Set the status to "syncing"
|
||||||
|
self.status = DataSourceStatusChoices.QUEUED
|
||||||
|
|
||||||
|
# Enqueue a sync job
|
||||||
|
job_result = JobResult.enqueue_job(
|
||||||
|
import_string('core.jobs.sync_datasource'),
|
||||||
|
name=self.name,
|
||||||
|
obj_type=ContentType.objects.get_for_model(DataSource),
|
||||||
|
user=request.user,
|
||||||
|
)
|
||||||
|
|
||||||
|
return job_result
|
||||||
|
|
||||||
def sync(self):
|
def sync(self):
|
||||||
"""
|
"""
|
||||||
Create/update/delete child DataFiles as necessary to synchronize with the remote source.
|
Create/update/delete child DataFiles as necessary to synchronize with the remote source.
|
||||||
|
@ -44,18 +44,7 @@ class DataSourceSyncView(BaseObjectView):
|
|||||||
|
|
||||||
def post(self, request, pk):
|
def post(self, request, pk):
|
||||||
datasource = get_object_or_404(self.queryset, pk=pk)
|
datasource = get_object_or_404(self.queryset, pk=pk)
|
||||||
|
job_result = datasource.enqueue_sync_job(request)
|
||||||
# Set the status to "syncing"
|
|
||||||
datasource.status = DataSourceStatusChoices.QUEUED
|
|
||||||
datasource.save()
|
|
||||||
|
|
||||||
# Enqueue a sync job
|
|
||||||
job_result = JobResult.enqueue_job(
|
|
||||||
jobs.sync_datasource,
|
|
||||||
name=datasource.name,
|
|
||||||
obj_type=ContentType.objects.get_for_model(DataSource),
|
|
||||||
user=request.user,
|
|
||||||
)
|
|
||||||
|
|
||||||
messages.success(request, f"Queued job #{job_result.pk} to sync {datasource}")
|
messages.success(request, f"Queued job #{job_result.pk} to sync {datasource}")
|
||||||
return redirect(datasource.get_absolute_url())
|
return redirect(datasource.get_absolute_url())
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
{% block extra_controls %}
|
{% block extra_controls %}
|
||||||
{% if perms.core.sync_datasource %}
|
{% if perms.core.sync_datasource %}
|
||||||
{% if object.enabled %}
|
{% if object.ready_for_sync %}
|
||||||
<form action="{% url 'core:datasource_sync' pk=object.pk %}" method="post">
|
<form action="{% url 'core:datasource_sync' pk=object.pk %}" method="post">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<button type="submit" class="btn btn-sm btn-primary">
|
<button type="submit" class="btn btn-sm btn-primary">
|
||||||
|
Loading…
Reference in New Issue
Block a user