Added processingnode API, UI improvements

pull/34/head
Piero Toffanin 2016-10-18 16:23:10 -04:00
rodzic 6036e613f6
commit 75c83ff03b
8 zmienionych plików z 87 dodań i 7 usunięć

Wyświetl plik

@ -0,0 +1,24 @@
from rest_framework import serializers, viewsets
from rest_framework.response import Response
from rest_framework.decorators import permission_classes
from rest_framework.permissions import DjangoModelPermissions
from rest_framework.filters import DjangoFilterBackend
from nodeodm.models import ProcessingNode
class ProcessingNodeSerializer(serializers.ModelSerializer):
class Meta:
model = ProcessingNode
class ProcessingNodeViewSet(viewsets.ModelViewSet):
"""
Processing nodes available. Processing nodes are associated with
zero or more tasks and take care of processing input images.
"""
# Don't need a "view node" permission. If you are logged-in, you can view nodes.
permission_classes = (DjangoModelPermissions, )
filter_backends = (DjangoFilterBackend, )
pagination_class = None
serializer_class = ProcessingNodeSerializer
queryset = ProcessingNode.objects.all()

Wyświetl plik

@ -1,7 +1,6 @@
from django.contrib.auth.models import User
from rest_framework import serializers, viewsets, filters
from rest_framework import serializers, viewsets
from rest_framework.response import Response
from rest_framework.decorators import detail_route
from app import models
from .tasks import TaskIDsSerializer, TaskSerializer

Wyświetl plik

@ -1,10 +1,12 @@
from django.conf.urls import url, include
from .projects import ProjectViewSet
from .tasks import TaskViewSet
from .processingnodes import ProcessingNodeViewSet
from rest_framework_nested import routers
router = routers.DefaultRouter()
router.register(r'projects', ProjectViewSet)
router.register(r'processingnodes', ProcessingNodeViewSet)
tasks_router = routers.NestedSimpleRouter(router, r'projects', lookup='project')
tasks_router.register(r'tasks', TaskViewSet, base_name='projects-tasks')

Wyświetl plik

@ -35,7 +35,7 @@ class EditTaskPanel extends React.Component {
return (
<div className="edit-task-panel">
<form className="form-horizontal">
<p>Your images are being uploaded. In the meanwhile, set these additional options:</p>
<p>Your images are being uploaded. In the meanwhile, check these additional options:</p>
<div className="form-group">
<label className="col-sm-2 control-label">Name</label>
<div className="col-sm-10">

Wyświetl plik

@ -169,6 +169,8 @@ class ProjectListItem extends React.Component {
</div>
</div>
{this.state.showPanel ? <ProjectListItemPanel /> : ""}
{this.state.upload.uploading ? <UploadProgressBar {...this.state.upload}/> : ""}
{this.state.upload.error !== "" ?
@ -180,7 +182,6 @@ class ProjectListItem extends React.Component {
<EditTaskPanel className={!this.state.upload.showEditTask ? "hide" : ""} />
{this.state.showPanel ? <ProjectListItemPanel /> : ""}
</div>
</li>
);

Wyświetl plik

@ -257,7 +257,7 @@
</ul>
<!-- /.nav-second-level -->
</li>
{% if user.is_superuser %}
{% if user.is_staff %}
<li>
<a href="/admin/"><i class="fa fa-gears fa-fw"></i> {% trans 'Administration' %}</a>
</li>

Wyświetl plik

@ -3,6 +3,7 @@ from rest_framework.test import APIClient
from rest_framework import status
from app.models import Project, Task
from nodeodm.models import ProcessingNode
from django.contrib.auth.models import User
class TestApi(BootTestCase):
@ -98,4 +99,57 @@ class TestApi(BootTestCase):
# Cannot access task details for a task that doesn't exist
res = client.get('/api/projects/{}/tasks/999/'.format(project.id, other_task.id))
self.assertEqual(res.status_code, status.HTTP_404_NOT_FOUND)
self.assertEqual(res.status_code, status.HTTP_404_NOT_FOUND)
def test_processingnodes(self):
client = APIClient()
pnode = ProcessingNode.objects.create(
hostname="localhost",
port=999
)
# Cannot list processing nodes as guest
res = client.get('/api/processingnodes/')
self.assertEqual(res.status_code, status.HTTP_403_FORBIDDEN)
res = client.get('/api/processingnodes/{}/'.format(pnode.id))
self.assertEqual(res.status_code, status.HTTP_403_FORBIDDEN)
client.login(username="testuser", password="test1234")
# Can list processing nodes as normal user
res = client.get('/api/processingnodes/')
self.assertEqual(res.status_code, status.HTTP_200_OK)
self.assertTrue(len(res.data) == 1)
self.assertTrue(res.data[0]["hostname"] == "localhost")
# Can get single processing node as normal user
res = client.get('/api/processingnodes/{}/'.format(pnode.id))
self.assertEqual(res.status_code, status.HTTP_200_OK)
self.assertTrue(res.data["hostname"] == "localhost")
# Cannot delete a processing node as normal user
res = client.delete('/api/processingnodes/{}/'.format(pnode.id))
self.assertTrue(res.status_code, status.HTTP_403_FORBIDDEN)
# Cannot create a processing node as normal user
res = client.post('/api/processingnodes/', {'hostname': 'localhost', 'port':'1000'})
self.assertTrue(res.status_code, status.HTTP_403_FORBIDDEN)
client.login(username="testsuperuser", password="test1234")
# Can delete a processing node as super user
res = client.delete('/api/processingnodes/{}/'.format(pnode.id))
self.assertTrue(res.status_code, status.HTTP_200_OK)
# Can create a processing node as super user
res = client.post('/api/processingnodes/', {'hostname': 'localhost', 'port':'1000'})
self.assertTrue(res.status_code, status.HTTP_200_OK)
# Verify node has been created
res = client.get('/api/processingnodes/')
self.assertEqual(res.status_code, status.HTTP_200_OK)
self.assertTrue(len(res.data) == 1)
self.assertTrue(res.data[0]["port"] == 1000)

Wyświetl plik

@ -9,7 +9,7 @@ import json
class ProcessingNode(models.Model):
hostname = models.CharField(max_length=255, help_text="Hostname where the node is located (can be an internal hostname as well)")
port = models.PositiveIntegerField(help_text="Port that connects to the node's API")
api_version = models.CharField(max_length=32, help_text="API version used by the node")
api_version = models.CharField(max_length=32, null=True, help_text="API version used by the node")
last_refreshed = models.DateTimeField(null=True, help_text="When was the information about this node last retrieved?")
queue_count = models.PositiveIntegerField(default=0, help_text="Number of tasks currently being processed by this node (as reported by the node itself)")
available_options = fields.JSONField(default=dict(), help_text="Description of the options that can be used for processing")