From 7130ac36057d44c42e3630b93d1368b1e640a1ea Mon Sep 17 00:00:00 2001 From: Tony Mack Date: Fri, 22 Mar 2013 21:58:00 -0400 Subject: [PATCH] Initial commit --- plstackapi/core/__init__.py | 0 plstackapi/core/admin.py | 13 ++ plstackapi/core/fixtures/initial_data.json | 1 + plstackapi/core/models.py | 65 +++++++++ plstackapi/core/serializers.py | 93 ++++++++++++ plstackapi/core/tests.py | 16 +++ plstackapi/core/views.py | 66 +++++++++ plstackapi/manage.py | 10 ++ plstackapi/planetstack/__init__.py | 0 plstackapi/planetstack/settings.py | 160 +++++++++++++++++++++ plstackapi/planetstack/urls.py | 46 ++++++ plstackapi/planetstack/wsgi.py | 32 +++++ 12 files changed, 502 insertions(+) create mode 100644 plstackapi/core/__init__.py create mode 100644 plstackapi/core/admin.py create mode 100644 plstackapi/core/fixtures/initial_data.json create mode 100644 plstackapi/core/models.py create mode 100644 plstackapi/core/serializers.py create mode 100644 plstackapi/core/tests.py create mode 100644 plstackapi/core/views.py create mode 100644 plstackapi/manage.py create mode 100644 plstackapi/planetstack/__init__.py create mode 100644 plstackapi/planetstack/settings.py create mode 100644 plstackapi/planetstack/urls.py create mode 100644 plstackapi/planetstack/wsgi.py diff --git a/plstackapi/core/__init__.py b/plstackapi/core/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/plstackapi/core/admin.py b/plstackapi/core/admin.py new file mode 100644 index 0000000..fd51666 --- /dev/null +++ b/plstackapi/core/admin.py @@ -0,0 +1,13 @@ +from core.models import * +from django.contrib import admin + +from django.contrib.auth.admin import UserAdmin +from django.contrib.auth.models import User + +admin.site.register(Site) +admin.site.register(Slice) +admin.site.register(Node) +admin.site.register(DeploymentNetwork) +admin.site.register(SiteDeploymentNetwork) +admin.site.register(Sliver) + diff --git a/plstackapi/core/fixtures/initial_data.json b/plstackapi/core/fixtures/initial_data.json new file mode 100644 index 0000000..5188d63 --- /dev/null +++ b/plstackapi/core/fixtures/initial_data.json @@ -0,0 +1 @@ +[{"pk": 1, "model": "core.deploymentnetwork", "fields": {"updated": "2013-03-20T01:18:31.247Z", "name": "VICCI", "created": "2013-03-20T01:18:31.247Z"}}, {"pk": 2, "model": "core.deploymentnetwork", "fields": {"updated": "2013-03-20T01:19:00.063Z", "name": "VINI", "created": "2013-03-20T01:19:00.063Z"}}, {"pk": 3, "model": "core.deploymentnetwork", "fields": {"updated": "2013-03-20T01:19:15.143Z", "name": "GENI", "created": "2013-03-20T01:19:15.143Z"}}, {"pk": 4, "model": "core.deploymentnetwork", "fields": {"updated": "2013-03-20T01:19:40.098Z", "name": "PlanetLab Classic", "created": "2013-03-20T01:19:25.672Z"}}] \ No newline at end of file diff --git a/plstackapi/core/models.py b/plstackapi/core/models.py new file mode 100644 index 0000000..4ea2a25 --- /dev/null +++ b/plstackapi/core/models.py @@ -0,0 +1,65 @@ +from django.db import models + +# Create your models here. + +class PlCoreBase(models.Model): + + created = models.DateTimeField(auto_now_add=True) + updated = models.DateTimeField(auto_now=True) + + class Meta: + abstract = True + +class Site(PlCoreBase): + name = models.CharField(max_length=200, unique=True, help_text="Name for this Site") + site_url = models.URLField(help_text="Site's Home URL Page") + enabled = models.BooleanField(default=True, help_text="Status for this Site") + longitude = models.FloatField(null=True, blank=True) + latitude = models.FloatField(null=True, blank=True) + login_base = models.CharField(max_length=50, help_text="Prefix for Slices associated with this Site") + is_public = models.BooleanField(default=True, help_text="Indicates the visibility of this site to other members") + abbreviated_name = models.CharField(max_length=80) + + def __unicode__(self): return u'%s' % (self.name) + +class Slice(PlCoreBase): + name = models.CharField(help_text="The Name of the Slice", max_length=80) + SLICE_CHOICES = (('plc', 'PLC'), ('delegated', 'Delegated'), ('controller','Controller'), ('none','None')) + instantiation = models.CharField(help_text="The instantiation type of the slice", max_length=80, choices=SLICE_CHOICES) + omf_friendly = models.BooleanField() + description=models.TextField(blank=True,help_text="High level description of the slice and expected activities", max_length=1024) + slice_url = models.URLField(blank=True) + site = models.ForeignKey(Site, related_name='slices', help_text="The Site this Node belongs too") + + def __unicode__(self): return u'%s' % (self.name) + +class DeploymentNetwork(PlCoreBase): + name = models.CharField(max_length=200, unique=True, help_text="Name of the Deployment Network") + + def __unicode__(self): return u'%s' % (self.name) + +class SiteDeploymentNetwork(PlCoreBase): + class Meta: + unique_together = ['site', 'deploymentNetwork'] + + site = models.ForeignKey(Site, related_name='deploymentNetworks') + deploymentNetwork = models.ForeignKey(DeploymentNetwork, related_name='sites') + name = models.CharField(default="Blah", max_length=100) + + + def __unicode__(self): return u'%s::%s' % (self.site, self.deploymentNetwork) + + +class Sliver(PlCoreBase): + name = models.CharField(max_length=200, unique=True) + slice = models.ForeignKey(Slice) + siteDeploymentNetwork = models.ForeignKey(SiteDeploymentNetwork) + + def __unicode__(self): return u'%s::%s' % (self.slice, self.siteDeploymentNetwork) + +class Node(PlCoreBase): + name = models.CharField(max_length=200, unique=True, help_text="Name of the Node") + siteDeploymentNetwork = models.ForeignKey(SiteDeploymentNetwork, help_text="The Site and Deployment Network this Node belongs too.") + + def __unicode__(self): return u'%s' % (self.name) + diff --git a/plstackapi/core/serializers.py b/plstackapi/core/serializers.py new file mode 100644 index 0000000..62ac271 --- /dev/null +++ b/plstackapi/core/serializers.py @@ -0,0 +1,93 @@ +from django.forms import widgets +from rest_framework import serializers +from models import * + + +class SliceSerializer(serializers.HyperlinkedModelSerializer): + + site = serializers.HyperlinkedRelatedField(view_name='site-detail') + + class Meta: + model = Slice + fields = ('url', + 'name', + 'instantiation', + 'omf_friendly', + 'description', + 'slice_url', + 'site', + 'updated', + 'created') + +class SiteSerializer(serializers.HyperlinkedModelSerializer): + + #Experimenting with whether to use ids, hyperlinks, or nested includes + #slices = serializers.PrimaryKeyRelatedField(many=True, read_only=True) + #slices = serializers.RelatedField(many=True, read_only=True) + #slices = SliceSerializer(many=True) + slices = serializers.HyperlinkedRelatedField(many=True, read_only=True,view_name='slice-detail') + deploymentNetworks = serializers.HyperlinkedRelatedField(many=True, read_only=True,view_name='sitedeploymentnetwork-detail') + + class Meta: + model = Site + fields = ('url', + 'name', + 'deploymentNetworks', + 'slices', + 'site_url', + 'enabled', + 'longitude', + 'latitude', + 'login_base', + 'is_public', + 'abbreviated_name', + 'updated', + 'created') + +class DeploymentNetworkSerializer(serializers.HyperlinkedModelSerializer): + + sites = serializers.HyperlinkedRelatedField(view_name='sitedeploymentnetwork-detail') + class Meta: + model = DeploymentNetwork + fields = ('url', + 'name', + 'sites' + ) + +class SiteDeploymentNetworkSerializer(serializers.HyperlinkedModelSerializer): + + site = serializers.HyperlinkedRelatedField(view_name='site-detail') + deploymentNetwork = serializers.HyperlinkedRelatedField(view_name='deploymentnetwork-detail') + + class Meta: + model = SiteDeploymentNetwork + fields = ('url', + 'site', + 'deploymentNetwork') + +class SliverSerializer(serializers.ModelSerializer): + slice = serializers.RelatedField(read_only=True) + #slice = serializers.PrimaryKeyRelatedField(read_only=True) + + class Meta: + model = Sliver + fields = ('id', + 'slice', + 'name') + +class NodeSerializer(serializers.ModelSerializer): + + class Meta: + model = Node + fields = ('id', + 'name') + + +serializerLookUp = { Site: SiteSerializer, + Slice: SliceSerializer, + Node: NodeSerializer, + Sliver: SliverSerializer, + DeploymentNetwork: DeploymentNetworkSerializer, + SiteDeploymentNetwork: SiteDeploymentNetworkSerializer, + None: None, + } diff --git a/plstackapi/core/tests.py b/plstackapi/core/tests.py new file mode 100644 index 0000000..501deb7 --- /dev/null +++ b/plstackapi/core/tests.py @@ -0,0 +1,16 @@ +""" +This file demonstrates writing tests using the unittest module. These will pass +when you run "manage.py test". + +Replace this with more appropriate tests for your application. +""" + +from django.test import TestCase + + +class SimpleTest(TestCase): + def test_basic_addition(self): + """ + Tests that 1 + 1 always equals 2. + """ + self.assertEqual(1 + 1, 2) diff --git a/plstackapi/core/views.py b/plstackapi/core/views.py new file mode 100644 index 0000000..ebbd907 --- /dev/null +++ b/plstackapi/core/views.py @@ -0,0 +1,66 @@ +# Create your views here. + +from models import Site +from serializers import * +from rest_framework import generics +from rest_framework.decorators import api_view +from rest_framework.response import Response +from rest_framework.reverse import reverse +from rest_framework import renderers + +@api_view(['GET']) +def api_root(request, format=None): + return Response({ + 'nodes': reverse('node-list', request=request, format=format), + 'sites': reverse('site-list', request=request, format=format), + 'deploymentNetworks': reverse('deploymentnetwork-list', request=request, format=format), + 'slices': reverse('slice-list', request=request, format=format) + }) + +class SiteList(generics.ListCreateAPIView): + model=Site + serializer_class = SiteSerializer + +class SiteDetail(generics.RetrieveUpdateDestroyAPIView): + model = Site + serializer_class = SiteSerializer + +class SliceList(generics.ListCreateAPIView): + model=Slice + serializer_class = SliceSerializer + +class SliceDetail(generics.RetrieveUpdateDestroyAPIView): + model = Slice + serializer_class = SliceSerializer + +class NodeList(generics.ListCreateAPIView): + model=Node + serializer_class = NodeSerializer + +class NodeDetail(generics.RetrieveUpdateDestroyAPIView): + model = Node + serializer_class = NodeSerializer + +class SliverList(generics.ListCreateAPIView): + model=Sliver + serializer_class = SliverSerializer + +class SliverDetail(generics.RetrieveUpdateDestroyAPIView): + model = Sliver + serializer_class = SliverSerializer + +class DeploymentNetworkList(generics.ListCreateAPIView): + model=DeploymentNetwork + serializer_class = DeploymentNetworkSerializer + +class DeploymentNetworkDetail(generics.RetrieveUpdateDestroyAPIView): + model = DeploymentNetwork + serializer_class = DeploymentNetworkSerializer + +class SiteDeploymentNetworkList(generics.ListCreateAPIView): + model=SiteDeploymentNetwork + serializer_class = SiteDeploymentNetworkSerializer + +class SiteDeploymentNetworkDetail(generics.RetrieveUpdateDestroyAPIView): + model = SiteDeploymentNetwork + serializer_class = DeploymentNetworkSerializer diff --git a/plstackapi/manage.py b/plstackapi/manage.py new file mode 100644 index 0000000..c12bf36 --- /dev/null +++ b/plstackapi/manage.py @@ -0,0 +1,10 @@ +#!/usr/bin/env python +import os +import sys + +if __name__ == "__main__": + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "planetstack.settings") + + from django.core.management import execute_from_command_line + + execute_from_command_line(sys.argv) diff --git a/plstackapi/planetstack/__init__.py b/plstackapi/planetstack/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/plstackapi/planetstack/settings.py b/plstackapi/planetstack/settings.py new file mode 100644 index 0000000..0cbd656 --- /dev/null +++ b/plstackapi/planetstack/settings.py @@ -0,0 +1,160 @@ +# Django settings for planetstack project. + +DEBUG = True +TEMPLATE_DEBUG = DEBUG + +ADMINS = ( + # ('Your Name', 'your_email@example.com'), +) + +MANAGERS = ADMINS + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.postgresql_psycopg2', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'. + 'NAME': 'planetstack', # Or path to database file if using sqlite3. + # The following settings are not used with sqlite3: + 'USER': 'postgres', + 'PASSWORD': 'password', + 'HOST': 'localhost', # Empty for localhost through domain sockets or '127.0.0.1' for localhost through TCP. + 'PORT': '', # Set to empty string for default. + } +} + +# Hosts/domain names that are valid for this site; required if DEBUG is False +# See https://docs.djangoproject.com/en/1.5/ref/settings/#allowed-hosts +ALLOWED_HOSTS = [] + +# Local time zone for this installation. Choices can be found here: +# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name +# although not all choices may be available on all operating systems. +# In a Windows environment this must be set to your system time zone. +TIME_ZONE = 'America/New_York' + +# Language code for this installation. All choices can be found here: +# http://www.i18nguy.com/unicode/language-identifiers.html +LANGUAGE_CODE = 'en-us' + +SITE_ID = 1 + +# If you set this to False, Django will make some optimizations so as not +# to load the internationalization machinery. +USE_I18N = True + +# If you set this to False, Django will not format dates, numbers and +# calendars according to the current locale. +USE_L10N = True + +# If you set this to False, Django will not use timezone-aware datetimes. +USE_TZ = True + +# Absolute filesystem path to the directory that will hold user-uploaded files. +# Example: "/var/www/example.com/media/" +MEDIA_ROOT = '' + +# URL that handles the media served from MEDIA_ROOT. Make sure to use a +# trailing slash. +# Examples: "http://example.com/media/", "http://media.example.com/" +MEDIA_URL = '' + +# Absolute path to the directory static files should be collected to. +# Don't put anything in this directory yourself; store your static files +# in apps' "static/" subdirectories and in STATICFILES_DIRS. +# Example: "/var/www/example.com/static/" +STATIC_ROOT = '' + +# URL prefix for static files. +# Example: "http://example.com/static/", "http://static.example.com/" +STATIC_URL = '/static/' + +# Additional locations of static files +STATICFILES_DIRS = ( + # Put strings here, like "/home/html/static" or "C:/www/django/static". + # Always use forward slashes, even on Windows. + # Don't forget to use absolute paths, not relative paths. +) + +# List of finder classes that know how to find static files in +# various locations. +STATICFILES_FINDERS = ( + 'django.contrib.staticfiles.finders.FileSystemFinder', + 'django.contrib.staticfiles.finders.AppDirectoriesFinder', +# 'django.contrib.staticfiles.finders.DefaultStorageFinder', +) + +# Make this unique, and don't share it with anybody. +SECRET_KEY = 'i0=a)c7_#2)5m%k_fu#%53xap$tlqc+#&z5as+bl7&)(@be_f9' + +# List of callables that know how to import templates from various sources. +TEMPLATE_LOADERS = ( + 'django.template.loaders.filesystem.Loader', + 'django.template.loaders.app_directories.Loader', +# 'django.template.loaders.eggs.Loader', +) + +MIDDLEWARE_CLASSES = ( + 'django.middleware.common.CommonMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + # Uncomment the next line for simple clickjacking protection: + # 'django.middleware.clickjacking.XFrameOptionsMiddleware', +) + +ROOT_URLCONF = 'planetstack.urls' + +# Python dotted path to the WSGI application used by Django's runserver. +WSGI_APPLICATION = 'planetstack.wsgi.application' + +TEMPLATE_DIRS = ( + # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates". + # Always use forward slashes, even on Windows. + # Don't forget to use absolute paths, not relative paths. +) + +INSTALLED_APPS = ( + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', +# 'django.contrib.sites', + 'django.contrib.messages', + 'django.contrib.staticfiles', + # Uncomment the next line to enable the admin: + 'django.contrib.admin', + # Uncomment the next line to enable admin documentation: + 'django.contrib.admindocs', + 'rest_framework', + 'django_extensions', + 'core', + 'django_evolution', +) + +# A sample logging configuration. The only tangible logging +# performed by this configuration is to send an email to +# the site admins on every HTTP 500 error when DEBUG=False. +# See http://docs.djangoproject.com/en/dev/topics/logging for +# more details on how to customize your logging configuration. +LOGGING = { + 'version': 1, + 'disable_existing_loggers': False, + 'filters': { + 'require_debug_false': { + '()': 'django.utils.log.RequireDebugFalse' + } + }, + 'handlers': { + 'mail_admins': { + 'level': 'ERROR', + 'filters': ['require_debug_false'], + 'class': 'django.utils.log.AdminEmailHandler' + } + }, + 'loggers': { + 'django.request': { + 'handlers': ['mail_admins'], + 'level': 'ERROR', + 'propagate': True, + }, + } +} diff --git a/plstackapi/planetstack/urls.py b/plstackapi/planetstack/urls.py new file mode 100644 index 0000000..a4cf203 --- /dev/null +++ b/plstackapi/planetstack/urls.py @@ -0,0 +1,46 @@ +from django.conf.urls import patterns, include, url + +# Uncomment the next two lines to enable the admin: +from django.contrib import admin +from core import views +from core.views import api_root +from core.models import Site +from rest_framework import generics + +admin.autodiscover() + +urlpatterns = patterns('', + # Examples: + # url(r'^$', 'planetstack.views.home', name='home'), + # url(r'^planetstack/', include('planetstack.foo.urls')), + + # Uncomment the admin/doc line below to enable admin documentation: + # url(r'^admin/doc/', include('django.contrib.admindocs.urls')), + + # Uncomment the next line to enable the admin: + url(r'^admin/', include(admin.site.urls)), + + url(r'^plstackapi/$', api_root), + url(r'^plstackapi/sites/$', views.SiteList.as_view(), name='site-list'), + url(r'^plstackapi/sites/(?P[0-9]+)/$', views.SiteDetail.as_view(), name='site-detail'), + + url(r'^plstackapi/slices/$', views.SliceList.as_view(), name='slice-list'), + url(r'^plstackapi/slices/(?P[0-9]+)/$', views.SliceDetail.as_view(), name='slice-detail'), + + url(r'^plstackapi/slivers/$', views.SliverList.as_view()), + url(r'^plstackapi/slivers/(?P[0-9]+)/$', views.SliverDetail.as_view()), + + url(r'^plstackapi/nodes/$', views.NodeList.as_view(), name='node-list'), + url(r'^plstackapi/nodes/(?P[0-9]+)/$', views.NodeDetail.as_view(), name='node-detail'), + + url(r'^plstackapi/deploymentnetworks/$', views.DeploymentNetworkList.as_view(), name='deploymentnetwork-list'), + url(r'^plstackapi/deploymentnetworks/(?P[0-9]+)/$', views.DeploymentNetworkDetail.as_view(), name='deploymentnetwork-detail'), + + url(r'^plstackapi/sitedeploymentnetworks/$', views.SiteDeploymentNetworkList.as_view(), name='sitedeploymentnetwork-list'), + url(r'^plstackapi/sitedeploymentnetworks/(?P[0-9]+)/$', views.SiteDeploymentNetworkDetail.as_view(), name='sitedeploymentnetwork-detail'), + + + #Adding in rest_framework urls + url(r'^plstackapi/', include('rest_framework.urls', namespace='rest_framework')), + +) diff --git a/plstackapi/planetstack/wsgi.py b/plstackapi/planetstack/wsgi.py new file mode 100644 index 0000000..6e03e11 --- /dev/null +++ b/plstackapi/planetstack/wsgi.py @@ -0,0 +1,32 @@ +""" +WSGI config for planetstack project. + +This module contains the WSGI application used by Django's development server +and any production WSGI deployments. It should expose a module-level variable +named ``application``. Django's ``runserver`` and ``runfcgi`` commands discover +this application via the ``WSGI_APPLICATION`` setting. + +Usually you will have the standard Django WSGI application here, but it also +might make sense to replace the whole Django WSGI application with a custom one +that later delegates to the Django one. For example, you could introduce WSGI +middleware here, or combine a Django application with an application of another +framework. + +""" +import os + +# We defer to a DJANGO_SETTINGS_MODULE already in the environment. This breaks +# if running multiple sites in the same mod_wsgi process. To fix this, use +# mod_wsgi daemon mode with each site in its own daemon process, or use +# os.environ["DJANGO_SETTINGS_MODULE"] = "planetstack.settings" +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "planetstack.settings") + +# This application object is used by any WSGI server configured to use this +# file. This includes Django's development server, if the WSGI_APPLICATION +# setting points here. +from django.core.wsgi import get_wsgi_application +application = get_wsgi_application() + +# Apply WSGI middleware here. +# from helloworld.wsgi import HelloWorldApplication +# application = HelloWorldApplication(application) -- 2.47.0