Adjusted modeling of Service, Slice and Tags. Added RequestRouter starter App. ...
authorSiobhan Tully <stully@verivue.com>
Wed, 9 Oct 2013 01:52:35 +0000 (21:52 -0400)
committerSiobhan Tully <stully@verivue.com>
Wed, 9 Oct 2013 01:52:35 +0000 (21:52 -0400)
14 files changed:
planetstack/core/admin.py
planetstack/core/fixtures/initial_data.json
planetstack/core/models/__init__.py
planetstack/core/models/network.py
planetstack/core/models/plcorebase.py
planetstack/core/models/plservice.py [new file with mode: 0644]
planetstack/core/models/singletonmodel.py [new file with mode: 0644]
planetstack/core/models/slice.py
planetstack/core/models/tag.py
planetstack/core/static/planetstack.css
planetstack/planetstack/settings.py
planetstack/requestrouter/__init__.py [new file with mode: 0644]
planetstack/requestrouter/admin.py [new file with mode: 0644]
planetstack/requestrouter/models.py [new file with mode: 0644]

index bae7be1..dd89024 100644 (file)
@@ -16,6 +16,15 @@ from suit.widgets import LinkedSelect
 
 import django_evolution 
 
 
 import django_evolution 
 
+class SingletonAdmin (admin.ModelAdmin):
+    def has_add_permission(self, request):
+        num_objects = self.model.objects.count()
+        if num_objects >= 1:
+            return False
+        else:
+            return True
+
+
 class PlStackTabularInline(admin.TabularInline):
     pass
 
 class PlStackTabularInline(admin.TabularInline):
     pass
 
@@ -119,7 +128,7 @@ class UserInline(PlStackTabularInline):
 
 class SliceInline(PlStackTabularInline):
     model = Slice
 
 class SliceInline(PlStackTabularInline):
     model = Slice
-    fields = ['name','enabled','description','slice_url']
+    fields = ['name','site', 'serviceClass', 'service']
     extra = 0
     suit_classes = 'suit-tab suit-tab-slices'
 
     extra = 0
     suit_classes = 'suit-tab suit-tab-slices'
 
@@ -254,6 +263,22 @@ class DeploymentAdmin(PlanetStackBaseAdmin):
         (None, {'fields': ['sites'], 'classes':['suit-tab suit-tab-sites']}),]
     suit_form_tabs =(('sites', 'Sites'),('nodes','Nodes'),('deploymentprivileges','Privileges'),('tags','Tags'))
 
         (None, {'fields': ['sites'], 'classes':['suit-tab suit-tab-sites']}),]
     suit_form_tabs =(('sites', 'Sites'),('nodes','Nodes'),('deploymentprivileges','Privileges'),('tags','Tags'))
 
+class ServiceAttrAsTabInline(PlStackTabularInline):
+    model = ServiceAttribute
+    fields = ['name','value']
+    extra = 0
+    suit_classes = 'suit-tab suit-tab-serviceattrs'
+
+class ServiceAttributeInline(PlStackTabularInline):
+    model = ServiceAttribute
+    fields = ['name','value']
+    extra = 0
+
+class ServiceAdmin(PlanetStackBaseAdmin):
+    list_display = ("name","enabled")
+    fieldsets = [(None, {'fields': ['name','enabled','description']})]
+    inlines = [ServiceAttributeInline,]
+
 class SiteAdmin(PlanetStackBaseAdmin):
     fieldsets = [
         (None, {'fields': ['name', 'site_url', 'enabled', 'is_public', 'login_base', 'location'], 'classes':['suit-tab suit-tab-general']}),
 class SiteAdmin(PlanetStackBaseAdmin):
     fieldsets = [
         (None, {'fields': ['name', 'site_url', 'enabled', 'is_public', 'login_base', 'location'], 'classes':['suit-tab suit-tab-general']}),
@@ -342,8 +367,16 @@ class SitePrivilegeAdmin(PlanetStackBaseAdmin):
             qs = qs.filter(site__in=sites)
         return qs
 
             qs = qs.filter(site__in=sites)
         return qs
 
+class SliceForm(forms.ModelForm):
+    class Meta:
+        model = Slice
+        widgets = {
+            'service': LinkedSelect 
+        }
+
 class SliceAdmin(PlanetStackBaseAdmin):
 class SliceAdmin(PlanetStackBaseAdmin):
-    fieldsets = [('Slice Details', {'fields': ['name', 'site', 'serviceClass', 'description', 'slice_url'], 'classes':['suit-tab suit-tab-general']}),]
+    form = SliceForm
+    fieldsets = [('Slice Details', {'fields': ['name', 'site', 'serviceClass', 'enabled','description', 'service', 'slice_url'], 'classes':['suit-tab suit-tab-general']}),]
     list_display = ('name', 'site','serviceClass', 'slice_url')
     inlines = [SlicePrivilegeInline,SliverInline, TagInline, ReservationInline,SliceNetworkInline]
 
     list_display = ('name', 'site','serviceClass', 'slice_url')
     inlines = [SlicePrivilegeInline,SliverInline, TagInline, ReservationInline,SliceNetworkInline]
 
@@ -500,11 +533,8 @@ class SliverForm(forms.ModelForm):
             'image': LinkedSelect
         }
 
             'image': LinkedSelect
         }
 
-class ProjectAdmin(admin.ModelAdmin):
-    inlines = [TagInline]
-
 class TagAdmin(admin.ModelAdmin):
 class TagAdmin(admin.ModelAdmin):
-    list_display = ['project', 'name', 'value', 'content_type', 'content_object',]
+    list_display = ['service', 'name', 'value', 'content_type', 'content_object',]
 
 class SliverAdmin(PlanetStackBaseAdmin):
     form = SliverForm
 
 class SliverAdmin(PlanetStackBaseAdmin):
     form = SliverForm
@@ -631,6 +661,7 @@ class UserAdmin(UserAdmin):
     # These override the definitions on the base UserAdmin
     # that reference specific fields on auth.User.
     list_display = ('email', 'firstname', 'lastname', 'is_admin', 'last_login')
     # These override the definitions on the base UserAdmin
     # that reference specific fields on auth.User.
     list_display = ('email', 'firstname', 'lastname', 'is_admin', 'last_login')
+    #list_display = ('email', 'username','firstname', 'lastname', 'is_admin', 'last_login')
     list_filter = ()
     inlines = [SlicePrivilegeInline,SitePrivilegeInline,DeploymentPrivilegeInline]
     fieldsets = (
     list_filter = ()
     inlines = [SlicePrivilegeInline,SitePrivilegeInline,DeploymentPrivilegeInline]
     fieldsets = (
@@ -747,7 +778,7 @@ class ReservationAddRefreshForm(ReservationAddForm):
         return False
 
 class ReservationAdmin(admin.ModelAdmin):
         return False
 
 class ReservationAdmin(admin.ModelAdmin):
-    fieldsets = [('Reservation Details', {'fields': ['startTime', 'duration','slice'], 'classes': ['suit-tab suit-tab-general']})]
+    fieldsets = [('Reservation Details', {'fields': ['slice', 'startTime', 'duration'], 'classes': ['suit-tab suit-tab-general']})]
     list_display = ('startTime', 'duration')
     form = ReservationAddForm
 
     list_display = ('startTime', 'duration')
     form = ReservationAddForm
 
@@ -862,11 +893,12 @@ def cache_credentials(sender, user, request, **kwds):
     request.session['auth'] = auth
 user_logged_in.connect(cache_credentials)
 
     request.session['auth'] = auth
 user_logged_in.connect(cache_credentials)
 
+
 # Now register the new UserAdmin...
 admin.site.register(User, UserAdmin)
 # ... and, since we're not using Django's builtin permissions,
 # unregister the Group model from admin.
 # Now register the new UserAdmin...
 admin.site.register(User, UserAdmin)
 # ... and, since we're not using Django's builtin permissions,
 # unregister the Group model from admin.
-admin.site.unregister(Group)
+#admin.site.unregister(Group)
 
 #Do not show django evolution in the admin interface
 from django_evolution.models import Version, Evolution
 
 #Do not show django evolution in the admin interface
 from django_evolution.models import Version, Evolution
@@ -881,8 +913,8 @@ showAll = True
 admin.site.register(Deployment, DeploymentAdmin)
 admin.site.register(Site, SiteAdmin)
 admin.site.register(Slice, SliceAdmin)
 admin.site.register(Deployment, DeploymentAdmin)
 admin.site.register(Site, SiteAdmin)
 admin.site.register(Slice, SliceAdmin)
-admin.site.register(Project, ProjectAdmin)
 admin.site.register(ServiceClass, ServiceClassAdmin)
 admin.site.register(ServiceClass, ServiceClassAdmin)
+admin.site.register(Service, ServiceAdmin)
 admin.site.register(Reservation, ReservationAdmin)
 admin.site.register(Network, NetworkAdmin)
 admin.site.register(Router, RouterAdmin)
 admin.site.register(Reservation, ReservationAdmin)
 admin.site.register(Network, NetworkAdmin)
 admin.site.register(Router, RouterAdmin)
@@ -892,6 +924,10 @@ admin.site.register(NetworkTemplate, NetworkTemplateAdmin)
 if showAll:
     #admin.site.register(PlanetStack)
     admin.site.register(Tag, TagAdmin)
 if showAll:
     #admin.site.register(PlanetStack)
     admin.site.register(Tag, TagAdmin)
+    admin.site.register(DeploymentRole)
+    admin.site.register(SiteRole)
+    admin.site.register(SliceRole)
+    admin.site.register(PlanetStackRole)
     admin.site.register(Node, NodeAdmin)
     #admin.site.register(SlicePrivilege, SlicePrivilegeAdmin)
     #admin.site.register(SitePrivilege, SitePrivilegeAdmin)
     admin.site.register(Node, NodeAdmin)
     #admin.site.register(SlicePrivilege, SlicePrivilegeAdmin)
     #admin.site.register(SitePrivilege, SitePrivilegeAdmin)
index 3db94b8..45edbd4 100644 (file)
@@ -1,4 +1,145 @@
 [
 [
+{
+    "pk": 1, 
+    "model": "core.planetstackrole", 
+    "fields": {
+        "updated": "2013-09-03T11:47:42.611Z", 
+        "role": "admin", 
+        "created": "2013-09-03T11:47:42.611Z"
+    }
+},
+{
+    "pk": 1, 
+    "model": "core.role", 
+    "fields": {
+        "updated": "2013-07-30T10:35:50.572Z", 
+        "content_type": 8, 
+        "description": "PlanetStack Application Administrator", 
+        "role_type": "Admin", 
+        "created": "2013-07-30T10:30:28.633Z"
+    }
+},
+{
+    "pk": 2, 
+    "model": "core.role", 
+    "fields": {
+        "updated": "2013-07-30T10:36:30.174Z", 
+        "content_type": 8, 
+        "description": "User level role for PlanetStack Application", 
+        "role_type": "Default", 
+        "created": "2013-07-30T10:31:02.627Z"
+    }
+},
+{
+    "pk": 3, 
+    "model": "core.role", 
+    "fields": {
+        "updated": "2013-07-30T10:36:07.877Z", 
+        "content_type": 21, 
+        "description": "Administrative role for a Slice", 
+        "role_type": "Admin", 
+        "created": "2013-07-30T10:31:25.829Z"
+    }
+},
+{
+    "pk": 4, 
+    "model": "core.role", 
+    "fields": {
+        "updated": "2013-07-30T10:36:20.679Z", 
+        "content_type": 21, 
+        "description": "User level access for a particular Slice", 
+        "role_type": "Default", 
+        "created": "2013-07-30T10:31:48.791Z"
+    }
+},
+{
+    "pk": 5, 
+    "model": "core.role", 
+    "fields": {
+        "updated": "2013-07-30T10:35:59.388Z", 
+        "content_type": 15, 
+        "description": "Administrator role for a particular Site", 
+        "role_type": "Admin", 
+        "created": "2013-07-30T10:32:20.600Z"
+    }
+},
+{
+    "pk": 6, 
+    "model": "core.role", 
+    "fields": {
+        "updated": "2013-07-30T10:34:39.494Z", 
+        "content_type": 15, 
+        "description": "Principal Investigator for a particular Site", 
+        "role_type": "PI", 
+        "created": "2013-07-30T10:34:39.494Z"
+    }
+},
+{
+    "pk": 7, 
+    "model": "core.role", 
+    "fields": {
+        "updated": "2013-07-30T10:35:27.633Z", 
+        "content_type": 15, 
+        "description": "Technical support for a particular Site. Allows for Read/Write access to a Site's Nodes.", 
+        "role_type": "Tech", 
+        "created": "2013-07-30T10:35:27.633Z"
+    }
+},
+{
+    "pk": 8, 
+    "model": "core.role", 
+    "fields": {
+        "updated": "2013-07-30T10:38:04.554Z", 
+        "content_type": 15, 
+        "description": "Responsibility for a particular Site's accounting and invoices.", 
+        "role_type": "Billing", 
+        "created": "2013-07-30T10:38:04.554Z"
+    }
+},
+{
+    "pk": 9, 
+    "model": "core.role", 
+    "fields": {
+        "updated": "2013-07-30T10:39:07.062Z", 
+        "content_type": 15, 
+        "description": "Default access for a particular Site which allows for Read-only access to the Site's objects.", 
+        "role_type": "Default", 
+        "created": "2013-07-30T10:39:07.062Z"
+    }
+},
+{
+    "pk": 10, 
+    "model": "core.role", 
+    "fields": {
+        "updated": "2013-07-30T10:39:55.479Z", 
+        "content_type": 15, 
+        "description": "Represents the Site through which a particular user is managed through.", 
+        "role_type": "Homed", 
+        "created": "2013-07-30T10:39:55.479Z"
+    }
+},
+{
+    "pk": 11, 
+    "model": "core.role", 
+    "fields": {
+        "updated": "2013-07-30T17:35:59.815Z", 
+        "content_type": 9, 
+        "description": "Administrative responsibility for a particular Deployment.", 
+        "role_type": "Admin", 
+        "created": "2013-07-30T17:35:59.815Z"
+    }
+},
+{
+    "pk": 12, 
+    "model": "core.role", 
+    "fields": {
+        "updated": "2013-07-30T17:36:54.728Z", 
+        "content_type": 9, 
+        "description": "Default access for a particular Deployment.", 
+        "role_type": "Default", 
+        "created": "2013-07-30T17:36:54.728Z"
+    }
+},
 {
     "pk": 1, 
     "model": "core.deployment", 
 {
     "pk": 1, 
     "model": "core.deployment", 
         "created": "2013-04-03T22:57:29.569Z"
     }
 },
         "created": "2013-04-03T22:57:29.569Z"
     }
 },
+{
+    "pk": 1, 
+    "model": "core.deploymentrole", 
+    "fields": {
+        "updated": "2013-09-03T11:48:02.080Z", 
+        "role": "admin", 
+        "created": "2013-09-03T11:48:02.080Z"
+    }
+},
 {
     "pk": 1, 
     "model": "core.site", 
     "fields": {
 {
     "pk": 1, 
     "model": "core.site", 
     "fields": {
-        "updated": "2013-06-21T21:12:16.675Z", 
+        "updated": "2013-09-22T22:04:18.656Z", 
         "name": "Princeton University", 
         "created": "2013-04-03T23:00:10.085Z", 
         "tenant_id": "", 
         "enabled": true, 
         "name": "Princeton University", 
         "created": "2013-04-03T23:00:10.085Z", 
         "tenant_id": "", 
         "enabled": true, 
+        "longitude": null, 
         "site_url": "http://princeton.edu/", 
         "login_base": "princeton", 
         "location": "40.3502,-74.6524", 
         "site_url": "http://princeton.edu/", 
         "login_base": "princeton", 
         "location": "40.3502,-74.6524", 
+        "latitude": null, 
         "is_public": true, 
         "deployments": [
             3, 
         "is_public": true, 
         "deployments": [
             3, 
         "created": "2013-04-03T23:03:51.742Z", 
         "tenant_id": "", 
         "enabled": true, 
         "created": "2013-04-03T23:03:51.742Z", 
         "tenant_id": "", 
         "enabled": true, 
+        "longitude": null, 
         "site_url": "http://www.stanford.edu/", 
         "login_base": "stanford", 
         "location": "37.4294,-122.172", 
         "site_url": "http://www.stanford.edu/", 
         "login_base": "stanford", 
         "location": "37.4294,-122.172", 
+        "latitude": null, 
         "is_public": true, 
         "deployments": [], 
         "is_public": true, 
         "deployments": [], 
-        "abbreviated_name": "" 
+        "abbreviated_name": ""
     }
 },
 {
     }
 },
 {
         "created": "2013-04-03T23:05:51.984Z", 
         "tenant_id": "", 
         "enabled": true, 
         "created": "2013-04-03T23:05:51.984Z", 
         "tenant_id": "", 
         "enabled": true, 
+        "longitude": null, 
         "site_url": "http://www.gatech.edu/", 
         "login_base": "gt", 
         "location": "33.7772,-84.3976", 
         "site_url": "http://www.gatech.edu/", 
         "login_base": "gt", 
         "location": "33.7772,-84.3976", 
+        "latitude": null, 
         "is_public": true, 
         "deployments": [], 
         "is_public": true, 
         "deployments": [], 
-        "abbreviated_name": "" 
+        "abbreviated_name": ""
     }
 },
 {
     }
 },
 {
         "created": "2013-04-03T23:09:52.337Z", 
         "tenant_id": "", 
         "enabled": true, 
         "created": "2013-04-03T23:09:52.337Z", 
         "tenant_id": "", 
         "enabled": true, 
+        "longitude": null, 
         "site_url": "https://www.washington.edu/", 
         "login_base": "uw", 
         "location": "47.6531,-122.313", 
         "site_url": "https://www.washington.edu/", 
         "login_base": "uw", 
         "location": "47.6531,-122.313", 
+        "latitude": null, 
         "is_public": true, 
         "deployments": [], 
         "is_public": true, 
         "deployments": [], 
-        "abbreviated_name": "" 
+        "abbreviated_name": ""
     }
 },
 {
     }
 },
 {
         "created": "2013-04-03T23:14:11.072Z", 
         "tenant_id": "", 
         "enabled": true, 
         "created": "2013-04-03T23:14:11.072Z", 
         "tenant_id": "", 
         "enabled": true, 
+        "longitude": null, 
         "site_url": "http://www.inf.ethz.ch/", 
         "login_base": "ethzcs", 
         "location": "47.3794,8.54513", 
         "site_url": "http://www.inf.ethz.ch/", 
         "login_base": "ethzcs", 
         "location": "47.3794,8.54513", 
+        "latitude": null, 
         "is_public": true, 
         "deployments": [], 
         "is_public": true, 
         "deployments": [], 
-        "abbreviated_name": "" 
+        "abbreviated_name": ""
     }
 },
 {
     }
 },
 {
         "created": "2013-04-03T23:19:38.789Z", 
         "tenant_id": "", 
         "enabled": true, 
         "created": "2013-04-03T23:19:38.789Z", 
         "tenant_id": "", 
         "enabled": true, 
+        "longitude": null, 
         "site_url": "http://www.mpi-sws.mpg.de/", 
         "login_base": "mpisws", 
         "location": "49.14,6.589", 
         "site_url": "http://www.mpi-sws.mpg.de/", 
         "login_base": "mpisws", 
         "location": "49.14,6.589", 
+        "latitude": null, 
         "is_public": true, 
         "deployments": [], 
         "abbreviated_name": ""
         "is_public": true, 
         "deployments": [], 
         "abbreviated_name": ""
         "created": "2013-04-03T23:20:49.815Z", 
         "tenant_id": "", 
         "enabled": true, 
         "created": "2013-04-03T23:20:49.815Z", 
         "tenant_id": "", 
         "enabled": true, 
+        "longitude": null, 
         "site_url": "http://www.planet-lab-jp.org/", 
         "login_base": "utokyo", 
         "location": "35.75,139.5", 
         "site_url": "http://www.planet-lab-jp.org/", 
         "login_base": "utokyo", 
         "location": "35.75,139.5", 
+        "latitude": null, 
         "is_public": true, 
         "deployments": [], 
         "is_public": true, 
         "deployments": [], 
-        "abbreviated_name": "" 
+        "abbreviated_name": ""
+    }
+},
+{
+    "pk": 1, 
+    "model": "core.siterole", 
+    "fields": {
+        "updated": "2013-09-03T11:48:34.966Z", 
+        "role": "admin", 
+        "created": "2013-09-03T11:48:34.966Z"
+    }
+},
+{
+    "pk": 2, 
+    "model": "core.siterole", 
+    "fields": {
+        "updated": "2013-09-03T11:48:49.480Z", 
+        "role": "pi", 
+        "created": "2013-09-03T11:48:49.480Z"
+    }
+},
+{
+    "pk": 3, 
+    "model": "core.siterole", 
+    "fields": {
+        "updated": "2013-09-03T11:49:03.678Z", 
+        "role": "tech", 
+        "created": "2013-09-03T11:49:03.678Z"
+    }
+},
+{
+    "pk": 4, 
+    "model": "core.siterole", 
+    "fields": {
+        "updated": "2013-09-03T11:49:17.254Z", 
+        "role": "billing", 
+        "created": "2013-09-03T11:49:17.254Z"
+    }
+},
+{
+    "pk": 1, 
+    "model": "core.user", 
+    "fields": {
+        "username": "padmin@vicci.org", 
+        "public_key": null, 
+        "updated": "2013-09-22T21:47:30.993Z", 
+        "firstname": "PlanetStack", 
+        "user_url": null, 
+        "lastname": "Admin", 
+        "created": "2013-09-22T21:47:30.959Z", 
+        "is_active": true, 
+        "site": null, 
+        "phone": null, 
+        "kuser_id": null, 
+        "is_staff": true, 
+        "last_login": "2013-09-22T21:48:01.047Z", 
+        "timezone": "America/New_York", 
+        "is_admin": true, 
+        "password": "pbkdf2_sha256$10000$myaBvvoueiQR$o6h2VfhUUfsgDNUYB8v9Qt3U4t+uPSQSb+OMVIPoNsI=", 
+        "email": "padmin@vicci.org", 
+        "enacted": null
+    }
+},
+{
+    "pk": 2, 
+    "model": "core.user", 
+    "fields": {
+        "username": "tony.mack@gmail.com", 
+        "public_key": null, 
+        "updated": "2013-09-22T22:04:26.249Z", 
+        "firstname": "Tony", 
+        "user_url": null, 
+        "lastname": "Mack", 
+        "created": "2013-09-22T22:04:26.249Z", 
+        "is_active": true, 
+        "site": 1, 
+        "phone": null, 
+        "kuser_id": null, 
+        "is_staff": true, 
+        "last_login": "2013-09-22T22:04:18.628Z", 
+        "timezone": "America/New_York", 
+        "is_admin": true, 
+        "password": "!", 
+        "email": "tony.mack@gmail.com", 
+        "enacted": null
+    }
+},
+{
+    "pk": 3, 
+    "model": "core.user", 
+    "fields": {
+        "username": "smbaker@gmail.com", 
+        "public_key": null, 
+        "updated": "2013-09-22T22:04:26.250Z", 
+        "firstname": "Scott", 
+        "user_url": null, 
+        "lastname": "Baker", 
+        "created": "2013-09-22T22:04:26.250Z", 
+        "is_active": true, 
+        "site": 1, 
+        "phone": null, 
+        "kuser_id": null, 
+        "is_staff": true, 
+        "last_login": "2013-09-22T22:04:18.630Z", 
+        "timezone": "America/New_York", 
+        "is_admin": true, 
+        "password": "!", 
+        "email": "smbaker@gmail.com", 
+        "enacted": null
+    }
+},
+{
+    "pk": 4, 
+    "model": "core.user", 
+    "fields": {
+        "username": "pete.larry@gmail.com", 
+        "public_key": null, 
+        "updated": "2013-09-22T22:04:26.251Z", 
+        "firstname": "Larry", 
+        "user_url": null, 
+        "lastname": "Peterson", 
+        "created": "2013-09-22T22:04:26.251Z", 
+        "is_active": true, 
+        "site": 1, 
+        "phone": null, 
+        "kuser_id": null, 
+        "is_staff": true, 
+        "last_login": "2013-09-22T22:04:18.633Z", 
+        "timezone": "America/New_York", 
+        "is_admin": true, 
+        "password": "!", 
+        "email": "pete.larry@gmail.com", 
+        "enacted": null
+    }
+},
+{
+    "pk": 5, 
+    "model": "core.user", 
+    "fields": {
+        "username": "john.hartman@gmail.com", 
+        "public_key": null, 
+        "updated": "2013-09-22T22:04:26.252Z", 
+        "firstname": "John", 
+        "user_url": null, 
+        "lastname": "Hartman", 
+        "created": "2013-09-22T22:04:26.252Z", 
+        "is_active": true, 
+        "site": 1, 
+        "phone": null, 
+        "kuser_id": null, 
+        "is_staff": true, 
+        "last_login": "2013-09-22T22:04:18.635Z", 
+        "timezone": "America/New_York", 
+        "is_admin": true, 
+        "password": "!", 
+        "email": "john.hartman@gmail.com", 
+        "enacted": null
+    }
+},
+{
+    "pk": 6, 
+    "model": "core.user", 
+    "fields": {
+        "username": "mhw@princeton.cs.edu", 
+        "public_key": null, 
+        "updated": "2013-09-22T22:04:26.253Z", 
+        "firstname": "Michael", 
+        "user_url": null, 
+        "lastname": "Wawrzoniak", 
+        "created": "2013-09-22T22:04:26.253Z", 
+        "is_active": true, 
+        "site": 1, 
+        "phone": null, 
+        "kuser_id": null, 
+        "is_staff": true, 
+        "last_login": "2013-09-22T22:04:18.636Z", 
+        "timezone": "America/New_York", 
+        "is_admin": true, 
+        "password": "!", 
+        "email": "mhw@princeton.cs.edu", 
+        "enacted": null
+    }
+},
+{
+    "pk": 7, 
+    "model": "core.user", 
+    "fields": {
+        "username": "andybavier@gmail.com", 
+        "public_key": null, 
+        "updated": "2013-09-22T22:04:26.253Z", 
+        "firstname": "Andy", 
+        "user_url": null, 
+        "lastname": "Bavier", 
+        "created": "2013-09-22T22:04:26.253Z", 
+        "is_active": true, 
+        "site": 1, 
+        "phone": null, 
+        "kuser_id": null, 
+        "is_staff": true, 
+        "last_login": "2013-09-22T22:04:18.638Z", 
+        "timezone": "America/New_York", 
+        "is_admin": true, 
+        "password": "!", 
+        "email": "andybavier@gmail.com", 
+        "enacted": null
     }
 },
 {
     }
 },
 {
     "fields": {
         "updated": "2013-05-10T23:30:52.931Z", 
         "membershipFee": 0, 
     "fields": {
         "updated": "2013-05-10T23:30:52.931Z", 
         "membershipFee": 0, 
-        "description": "Best Effort", 
         "membershipFeeMonths": 0, 
         "created": "2013-05-10T23:30:52.931Z", 
         "upgradeFrom": [
         "membershipFeeMonths": 0, 
         "created": "2013-05-10T23:30:52.931Z", 
         "upgradeFrom": [
         ], 
         "commitment": 0, 
         "name": "Best Effort", 
         ], 
         "commitment": 0, 
         "name": "Best Effort", 
-        "upgradeRequiresApproval": false 
+        "upgradeRequiresApproval": false, 
+        "description": "Best Effort"
     }
 },
 {
     }
 },
 {
     "fields": {
         "updated": "2013-05-10T23:35:51.694Z", 
         "membershipFee": 100, 
     "fields": {
         "updated": "2013-05-10T23:35:51.694Z", 
         "membershipFee": 100, 
-        "description": "Silver", 
         "membershipFeeMonths": 1, 
         "created": "2013-05-10T23:33:24.930Z", 
         "upgradeFrom": [
         "membershipFeeMonths": 1, 
         "created": "2013-05-10T23:33:24.930Z", 
         "upgradeFrom": [
         ], 
         "commitment": 365, 
         "name": "Silver", 
         ], 
         "commitment": 365, 
         "name": "Silver", 
-        "upgradeRequiresApproval": false 
+        "upgradeRequiresApproval": false, 
+        "description": "Silver"
     }
 },
 {
     }
 },
 {
     "fields": {
         "updated": "2013-05-10T23:34:01.320Z", 
         "membershipFee": 18000, 
     "fields": {
         "updated": "2013-05-10T23:34:01.320Z", 
         "membershipFee": 18000, 
-        "description": "Gold", 
         "membershipFeeMonths": 12, 
         "created": "2013-05-10T23:34:01.320Z", 
         "upgradeFrom": [
         "membershipFeeMonths": 12, 
         "created": "2013-05-10T23:34:01.320Z", 
         "upgradeFrom": [
         ], 
         "commitment": 365, 
         "name": "Gold", 
         ], 
         "commitment": 365, 
         "name": "Gold", 
-        "upgradeRequiresApproval": false 
+        "upgradeRequiresApproval": false, 
+        "description": "Gold"
+    }
+},
+{
+    "pk": 1, 
+    "model": "core.service", 
+    "fields": {
+        "updated": "2013-09-22T21:53:48.013Z", 
+        "name": "Request Router Service", 
+        "enabled": true, 
+        "description": "Service to help load balance and direct traffic flow to content within the CDN", 
+        "created": "2013-09-22T21:53:48.013Z"
+    }
+},
+{
+    "pk": 1, 
+    "model": "core.slice", 
+    "fields": {
+        "router_id": null, 
+        "service": 1, 
+        "updated": "2013-09-22T21:54:33.729Z", 
+        "name": "DnsRedir", 
+        "created": "2013-09-22T21:54:33.729Z", 
+        "network_id": null, 
+        "tenant_id": "", 
+        "serviceClass": 1, 
+        "enabled": true, 
+        "site": 1, 
+        "omf_friendly": false, 
+        "subnet_id": null, 
+        "slice_url": "", 
+        "creator": 1, 
+        "description": ""
+    }
+},
+{
+    "pk": 2, 
+    "model": "core.slice", 
+    "fields": {
+        "router_id": null, 
+        "service": 1, 
+        "updated": "2013-09-22T22:07:48.740Z", 
+        "name": "Redirect", 
+        "created": "2013-09-22T22:06:33.765Z", 
+        "network_id": null, 
+        "tenant_id": "", 
+        "serviceClass": 1, 
+        "enabled": true, 
+        "site": 1, 
+        "omf_friendly": false, 
+        "subnet_id": null, 
+        "slice_url": "", 
+        "creator": 1, 
+        "description": ""
+    }
+},
+{
+    "pk": 3, 
+    "model": "core.slice", 
+    "fields": {
+        "router_id": null, 
+        "service": 1, 
+        "updated": "2013-09-22T22:07:21.804Z", 
+        "name": "DnsDemux", 
+        "created": "2013-09-22T22:07:21.804Z", 
+        "network_id": null, 
+        "tenant_id": "", 
+        "serviceClass": 1, 
+        "enabled": true, 
+        "site": 1, 
+        "omf_friendly": false, 
+        "subnet_id": null, 
+        "slice_url": "", 
+        "creator": 1, 
+        "description": ""
+    }
+},
+{
+    "pk": 1, 
+    "model": "core.slicerole", 
+    "fields": {
+        "updated": "2013-09-03T11:48:02.080Z", 
+        "role": "admin", 
+        "created": "2013-09-03T11:48:02.080Z"
+    }
+},
+{
+    "pk": 2, 
+    "model": "core.slicerole", 
+    "fields": {
+        "updated": "2013-09-03T11:48:17.688Z", 
+        "role": "default", 
+        "created": "2013-09-03T11:48:17.688Z"
     }
 },
 {
     }
 },
 {
         "created": "2013-05-10T23:37:09.312Z", 
         "serviceClass": 1, 
         "maxUnitsDeployment": 0, 
         "created": "2013-05-10T23:37:09.312Z", 
         "serviceClass": 1, 
         "maxUnitsDeployment": 0, 
-        "calendarReservable": false, 
         "bucketInRate": 0, 
         "cost": 7, 
         "bucketInRate": 0, 
         "cost": 7, 
-        "maxUnitsNode": 0, 
-        "maxDuration": 0 
+        "calendarReservable": false, 
+        "maxDuration": 0, 
+        "maxUnitsNode": 0
     }
 },
 {
     }
 },
 {
         "created": "2013-05-10T23:44:39.936Z", 
         "serviceClass": 2, 
         "maxUnitsDeployment": 0, 
         "created": "2013-05-10T23:44:39.936Z", 
         "serviceClass": 2, 
         "maxUnitsDeployment": 0, 
-        "calendarReservable": false, 
         "bucketInRate": 0, 
         "cost": 7, 
         "bucketInRate": 0, 
         "cost": 7, 
-        "maxUnitsNode": 0, 
-        "maxDuration": 0 
+        "calendarReservable": false, 
+        "maxDuration": 0, 
+        "maxUnitsNode": 0
     }
 },
 {
     }
 },
 {
         "created": "2013-05-10T23:45:16.137Z", 
         "serviceClass": 3, 
         "maxUnitsDeployment": 0, 
         "created": "2013-05-10T23:45:16.137Z", 
         "serviceClass": 3, 
         "maxUnitsDeployment": 0, 
-        "calendarReservable": false, 
         "bucketInRate": 0, 
         "cost": 7, 
         "bucketInRate": 0, 
         "cost": 7, 
-        "maxUnitsNode": 0, 
-        "maxDuration": 0 
+        "calendarReservable": false, 
+        "maxDuration": 0, 
+        "maxUnitsNode": 0
     }
 },
 {
     }
 },
 {
         "created": "2013-05-10T23:46:33.201Z", 
         "serviceClass": 2, 
         "maxUnitsDeployment": 210, 
         "created": "2013-05-10T23:46:33.201Z", 
         "serviceClass": 2, 
         "maxUnitsDeployment": 210, 
-        "calendarReservable": true, 
         "bucketInRate": 10, 
         "cost": 7, 
         "bucketInRate": 10, 
         "cost": 7, 
-        "maxUnitsNode": 6, 
-        "maxDuration": 168 
+        "calendarReservable": true, 
+        "maxDuration": 168, 
+        "maxUnitsNode": 6
     }
 },
 {
     }
 },
 {
         "created": "2013-05-10T23:47:31.770Z", 
         "serviceClass": 3, 
         "maxUnitsDeployment": 210, 
         "created": "2013-05-10T23:47:31.770Z", 
         "serviceClass": 3, 
         "maxUnitsDeployment": 210, 
-        "calendarReservable": true, 
         "bucketInRate": 0, 
         "cost": 0, 
         "bucketInRate": 0, 
         "cost": 0, 
-        "maxUnitsNode": 6, 
-        "maxDuration": 8760 
+        "calendarReservable": true, 
+        "maxDuration": 8760, 
+        "maxUnitsNode": 6
     }
 },
 {
     "pk": 1, 
     }
 },
 {
     "pk": 1, 
-    "model": "core.role", 
-    "fields": {
-        "updated": "2013-07-30T10:35:50.572Z", 
-        "description": "PlanetStack Application Administrator", 
-        "created": "2013-07-30T10:30:28.633Z", 
-        "content_type": 8, 
-        "role_type": "Admin" 
-    }
-},
-{
-    "pk": 2, 
-    "model": "core.role", 
-    "fields": {
-        "updated": "2013-07-30T10:36:30.174Z", 
-        "description": "User level role for PlanetStack Application", 
-        "created": "2013-07-30T10:31:02.627Z", 
-        "content_type": 8, 
-        "role_type": "Default" 
-    }
-},
-{
-    "pk": 3, 
-    "model": "core.role", 
-    "fields": {
-        "updated": "2013-07-30T10:36:07.877Z", 
-        "description": "Administrative role for a Slice", 
-        "created": "2013-07-30T10:31:25.829Z", 
-        "content_type": 21, 
-        "role_type": "Admin" 
-    }
-},
-{
-    "pk": 4, 
-    "model": "core.role", 
-    "fields": {
-        "updated": "2013-07-30T10:36:20.679Z", 
-        "description": "User level access for a particular Slice", 
-        "created": "2013-07-30T10:31:48.791Z", 
-        "content_type": 21, 
-        "role_type": "Default" 
-    }
-},
-{
-    "pk": 5, 
-    "model": "core.role", 
-    "fields": {
-        "updated": "2013-07-30T10:35:59.388Z", 
-        "description": "Administrator role for a particular Site", 
-        "created": "2013-07-30T10:32:20.600Z", 
-        "content_type": 15, 
-        "role_type": "Admin" 
-    }
-},
-{
-    "pk": 6, 
-    "model": "core.role", 
+    "model": "requestrouter.requestrouterservice", 
     "fields": {
     "fields": {
-        "updated": "2013-07-30T10:34:39.494Z", 
-        "description": "Principal Investigator for a particular Site", 
-        "created": "2013-07-30T10:34:39.494Z", 
-        "content_type": 15, 
-        "role_type": "PI" 
-    }
-},
-{
-    "pk": 7, 
-    "model": "core.role", 
-    "fields": {
-        "updated": "2013-07-30T10:35:27.633Z", 
-        "description": "Technical support for a particular Site. Allows for Read/Write access to a Site's Nodes.", 
-        "created": "2013-07-30T10:35:27.633Z", 
-        "content_type": 15, 
-        "role_type": "Tech" 
-    }
-},
-{
-    "pk": 8, 
-    "model": "core.role", 
-    "fields": {
-        "updated": "2013-07-30T10:38:04.554Z", 
-        "description": "Responsibility for a particular Site's accounting and invoices.", 
-        "created": "2013-07-30T10:38:04.554Z", 
-        "content_type": 15, 
-        "role_type": "Billing" 
-    }
-},
-{
-    "pk": 9, 
-    "model": "core.role", 
-    "fields": {
-        "updated": "2013-07-30T10:39:07.062Z", 
-        "description": "Default access for a particular Site which allows for Read-only access to the Site's objects.", 
-        "created": "2013-07-30T10:39:07.062Z", 
-        "content_type": 15, 
-        "role_type": "Default" 
-    }
-},
-{
-    "pk": 10, 
-    "model": "core.role", 
-    "fields": {
-        "updated": "2013-07-30T10:39:55.479Z", 
-        "description": "Represents the Site through which a particular user is managed through.", 
-        "created": "2013-07-30T10:39:55.479Z", 
-        "content_type": 15, 
-        "role_type": "Homed" 
-    }
-},
-{
-    "pk": 11,
-    "model": "core.role",
-    "fields": {
-        "updated": "2013-07-30T17:35:59.815Z",
-        "description": "Administrative responsibility for a particular Deployment.",
-        "created": "2013-07-30T17:35:59.815Z",
-        "content_type": 9,
-        "role_type": "Admin"
-    }
-},
-{
-    "pk": 12,
-    "model": "core.role",
-    "fields": {
-        "updated": "2013-07-30T17:36:54.728Z",
-        "description": "Default access for a particular Deployment.",
-        "created": "2013-07-30T17:36:54.728Z",
-        "content_type": 9,
-        "role_type": "Default"
-    }
-},
-{
-    "pk": 1,
-    "model": "core.planetstackrole",
-    "fields": {
-        "updated": "2013-09-03T11:47:42.611Z",
-        "role": "admin",
-        "created": "2013-09-03T11:47:42.611Z"
-    }
-},
-{
-    "pk": 1,
-    "model": "core.siterole",
-    "fields": {
-        "updated": "2013-09-03T11:48:34.966Z",
-        "role": "admin",
-        "created": "2013-09-03T11:48:34.966Z"
-    }
-},
-{
-    "pk": 2,
-    "model": "core.siterole",
-    "fields": {
-        "updated": "2013-09-03T11:48:49.480Z",
-        "role": "pi",
-        "created": "2013-09-03T11:48:49.480Z"
-    }
-},
-{
-    "pk": 3,
-    "model": "core.siterole",
-    "fields": {
-        "updated": "2013-09-03T11:49:03.678Z",
-        "role": "tech",
-        "created": "2013-09-03T11:49:03.678Z"
-    }
-},
-{
-    "pk": 4,
-    "model": "core.siterole",
-    "fields": {
-        "updated": "2013-09-03T11:49:17.254Z",
-        "role": "billing",
-        "created": "2013-09-03T11:49:17.254Z"
-    }
-},
-{
-    "pk": 1,
-    "model": "core.slicerole",
-    "fields": {
-        "updated": "2013-09-03T11:48:02.080Z",
-        "role": "admin",
-        "created": "2013-09-03T11:48:02.080Z"
-    }
-},
-{
-    "pk": 2,
-    "model": "core.slicerole",
-    "fields": {
-        "updated": "2013-09-03T11:48:17.688Z",
-        "role": "default",
-        "created": "2013-09-03T11:48:17.688Z"
-    }
-},
-{
-    "pk": 1,
-    "model": "core.deploymentrole",
-    "fields": {
-        "updated": "2013-09-03T11:48:02.080Z",
-        "role": "admin",
-        "created": "2013-09-03T11:48:02.080Z"
+        "behindNat": false, 
+        "defaultAction": "best", 
+        "defaultTTL": 30, 
+        "lastResortAction": "random", 
+        "maxAnswers": 3
     }
 }
 ]
     }
 }
 ]
index b4c7cf6..ac12370 100644 (file)
@@ -1,6 +1,9 @@
 from .plcorebase import PlCoreBase
 from .planetstack import PlanetStack
 from .project import Project
 from .plcorebase import PlCoreBase
 from .planetstack import PlanetStack
 from .project import Project
+from .singletonmodel import SingletonModel
+from .service import Service
+from .service import ServiceAttribute
 from .tag import Tag
 from .role import Role
 from .deployment import Deployment
 from .tag import Tag
 from .role import Role
 from .deployment import Deployment
index 55711a4..72e7a5f 100644 (file)
@@ -29,7 +29,7 @@ class Network(PlCoreBase):
     subnet = models.CharField(max_length=32, blank=True)
     ports = models.CharField(max_length=1024, blank=True, null=True)
     labels = models.CharField(max_length=1024, blank=True, null=True)
     subnet = models.CharField(max_length=32, blank=True)
     ports = models.CharField(max_length=1024, blank=True, null=True)
     labels = models.CharField(max_length=1024, blank=True, null=True)
-    owner = models.ForeignKey(Slice, related_name="ownedNetworks")
+    owner = models.ForeignKey(Slice, related_name="ownedNetworks", help_text="Slice that owns control of this Network")
 
     guaranteedBandwidth = models.IntegerField(default=0)
     permitAllSlices = models.BooleanField(default=False)
 
     guaranteedBandwidth = models.IntegerField(default=0)
     permitAllSlices = models.BooleanField(default=False)
index 62bcb75..4a64ce5 100644 (file)
@@ -38,13 +38,13 @@ class PlCoreBase(models.Model):
        def delete(self, *args, **kwds):
                super(PlCoreBase, self).delete(*args, **kwds)
 
        def delete(self, *args, **kwds):
                super(PlCoreBase, self).delete(*args, **kwds)
 
-               EventSender().fire({'delete_flag':True,'model':self.__name__})
+#              EventSender().fire({'delete_flag':True,'model':self.__name__})
 
        def save(self, *args, **kwargs):
                super(PlCoreBase, self).save(*args, **kwargs)
                
                # Tell the observer that the source database has been updated
 
        def save(self, *args, **kwargs):
                super(PlCoreBase, self).save(*args, **kwargs)
                
                # Tell the observer that the source database has been updated
-               EventSender().fire()
+               #EventSender().fire()
 
                self.__initial = self._dict
 
 
                self.__initial = self._dict
 
diff --git a/planetstack/core/models/plservice.py b/planetstack/core/models/plservice.py
new file mode 100644 (file)
index 0000000..eb27d0f
--- /dev/null
@@ -0,0 +1,9 @@
+from core.models import PlCoreBase,SingletonModel
+from django.db import models
+
+class PlanetStackService(PlCoreBase):
+    description = models.TextField(max_length=254,null=True, blank=True,help_text="Description of Service")
+    enabled = models.BooleanField(default=True)
+    serviceName = models.CharField(max_length=30, help_text="Service Name")
+
+    def __unicode__(self): return u'%s' % (self.serviceName)
diff --git a/planetstack/core/models/singletonmodel.py b/planetstack/core/models/singletonmodel.py
new file mode 100644 (file)
index 0000000..4ab6f6e
--- /dev/null
@@ -0,0 +1,16 @@
+from django.db import models
+
+class SingletonModel(models.Model):
+    class Meta:
+        abstract = True
+    def save(self, *args, **kwargs):
+        self.__class__.objects.exclude(id=self.id).delete()
+        super(SingletonModel, self).save(*args, **kwargs)
+    @classmethod
+    def load(cls):
+        try:
+            return cls.objects.get()
+        except cls.DoesNotExist:
+            return cls()
index e584c07..51e05f5 100644 (file)
@@ -8,6 +8,7 @@ from core.models import Deployment
 from core.models import ServiceClass
 from core.models import Tag
 from django.contrib.contenttypes import generic
 from core.models import ServiceClass
 from core.models import Tag
 from django.contrib.contenttypes import generic
+from core.models import Service
 
 # Create your models here.
 
 
 # Create your models here.
 
@@ -22,6 +23,7 @@ class Slice(PlCoreBase):
     network_id = models.CharField(null=True, blank=True, max_length=256, help_text="Quantum network")
     router_id = models.CharField(null=True, blank=True, max_length=256, help_text="Quantum router id")
     subnet_id = models.CharField(null=True, blank=True, max_length=256, help_text="Quantum subnet id")
     network_id = models.CharField(null=True, blank=True, max_length=256, help_text="Quantum network")
     router_id = models.CharField(null=True, blank=True, max_length=256, help_text="Quantum router id")
     subnet_id = models.CharField(null=True, blank=True, max_length=256, help_text="Quantum subnet id")
+    service = models.ForeignKey(Service, related_name='service', null=True, blank=True)
 
     tags = generic.GenericRelation(Tag)
 
 
     tags = generic.GenericRelation(Tag)
 
index 7c957a1..cbe63a5 100644 (file)
@@ -1,7 +1,7 @@
 import os
 from django.db import models
 from core.models import PlCoreBase
 import os
 from django.db import models
 from core.models import PlCoreBase
-from core.models import Project
+from core.models import Service
 from django.contrib.contenttypes.models import ContentType
 from django.contrib.contenttypes import generic
 
 from django.contrib.contenttypes.models import ContentType
 from django.contrib.contenttypes import generic
 
@@ -9,7 +9,7 @@ from django.contrib.contenttypes import generic
 
 class Tag(PlCoreBase):
 
 
 class Tag(PlCoreBase):
 
-    project = models.ForeignKey(Project, related_name='tags', help_text="The Project this Tag is associated with")
+    service = models.ForeignKey(Service, related_name='tags', help_text="The Service this Tag is associated with")
 
     name = models.SlugField(help_text="The name of this tag", max_length=128)
     value = models.CharField(help_text="The value of this tag", max_length=1024)
 
     name = models.SlugField(help_text="The name of this tag", max_length=128)
     value = models.CharField(help_text="The value of this tag", max_length=1024)
index b517eac..e076854 100644 (file)
@@ -1,2 +1,21 @@
 .required:after {color: red ! important; font-size: 18px }
 #.btn-success {color:black}
 .required:after {color: red ! important; font-size: 18px }
 #.btn-success {color:black}
+#suit-center {
+padding: 20px;
+width: 100%;
+min-width:650px;
+}
+.inner-two-columns .inner-center-column .tab-content {
+overflow: inherit;
+margin-bottom: 15px;
+min-width: 650px;
+}
+.inner-two-columns .inner-center-column {
+#margin-right: 200px;
+#background-color: rgb(158, 163, 159);
+}
+label {
+display: block;
+font-weight: bold;
+margin-bottom: 5px;
+}
index 7593650..5cd62b0 100644 (file)
@@ -138,6 +138,7 @@ INSTALLED_APPS = (
     'django_evolution',
     'core',
     'hpc',
     'django_evolution',
     'core',
     'hpc',
+    'requestrouter',
     'geoposition',
 )
 
     'geoposition',
 )
 
diff --git a/planetstack/requestrouter/__init__.py b/planetstack/requestrouter/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/planetstack/requestrouter/admin.py b/planetstack/requestrouter/admin.py
new file mode 100644 (file)
index 0000000..30b7fad
--- /dev/null
@@ -0,0 +1,31 @@
+from django.contrib import admin
+
+from requestrouter.models import *
+from django import forms
+from django.utils.safestring import mark_safe
+from django.contrib.auth.admin import UserAdmin
+from django.contrib.admin.widgets import FilteredSelectMultiple
+from django.contrib.auth.forms import ReadOnlyPasswordHashField
+from django.contrib.auth.signals import user_logged_in
+from django.utils import timezone
+from django.contrib.contenttypes import generic
+from suit.widgets import LinkedSelect
+from core.admin import SingletonAdmin,SliceInline,ServiceAttrAsTabInline
+
+class RequestRouterServiceAdmin(SingletonAdmin):
+    model = RequestRouterService
+    verbose_name = "Request Router Service"
+    verbose_name_plural = "Request Router Service"
+    list_display = ("name","enabled")
+    fieldsets = [(None, {'fields': ['name','enabled','versionNumber', 'description','behindNat','defaultTTL','defaultAction','lastResortAction','maxAnswers'], 'classes':['suit-tab suit-tab-general']})]
+    inlines = [SliceInline,ServiceAttrAsTabInline]
+
+    suit_form_tabs =(('general', 'Request Router Service Details'),
+        ('slices','Slices'),
+        ('serviceattrs','Additional Attributes'),
+    )
+
+
+admin.site.register(RequestRouterService, RequestRouterServiceAdmin)
+admin.site.register(ClientMap)
+
diff --git a/planetstack/requestrouter/models.py b/planetstack/requestrouter/models.py
new file mode 100644 (file)
index 0000000..c641b16
--- /dev/null
@@ -0,0 +1,25 @@
+from core.models import User,Site,Service,SingletonModel,PlCoreBase
+import os
+from django.db import models
+from django.forms.models import model_to_dict
+
+# Create your models here.
+
+class RequestRouterService(SingletonModel,Service):
+    class Meta:
+        app_label = "requestrouter"
+        verbose_name = "Request Router Service"
+
+    behindNat = models.BooleanField(default=False, help_text="Enables 'Behind NAT' mode.")
+    defaultTTL = models.PositiveIntegerField(default=30, help_text="DNS response time-to-live(TTL)")
+    defaultAction = models.CharField(max_length=30, default = "best", help_text="Review if this should be enum")
+    lastResortAction = models.CharField(max_length=30, default = "random", help_text="Review if this should be enum")
+    maxAnswers = models.PositiveIntegerField(default=3, help_text="Maximum number of answers in DNS response.")
+    
+    def __unicode__(self):  return u'RequestRouterService'
+
+class ClientMap(models.Model):
+    site = models.OneToOneField(Site, unique=True)
+    name = models.CharField(max_length=64, help_text="Name of the Client Map")
+    description = models.TextField(null=True, blank=True,max_length=130)
+