Merge branch 'master' of ssh://git.planet-lab.org/git/plstackapi
diff --git a/planetstack/core/admin.py b/planetstack/core/admin.py
index cd0e5dd..5590144 100644
--- a/planetstack/core/admin.py
+++ b/planetstack/core/admin.py
@@ -7,7 +7,7 @@
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.admin.widgets import FilteredSelectMultiple, AdminTextareaWidget
from django.contrib.auth.forms import ReadOnlyPasswordHashField, AdminPasswordChangeForm
from django.contrib.auth.signals import user_logged_in
from django.utils import timezone
@@ -15,6 +15,9 @@
from suit.widgets import LinkedSelect
from django.core.exceptions import PermissionDenied
from django.core.urlresolvers import reverse, NoReverseMatch
+from django.utils.encoding import force_text, python_2_unicode_compatible
+from django.utils.html import conditional_escape, format_html
+from django.forms.utils import flatatt, to_current_timezone
from cgi import escape as html_escape
import django_evolution
@@ -40,6 +43,17 @@
else:
return "%s %s" % (icon, html_escape(obj.backend_status, quote=True))
+class UploadTextareaWidget(AdminTextareaWidget):
+ def render(self, name, value, attrs=None):
+ if value is None:
+ value = ''
+ final_attrs = self.build_attrs(attrs, name=name)
+ return format_html('<input type="file" style="width: 0; height: 0" id="btn_upload_%s" onChange="uploadTextarea(event,\'%s\');">' \
+ '<button onClick="$(\'#btn_upload_%s\').click(); return false;">Upload</button>' \
+ '<br><textarea{0}>\r\n{1}</textarea>' % (attrs["id"], attrs["id"], attrs["id"]),
+ flatatt(final_attrs),
+ force_text(value))
+
class PlainTextWidget(forms.HiddenInput):
input_type = 'hidden'
@@ -408,8 +422,8 @@
def queryset(self, request):
return SitePrivilege.select_by_user(request.user)
-class SiteDeploymentInline(PlStackTabularInline):
- model = SiteDeployment
+class SiteDeploymentsInline(PlStackTabularInline):
+ model = SiteDeployments
extra = 0
suit_classes = 'suit-tab suit-tab-deployments'
fields = ['backend_status_icon', 'deployment','site']
@@ -421,10 +435,10 @@
if db_field.name == 'deployment':
kwargs['queryset'] = Deployment.select_by_user(request.user)
- return super(SiteDeploymentInline, self).formfield_for_foreignkey(db_field, request, **kwargs)
+ return super(SiteDeploymentsInline, self).formfield_for_foreignkey(db_field, request, **kwargs)
def queryset(self, request):
- return SiteDeployment.select_by_user(request.user)
+ return SiteDeployments.select_by_user(request.user)
class SlicePrivilegeInline(PlStackTabularInline):
@@ -455,8 +469,8 @@
fields = ['backend_status_icon', 'network']
readonly_fields = ('backend_status_icon', )
-class ImageDeploymentInline(PlStackTabularInline):
- model = ImageDeployment
+class ImageDeploymentsInline(PlStackTabularInline):
+ model = ImageDeployments
extra = 0
verbose_name = "Image Deployments"
verbose_name_plural = "Image Deployments"
@@ -508,8 +522,8 @@
self.fields['accessControl'].initial = "allow site " + request.user.site.name
if self.instance and self.instance.pk:
- self.fields['sites'].initial = [x.site for x in self.instance.sitedeployments_set.all()]
- self.fields['images'].initial = [x.image for x in self.instance.imagedeployments_set.all()]
+ self.fields['sites'].initial = [x.site for x in self.instance.sitedeployments.all()]
+ self.fields['images'].initial = [x.image for x in self.instance.imagedeployments.all()]
self.fields['flavors'].initial = self.instance.flavors.all()
def manipulate_m2m_objs(self, this_obj, selected_objs, all_relations, relation_class, local_attrname, foreign_attrname):
@@ -560,8 +574,8 @@
# create/destroy the through models ourselves. There has to be
# a better way...
- self.manipulate_m2m_objs(deployment, self.cleaned_data['sites'], deployment.sitedeployments_set.all(), SiteDeployment, "deployment", "site")
- self.manipulate_m2m_objs(deployment, self.cleaned_data['images'], deployment.imagedeployments_set.all(), ImageDeployment, "deployment", "image")
+ self.manipulate_m2m_objs(deployment, self.cleaned_data['sites'], deployment.sitedeployments.all(), SiteDeployments, "deployment", "site")
+ self.manipulate_m2m_objs(deployment, self.cleaned_data['images'], deployment.imagedeployments.all(), ImageDeployments, "deployment", "image")
self.save_m2m()
@@ -580,7 +594,7 @@
model = Deployment
fieldList = ['backend_status_text', 'name', 'availability_zone', 'sites', 'images', 'flavors', 'accessControl']
fieldsets = [(None, {'fields': fieldList, 'classes':['suit-tab suit-tab-sites']})]
- inlines = [DeploymentPrivilegeInline,NodeInline,TagInline] # ,ImageDeploymentInline]
+ inlines = [DeploymentPrivilegeInline,NodeInline,TagInline] # ,ImageDeploymentsInline]
list_display = ['backend_status_icon', 'name']
list_display_links = ('backend_status_icon', 'name', )
readonly_fields = ('backend_status_text', )
@@ -647,7 +661,7 @@
list_display = ('backend_status_icon', 'name', 'login_base','site_url', 'enabled')
list_display_links = ('backend_status_icon', 'name', )
filter_horizontal = ('deployments',)
- inlines = [SliceInline,UserInline,TagInline, NodeInline, SitePrivilegeInline, SiteDeploymentInline]
+ inlines = [SliceInline,UserInline,TagInline, NodeInline, SitePrivilegeInline, SiteDeploymentsInline]
search_fields = ['name']
def queryset(self, request):
@@ -748,8 +762,8 @@
raise forms.ValidationError('slice name must begin with %s' % site.login_base)
return cleaned_data
-class SliceDeploymentInline(PlStackTabularInline):
- model = SliceDeployment
+class SliceDeploymentsInline(PlStackTabularInline):
+ model = SliceDeployments
extra = 0
verbose_name = "Slice Deployment"
verbose_name_plural = "Slice Deployments"
@@ -765,7 +779,7 @@
list_display = ('backend_status_icon', 'name', 'site','serviceClass', 'slice_url', 'max_slivers')
list_display_links = ('backend_status_icon', 'name', )
inlines = [SlicePrivilegeInline,SliverInline, TagInline, ReservationInline,SliceNetworkInline]
- admin_inlines = [SliceDeploymentInline]
+ admin_inlines = [SliceDeploymentsInline]
user_readonly_fields = fieldList
@@ -892,7 +906,7 @@
suit_form_tabs =(('general','Image Details'),('slivers','Slivers'),('imagedeployments','Deployments'))
- inlines = [SliverInline, ImageDeploymentInline]
+ inlines = [SliverInline, ImageDeploymentsInline]
user_readonly_fields = ['name', 'disk_format', 'container_format']
@@ -1041,6 +1055,7 @@
class Meta:
model = User
+ widgets = { 'public_key': UploadTextareaWidget, }
def clean_password(self):
# Regardless of what the user provides, return the initial value.
@@ -1333,6 +1348,14 @@
fields = ['backend_status_icon', 'deployment','net_id','subnet_id']
readonly_fields = ('backend_status_icon', )
+class NetworkForm(forms.ModelForm):
+ class Meta:
+ model = Network
+ widgets = {
+ 'topologyParameters': UploadTextareaWidget,
+ 'controllerParameters': UploadTextareaWidget,
+ }
+
class NetworkAdmin(PlanetStackBaseAdmin):
list_display = ("backend_status_icon", "name", "subnet", "ports", "labels")
list_display_links = ('backend_status_icon', 'name', )
@@ -1341,8 +1364,14 @@
inlines = [NetworkParameterInline, NetworkSliversInline, NetworkSlicesInline, RouterInline]
admin_inlines = [NetworkDeploymentsInline]
+ form=NetworkForm
+
fieldsets = [
- (None, {'fields': ['backend_status_text', 'name','template','ports','labels','owner','guaranteedBandwidth', 'permitAllSlices','permittedSlices','network_id','router_id','subnet_id','subnet'], 'classes':['suit-tab suit-tab-general']}),]
+ (None, {'fields': ['backend_status_text', 'name','template','ports','labels','owner','guaranteedBandwidth', 'permitAllSlices','permittedSlices','network_id','router_id','subnet_id','subnet'],
+ 'classes':['suit-tab suit-tab-general']}),
+ (None, {'fields': ['topologyParameters', 'controllerUrl', 'controllerParameters'],
+ 'classes':['suit-tab suit-tab-sdn']}),
+ ]
readonly_fields = ('backend_status_text', )
user_readonly_fields = ['name','template','ports','labels','owner','guaranteedBandwidth', 'permitAllSlices','permittedSlices','network_id','router_id','subnet_id','subnet']
@@ -1350,6 +1379,7 @@
@property
def suit_form_tabs(self):
tabs=[('general','Network Details'),
+ ('sdn', 'SDN Configuration'),
('netparams', 'Parameters'),
('networkslivers','Slivers'),
('networkslices','Slices'),
@@ -1368,6 +1398,10 @@
list_display_links = ('backend_status_icon', 'name', )
user_readonly_fields = ["name", "guaranteedBandwidth", "visibility"]
user_readonly_inlines = []
+ fieldsets = [
+ (None, {'fields': ['name', 'description', 'guaranteedBandwidth', 'visibility', 'translation', 'sharedNetworkName', 'sharedNetworkId', 'topologyKind', 'controllerKind'],
+ 'classes':['suit-tab suit-tab-general']}),]
+ suit_form_tabs = (('general','Network Template Details'), )
class FlavorAdmin(PlanetStackBaseAdmin):
list_display = ("backend_status_icon", "name", "flavor", "order", "default")
diff --git a/planetstack/core/migrations/0006_auto_20141111_2314.py b/planetstack/core/migrations/0006_auto_20141111_2314.py
deleted file mode 100644
index 37a197d..0000000
--- a/planetstack/core/migrations/0006_auto_20141111_2314.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.db import models, migrations
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('core', '0005_auto_20141111_2311'),
- ]
-
- operations = [
- migrations.DeleteModel(
- name='ImageDeployments',
- ),
- migrations.DeleteModel(
- name='SiteDeployments',
- ),
- migrations.DeleteModel(
- name='SliceDeployments',
- ),
- migrations.DeleteModel(
- name='UserDeployments',
- ),
- ]
diff --git a/planetstack/core/migrations/0007_network_ports.py b/planetstack/core/migrations/0007_network_ports.py
new file mode 100644
index 0000000..b99c840
--- /dev/null
+++ b/planetstack/core/migrations/0007_network_ports.py
@@ -0,0 +1,21 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import models, migrations
+import core.models.network
+import timezones.fields
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('core', '0004_auto_20141006_1719'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='network',
+ name='ports',
+ field=models.CharField(blank=True, max_length=1024, null=True, validators=[core.models.network.ValidateNatList]),
+ ),
+ ]
diff --git a/planetstack/core/migrations/0008_network_sdn.py b/planetstack/core/migrations/0008_network_sdn.py
new file mode 100644
index 0000000..4a1443e
--- /dev/null
+++ b/planetstack/core/migrations/0008_network_sdn.py
@@ -0,0 +1,44 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import models, migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('core', '0007_network_ports'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='network',
+ name='controllerParameters',
+ field=models.TextField(null=True, blank=True),
+ preserve_default=True,
+ ),
+ migrations.AddField(
+ model_name='network',
+ name='topologyParameters',
+ field=models.TextField(null=True, blank=True),
+ preserve_default=True,
+ ),
+ migrations.AddField(
+ model_name='networktemplate',
+ name='controllerKind',
+ field=models.CharField(default=None, max_length=30, null=True, blank=True, choices=[(None, b'None'), (b'onos', b'ONOS'), (b'custom', b'Custom')]),
+ preserve_default=True,
+ ),
+ migrations.AddField(
+ model_name='networktemplate',
+ name='topologyKind',
+ field=models.CharField(default=b'BigSwitch', max_length=30, choices=[(b'bigswitch', b'BigSwitch'), (b'physical', b'Physical'), (b'custom', b'Custom')]),
+ preserve_default=True,
+ ),
+ migrations.AddField(
+ model_name='network',
+ name='controllerUrl',
+ field=models.CharField(max_length=1024, null=True, blank=True),
+ preserve_default=True,
+ ),
+ ]
diff --git a/planetstack/core/migrations/0005_auto_20141111_2311.py b/planetstack/core/migrations/0009_auto_20141119_1515.py
similarity index 78%
rename from planetstack/core/migrations/0005_auto_20141111_2311.py
rename to planetstack/core/migrations/0009_auto_20141119_1515.py
index 257cf43..57609c0 100644
--- a/planetstack/core/migrations/0005_auto_20141111_2311.py
+++ b/planetstack/core/migrations/0009_auto_20141119_1515.py
@@ -2,8 +2,6 @@
from __future__ import unicode_literals
from django.db import models, migrations
-import core.models.network
-import django.utils.timezone
from django.conf import settings
import timezones.fields
@@ -11,117 +9,10 @@
class Migration(migrations.Migration):
dependencies = [
- ('core', '0004_auto_20141006_1719'),
+ ('core', '0008_network_sdn'),
]
operations = [
- migrations.CreateModel(
- name='ImageDeployment',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('created', models.DateTimeField(default=django.utils.timezone.now, auto_now_add=True)),
- ('updated', models.DateTimeField(default=django.utils.timezone.now, auto_now=True)),
- ('enacted', models.DateTimeField(default=None, null=True)),
- ('backend_status', models.CharField(default=b'Provisioning in progress', max_length=140)),
- ('deleted', models.BooleanField(default=False)),
- ('glance_image_id', models.CharField(help_text=b'Glance image id', max_length=200, null=True, blank=True)),
- ('deployment', models.ForeignKey(related_name=b'imagedeployments', to='core.Deployment')),
- ('image', models.ForeignKey(related_name=b'imagedeployments', to='core.Image')),
- ],
- options={
- 'abstract': False,
- },
- bases=(models.Model,),
- ),
- migrations.CreateModel(
- name='SiteDeployment',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('created', models.DateTimeField(default=django.utils.timezone.now, auto_now_add=True)),
- ('updated', models.DateTimeField(default=django.utils.timezone.now, auto_now=True)),
- ('enacted', models.DateTimeField(default=None, null=True)),
- ('backend_status', models.CharField(default=b'Provisioning in progress', max_length=140)),
- ('deleted', models.BooleanField(default=False)),
- ('tenant_id', models.CharField(help_text=b'Keystone tenant id', max_length=200, null=True, blank=True)),
- ('deployment', models.ForeignKey(related_name=b'sitedeployments', to='core.Deployment')),
- ('site', models.ForeignKey(related_name=b'sitedeployments', to='core.Site')),
- ],
- options={
- 'abstract': False,
- },
- bases=(models.Model,),
- ),
- migrations.CreateModel(
- name='SliceDeployment',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('created', models.DateTimeField(default=django.utils.timezone.now, auto_now_add=True)),
- ('updated', models.DateTimeField(default=django.utils.timezone.now, auto_now=True)),
- ('enacted', models.DateTimeField(default=None, null=True)),
- ('backend_status', models.CharField(default=b'Provisioning in progress', max_length=140)),
- ('deleted', models.BooleanField(default=False)),
- ('tenant_id', models.CharField(help_text=b'Keystone tenant id', max_length=200, null=True, blank=True)),
- ('network_id', models.CharField(help_text=b'Quantum network', max_length=256, null=True, blank=True)),
- ('router_id', models.CharField(help_text=b'Quantum router id', max_length=256, null=True, blank=True)),
- ('subnet_id', models.CharField(help_text=b'Quantum subnet id', max_length=256, null=True, blank=True)),
- ('deployment', models.ForeignKey(related_name=b'slicedeployments', to='core.Deployment')),
- ('slice', models.ForeignKey(related_name=b'slicedeployments', to='core.Slice')),
- ],
- options={
- 'abstract': False,
- },
- bases=(models.Model,),
- ),
- migrations.CreateModel(
- name='UserDeployment',
- fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
- ('created', models.DateTimeField(default=django.utils.timezone.now, auto_now_add=True)),
- ('updated', models.DateTimeField(default=django.utils.timezone.now, auto_now=True)),
- ('enacted', models.DateTimeField(default=None, null=True)),
- ('backend_status', models.CharField(default=b'Provisioning in progress', max_length=140)),
- ('deleted', models.BooleanField(default=False)),
- ('kuser_id', models.CharField(help_text=b'Keystone user id', max_length=200, null=True, blank=True)),
- ('deployment', models.ForeignKey(related_name=b'userdeployments', to='core.Deployment')),
- ('user', models.ForeignKey(related_name=b'userdeployments', to=settings.AUTH_USER_MODEL)),
- ],
- options={
- 'abstract': False,
- },
- bases=(models.Model,),
- ),
- migrations.RemoveField(
- model_name='imagedeployments',
- name='deployment',
- ),
- migrations.RemoveField(
- model_name='imagedeployments',
- name='image',
- ),
- migrations.RemoveField(
- model_name='sitedeployments',
- name='deployment',
- ),
- migrations.RemoveField(
- model_name='sitedeployments',
- name='site',
- ),
- migrations.RemoveField(
- model_name='slicedeployments',
- name='deployment',
- ),
- migrations.RemoveField(
- model_name='slicedeployments',
- name='slice',
- ),
- migrations.RemoveField(
- model_name='userdeployments',
- name='deployment',
- ),
- migrations.RemoveField(
- model_name='userdeployments',
- name='user',
- ),
migrations.AlterField(
model_name='deploymentcredential',
name='deployment',
@@ -143,9 +34,14 @@
field=models.ForeignKey(related_name=b'deploymentprivileges', to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
- model_name='network',
- name='ports',
- field=models.CharField(blank=True, max_length=1024, null=True, validators=[core.models.network.ValidateNatList]),
+ model_name='imagedeployments',
+ name='deployment',
+ field=models.ForeignKey(related_name=b'imagedeployments', to='core.Deployment'),
+ ),
+ migrations.AlterField(
+ model_name='imagedeployments',
+ name='image',
+ field=models.ForeignKey(related_name=b'imagedeployments', to='core.Image'),
),
migrations.AlterField(
model_name='networkdeployments',
@@ -213,16 +109,21 @@
field=models.ForeignKey(related_name=b'serviceresources', to='core.ServiceClass'),
),
migrations.AlterField(
- model_name='site',
- name='deployments',
- field=models.ManyToManyField(help_text=b'Select which sites are allowed to host nodes in this deployment', related_name=b'sites', through='core.SiteDeployment', to=b'core.Deployment', blank=True),
- ),
- migrations.AlterField(
model_name='sitecredential',
name='site',
field=models.ForeignKey(related_name=b'sitecredentials', to='core.Site', help_text=b'The User this credential is associated with'),
),
migrations.AlterField(
+ model_name='sitedeployments',
+ name='deployment',
+ field=models.ForeignKey(related_name=b'sitedeployments', to='core.Deployment'),
+ ),
+ migrations.AlterField(
+ model_name='sitedeployments',
+ name='site',
+ field=models.ForeignKey(related_name=b'sitedeployments', to='core.Site'),
+ ),
+ migrations.AlterField(
model_name='siteprivilege',
name='role',
field=models.ForeignKey(related_name=b'siteprivileges', to='core.SiteRole'),
@@ -243,6 +144,16 @@
field=models.ForeignKey(related_name=b'slicecredentials', to='core.Slice', help_text=b'The User this credential is associated with'),
),
migrations.AlterField(
+ model_name='slicedeployments',
+ name='deployment',
+ field=models.ForeignKey(related_name=b'slicedeployments', to='core.Deployment'),
+ ),
+ migrations.AlterField(
+ model_name='slicedeployments',
+ name='slice',
+ field=models.ForeignKey(related_name=b'slicedeployments', to='core.Slice'),
+ ),
+ migrations.AlterField(
model_name='sliceprivilege',
name='role',
field=models.ForeignKey(related_name=b'sliceprivileges', to='core.SliceRole'),
@@ -260,7 +171,7 @@
migrations.AlterField(
model_name='user',
name='timezone',
- field=timezones.fields.TimeZoneField(default=b'America/New_York', max_length=100, choices=[(b'Pacific/Midway', b'(GMT-1100) Pacific/Midway'), (b'Pacific/Niue', b'(GMT-1100) Pacific/Niue'), (b'Pacific/Pago_Pago', b'(GMT-1100) Pacific/Pago_Pago'), (b'America/Adak', b'(GMT-1000) America/Adak'), (b'Pacific/Honolulu', b'(GMT-1000) Pacific/Honolulu'), (b'Pacific/Johnston', b'(GMT-1000) Pacific/Johnston'), (b'Pacific/Rarotonga', b'(GMT-1000) Pacific/Rarotonga'), (b'Pacific/Tahiti', b'(GMT-1000) Pacific/Tahiti'), (b'US/Hawaii', b'(GMT-1000) US/Hawaii'), (b'Pacific/Marquesas', b'(GMT-0930) Pacific/Marquesas'), (b'America/Anchorage', b'(GMT-0900) America/Anchorage'), (b'America/Juneau', b'(GMT-0900) America/Juneau'), (b'America/Nome', b'(GMT-0900) America/Nome'), (b'America/Sitka', b'(GMT-0900) America/Sitka'), (b'America/Yakutat', b'(GMT-0900) America/Yakutat'), (b'Pacific/Gambier', b'(GMT-0900) Pacific/Gambier'), (b'US/Alaska', b'(GMT-0900) US/Alaska'), (b'America/Dawson', b'(GMT-0800) America/Dawson'), (b'America/Los_Angeles', b'(GMT-0800) America/Los_Angeles'), (b'America/Metlakatla', b'(GMT-0800) America/Metlakatla'), (b'America/Santa_Isabel', b'(GMT-0800) America/Santa_Isabel'), (b'America/Tijuana', b'(GMT-0800) America/Tijuana'), (b'America/Vancouver', b'(GMT-0800) America/Vancouver'), (b'America/Whitehorse', b'(GMT-0800) America/Whitehorse'), (b'Pacific/Pitcairn', b'(GMT-0800) Pacific/Pitcairn'), (b'US/Pacific', b'(GMT-0800) US/Pacific'), (b'America/Boise', b'(GMT-0700) America/Boise'), (b'America/Cambridge_Bay', b'(GMT-0700) America/Cambridge_Bay'), (b'America/Chihuahua', b'(GMT-0700) America/Chihuahua'), (b'America/Creston', b'(GMT-0700) America/Creston'), (b'America/Dawson_Creek', b'(GMT-0700) America/Dawson_Creek'), (b'America/Denver', b'(GMT-0700) America/Denver'), (b'America/Edmonton', b'(GMT-0700) America/Edmonton'), (b'America/Hermosillo', b'(GMT-0700) America/Hermosillo'), (b'America/Inuvik', b'(GMT-0700) America/Inuvik'), (b'America/Mazatlan', b'(GMT-0700) America/Mazatlan'), (b'America/Ojinaga', b'(GMT-0700) America/Ojinaga'), (b'America/Phoenix', b'(GMT-0700) America/Phoenix'), (b'America/Yellowknife', b'(GMT-0700) America/Yellowknife'), (b'US/Arizona', b'(GMT-0700) US/Arizona'), (b'US/Mountain', b'(GMT-0700) US/Mountain'), (b'America/Bahia_Banderas', b'(GMT-0600) America/Bahia_Banderas'), (b'America/Belize', b'(GMT-0600) America/Belize'), (b'America/Cancun', b'(GMT-0600) America/Cancun'), (b'America/Chicago', b'(GMT-0600) America/Chicago'), (b'America/Costa_Rica', b'(GMT-0600) America/Costa_Rica'), (b'America/El_Salvador', b'(GMT-0600) America/El_Salvador'), (b'America/Guatemala', b'(GMT-0600) America/Guatemala'), (b'America/Indiana/Knox', b'(GMT-0600) America/Indiana/Knox'), (b'America/Indiana/Tell_City', b'(GMT-0600) America/Indiana/Tell_City'), (b'America/Managua', b'(GMT-0600) America/Managua'), (b'America/Matamoros', b'(GMT-0600) America/Matamoros'), (b'America/Menominee', b'(GMT-0600) America/Menominee'), (b'America/Merida', b'(GMT-0600) America/Merida'), (b'America/Mexico_City', b'(GMT-0600) America/Mexico_City'), (b'America/Monterrey', b'(GMT-0600) America/Monterrey'), (b'America/North_Dakota/Beulah', b'(GMT-0600) America/North_Dakota/Beulah'), (b'America/North_Dakota/Center', b'(GMT-0600) America/North_Dakota/Center'), (b'America/North_Dakota/New_Salem', b'(GMT-0600) America/North_Dakota/New_Salem'), (b'America/Rainy_River', b'(GMT-0600) America/Rainy_River'), (b'America/Rankin_Inlet', b'(GMT-0600) America/Rankin_Inlet'), (b'America/Regina', b'(GMT-0600) America/Regina'), (b'America/Resolute', b'(GMT-0600) America/Resolute'), (b'America/Swift_Current', b'(GMT-0600) America/Swift_Current'), (b'America/Tegucigalpa', b'(GMT-0600) America/Tegucigalpa'), (b'America/Winnipeg', b'(GMT-0600) America/Winnipeg'), (b'Pacific/Galapagos', b'(GMT-0600) Pacific/Galapagos'), (b'US/Central', b'(GMT-0600) US/Central'), (b'America/Atikokan', b'(GMT-0500) America/Atikokan'), (b'America/Bogota', b'(GMT-0500) America/Bogota'), (b'America/Cayman', b'(GMT-0500) America/Cayman'), (b'America/Detroit', b'(GMT-0500) America/Detroit'), (b'America/Eirunepe', b'(GMT-0500) America/Eirunepe'), (b'America/Guayaquil', b'(GMT-0500) America/Guayaquil'), (b'America/Havana', b'(GMT-0500) America/Havana'), (b'America/Indiana/Indianapolis', b'(GMT-0500) America/Indiana/Indianapolis'), (b'America/Indiana/Marengo', b'(GMT-0500) America/Indiana/Marengo'), (b'America/Indiana/Petersburg', b'(GMT-0500) America/Indiana/Petersburg'), (b'America/Indiana/Vevay', b'(GMT-0500) America/Indiana/Vevay'), (b'America/Indiana/Vincennes', b'(GMT-0500) America/Indiana/Vincennes'), (b'America/Indiana/Winamac', b'(GMT-0500) America/Indiana/Winamac'), (b'America/Iqaluit', b'(GMT-0500) America/Iqaluit'), (b'America/Jamaica', b'(GMT-0500) America/Jamaica'), (b'America/Kentucky/Louisville', b'(GMT-0500) America/Kentucky/Louisville'), (b'America/Kentucky/Monticello', b'(GMT-0500) America/Kentucky/Monticello'), (b'America/Lima', b'(GMT-0500) America/Lima'), (b'America/Nassau', b'(GMT-0500) America/Nassau'), (b'America/New_York', b'(GMT-0500) America/New_York'), (b'America/Nipigon', b'(GMT-0500) America/Nipigon'), (b'America/Panama', b'(GMT-0500) America/Panama'), (b'America/Pangnirtung', b'(GMT-0500) America/Pangnirtung'), (b'America/Port-au-Prince', b'(GMT-0500) America/Port-au-Prince'), (b'America/Rio_Branco', b'(GMT-0500) America/Rio_Branco'), (b'America/Thunder_Bay', b'(GMT-0500) America/Thunder_Bay'), (b'America/Toronto', b'(GMT-0500) America/Toronto'), (b'Pacific/Easter', b'(GMT-0500) Pacific/Easter'), (b'US/Eastern', b'(GMT-0500) US/Eastern'), (b'America/Caracas', b'(GMT-0430) America/Caracas'), (b'America/Anguilla', b'(GMT-0400) America/Anguilla'), (b'America/Antigua', b'(GMT-0400) America/Antigua'), (b'America/Aruba', b'(GMT-0400) America/Aruba'), (b'America/Barbados', b'(GMT-0400) America/Barbados'), (b'America/Blanc-Sablon', b'(GMT-0400) America/Blanc-Sablon'), (b'America/Boa_Vista', b'(GMT-0400) America/Boa_Vista'), (b'America/Curacao', b'(GMT-0400) America/Curacao'), (b'America/Dominica', b'(GMT-0400) America/Dominica'), (b'America/Glace_Bay', b'(GMT-0400) America/Glace_Bay'), (b'America/Goose_Bay', b'(GMT-0400) America/Goose_Bay'), (b'America/Grand_Turk', b'(GMT-0400) America/Grand_Turk'), (b'America/Grenada', b'(GMT-0400) America/Grenada'), (b'America/Guadeloupe', b'(GMT-0400) America/Guadeloupe'), (b'America/Guyana', b'(GMT-0400) America/Guyana'), (b'America/Halifax', b'(GMT-0400) America/Halifax'), (b'America/Kralendijk', b'(GMT-0400) America/Kralendijk'), (b'America/La_Paz', b'(GMT-0400) America/La_Paz'), (b'America/Lower_Princes', b'(GMT-0400) America/Lower_Princes'), (b'America/Manaus', b'(GMT-0400) America/Manaus'), (b'America/Marigot', b'(GMT-0400) America/Marigot'), (b'America/Martinique', b'(GMT-0400) America/Martinique'), (b'America/Moncton', b'(GMT-0400) America/Moncton'), (b'America/Montserrat', b'(GMT-0400) America/Montserrat'), (b'America/Port_of_Spain', b'(GMT-0400) America/Port_of_Spain'), (b'America/Porto_Velho', b'(GMT-0400) America/Porto_Velho'), (b'America/Puerto_Rico', b'(GMT-0400) America/Puerto_Rico'), (b'America/Santo_Domingo', b'(GMT-0400) America/Santo_Domingo'), (b'America/St_Barthelemy', b'(GMT-0400) America/St_Barthelemy'), (b'America/St_Kitts', b'(GMT-0400) America/St_Kitts'), (b'America/St_Lucia', b'(GMT-0400) America/St_Lucia'), (b'America/St_Thomas', b'(GMT-0400) America/St_Thomas'), (b'America/St_Vincent', b'(GMT-0400) America/St_Vincent'), (b'America/Thule', b'(GMT-0400) America/Thule'), (b'America/Tortola', b'(GMT-0400) America/Tortola'), (b'Atlantic/Bermuda', b'(GMT-0400) Atlantic/Bermuda'), (b'America/St_Johns', b'(GMT-0330) America/St_Johns'), (b'America/Araguaina', b'(GMT-0300) America/Araguaina'), (b'America/Argentina/Buenos_Aires', b'(GMT-0300) America/Argentina/Buenos_Aires'), (b'America/Argentina/Catamarca', b'(GMT-0300) America/Argentina/Catamarca'), (b'America/Argentina/Cordoba', b'(GMT-0300) America/Argentina/Cordoba'), (b'America/Argentina/Jujuy', b'(GMT-0300) America/Argentina/Jujuy'), (b'America/Argentina/La_Rioja', b'(GMT-0300) America/Argentina/La_Rioja'), (b'America/Argentina/Mendoza', b'(GMT-0300) America/Argentina/Mendoza'), (b'America/Argentina/Rio_Gallegos', b'(GMT-0300) America/Argentina/Rio_Gallegos'), (b'America/Argentina/Salta', b'(GMT-0300) America/Argentina/Salta'), (b'America/Argentina/San_Juan', b'(GMT-0300) America/Argentina/San_Juan'), (b'America/Argentina/San_Luis', b'(GMT-0300) America/Argentina/San_Luis'), (b'America/Argentina/Tucuman', b'(GMT-0300) America/Argentina/Tucuman'), (b'America/Argentina/Ushuaia', b'(GMT-0300) America/Argentina/Ushuaia'), (b'America/Asuncion', b'(GMT-0300) America/Asuncion'), (b'America/Bahia', b'(GMT-0300) America/Bahia'), (b'America/Belem', b'(GMT-0300) America/Belem'), (b'America/Campo_Grande', b'(GMT-0300) America/Campo_Grande'), (b'America/Cayenne', b'(GMT-0300) America/Cayenne'), (b'America/Cuiaba', b'(GMT-0300) America/Cuiaba'), (b'America/Fortaleza', b'(GMT-0300) America/Fortaleza'), (b'America/Godthab', b'(GMT-0300) America/Godthab'), (b'America/Maceio', b'(GMT-0300) America/Maceio'), (b'America/Miquelon', b'(GMT-0300) America/Miquelon'), (b'America/Paramaribo', b'(GMT-0300) America/Paramaribo'), (b'America/Recife', b'(GMT-0300) America/Recife'), (b'America/Santarem', b'(GMT-0300) America/Santarem'), (b'America/Santiago', b'(GMT-0300) America/Santiago'), (b'Antarctica/Palmer', b'(GMT-0300) Antarctica/Palmer'), (b'Antarctica/Rothera', b'(GMT-0300) Antarctica/Rothera'), (b'Atlantic/Stanley', b'(GMT-0300) Atlantic/Stanley'), (b'America/Montevideo', b'(GMT-0200) America/Montevideo'), (b'America/Noronha', b'(GMT-0200) America/Noronha'), (b'America/Sao_Paulo', b'(GMT-0200) America/Sao_Paulo'), (b'Atlantic/South_Georgia', b'(GMT-0200) Atlantic/South_Georgia'), (b'America/Scoresbysund', b'(GMT-0100) America/Scoresbysund'), (b'Atlantic/Azores', b'(GMT-0100) Atlantic/Azores'), (b'Atlantic/Cape_Verde', b'(GMT-0100) Atlantic/Cape_Verde'), (b'Africa/Abidjan', b'(GMT+0000) Africa/Abidjan'), (b'Africa/Accra', b'(GMT+0000) Africa/Accra'), (b'Africa/Bamako', b'(GMT+0000) Africa/Bamako'), (b'Africa/Banjul', b'(GMT+0000) Africa/Banjul'), (b'Africa/Bissau', b'(GMT+0000) Africa/Bissau'), (b'Africa/Casablanca', b'(GMT+0000) Africa/Casablanca'), (b'Africa/Conakry', b'(GMT+0000) Africa/Conakry'), (b'Africa/Dakar', b'(GMT+0000) Africa/Dakar'), (b'Africa/El_Aaiun', b'(GMT+0000) Africa/El_Aaiun'), (b'Africa/Freetown', b'(GMT+0000) Africa/Freetown'), (b'Africa/Lome', b'(GMT+0000) Africa/Lome'), (b'Africa/Monrovia', b'(GMT+0000) Africa/Monrovia'), (b'Africa/Nouakchott', b'(GMT+0000) Africa/Nouakchott'), (b'Africa/Ouagadougou', b'(GMT+0000) Africa/Ouagadougou'), (b'Africa/Sao_Tome', b'(GMT+0000) Africa/Sao_Tome'), (b'America/Danmarkshavn', b'(GMT+0000) America/Danmarkshavn'), (b'Antarctica/Troll', b'(GMT+0000) Antarctica/Troll'), (b'Atlantic/Canary', b'(GMT+0000) Atlantic/Canary'), (b'Atlantic/Faroe', b'(GMT+0000) Atlantic/Faroe'), (b'Atlantic/Madeira', b'(GMT+0000) Atlantic/Madeira'), (b'Atlantic/Reykjavik', b'(GMT+0000) Atlantic/Reykjavik'), (b'Atlantic/St_Helena', b'(GMT+0000) Atlantic/St_Helena'), (b'Europe/Dublin', b'(GMT+0000) Europe/Dublin'), (b'Europe/Guernsey', b'(GMT+0000) Europe/Guernsey'), (b'Europe/Isle_of_Man', b'(GMT+0000) Europe/Isle_of_Man'), (b'Europe/Jersey', b'(GMT+0000) Europe/Jersey'), (b'Europe/Lisbon', b'(GMT+0000) Europe/Lisbon'), (b'Europe/London', b'(GMT+0000) Europe/London'), (b'GMT', b'(GMT+0000) GMT'), (b'UTC', b'(GMT+0000) UTC'), (b'Africa/Algiers', b'(GMT+0100) Africa/Algiers'), (b'Africa/Bangui', b'(GMT+0100) Africa/Bangui'), (b'Africa/Brazzaville', b'(GMT+0100) Africa/Brazzaville'), (b'Africa/Ceuta', b'(GMT+0100) Africa/Ceuta'), (b'Africa/Douala', b'(GMT+0100) Africa/Douala'), (b'Africa/Kinshasa', b'(GMT+0100) Africa/Kinshasa'), (b'Africa/Lagos', b'(GMT+0100) Africa/Lagos'), (b'Africa/Libreville', b'(GMT+0100) Africa/Libreville'), (b'Africa/Luanda', b'(GMT+0100) Africa/Luanda'), (b'Africa/Malabo', b'(GMT+0100) Africa/Malabo'), (b'Africa/Ndjamena', b'(GMT+0100) Africa/Ndjamena'), (b'Africa/Niamey', b'(GMT+0100) Africa/Niamey'), (b'Africa/Porto-Novo', b'(GMT+0100) Africa/Porto-Novo'), (b'Africa/Tunis', b'(GMT+0100) Africa/Tunis'), (b'Arctic/Longyearbyen', b'(GMT+0100) Arctic/Longyearbyen'), (b'Europe/Amsterdam', b'(GMT+0100) Europe/Amsterdam'), (b'Europe/Andorra', b'(GMT+0100) Europe/Andorra'), (b'Europe/Belgrade', b'(GMT+0100) Europe/Belgrade'), (b'Europe/Berlin', b'(GMT+0100) Europe/Berlin'), (b'Europe/Bratislava', b'(GMT+0100) Europe/Bratislava'), (b'Europe/Brussels', b'(GMT+0100) Europe/Brussels'), (b'Europe/Budapest', b'(GMT+0100) Europe/Budapest'), (b'Europe/Busingen', b'(GMT+0100) Europe/Busingen'), (b'Europe/Copenhagen', b'(GMT+0100) Europe/Copenhagen'), (b'Europe/Gibraltar', b'(GMT+0100) Europe/Gibraltar'), (b'Europe/Ljubljana', b'(GMT+0100) Europe/Ljubljana'), (b'Europe/Luxembourg', b'(GMT+0100) Europe/Luxembourg'), (b'Europe/Madrid', b'(GMT+0100) Europe/Madrid'), (b'Europe/Malta', b'(GMT+0100) Europe/Malta'), (b'Europe/Monaco', b'(GMT+0100) Europe/Monaco'), (b'Europe/Oslo', b'(GMT+0100) Europe/Oslo'), (b'Europe/Paris', b'(GMT+0100) Europe/Paris'), (b'Europe/Podgorica', b'(GMT+0100) Europe/Podgorica'), (b'Europe/Prague', b'(GMT+0100) Europe/Prague'), (b'Europe/Rome', b'(GMT+0100) Europe/Rome'), (b'Europe/San_Marino', b'(GMT+0100) Europe/San_Marino'), (b'Europe/Sarajevo', b'(GMT+0100) Europe/Sarajevo'), (b'Europe/Skopje', b'(GMT+0100) Europe/Skopje'), (b'Europe/Stockholm', b'(GMT+0100) Europe/Stockholm'), (b'Europe/Tirane', b'(GMT+0100) Europe/Tirane'), (b'Europe/Vaduz', b'(GMT+0100) Europe/Vaduz'), (b'Europe/Vatican', b'(GMT+0100) Europe/Vatican'), (b'Europe/Vienna', b'(GMT+0100) Europe/Vienna'), (b'Europe/Warsaw', b'(GMT+0100) Europe/Warsaw'), (b'Europe/Zagreb', b'(GMT+0100) Europe/Zagreb'), (b'Europe/Zurich', b'(GMT+0100) Europe/Zurich'), (b'Africa/Blantyre', b'(GMT+0200) Africa/Blantyre'), (b'Africa/Bujumbura', b'(GMT+0200) Africa/Bujumbura'), (b'Africa/Cairo', b'(GMT+0200) Africa/Cairo'), (b'Africa/Gaborone', b'(GMT+0200) Africa/Gaborone'), (b'Africa/Harare', b'(GMT+0200) Africa/Harare'), (b'Africa/Johannesburg', b'(GMT+0200) Africa/Johannesburg'), (b'Africa/Kigali', b'(GMT+0200) Africa/Kigali'), (b'Africa/Lubumbashi', b'(GMT+0200) Africa/Lubumbashi'), (b'Africa/Lusaka', b'(GMT+0200) Africa/Lusaka'), (b'Africa/Maputo', b'(GMT+0200) Africa/Maputo'), (b'Africa/Maseru', b'(GMT+0200) Africa/Maseru'), (b'Africa/Mbabane', b'(GMT+0200) Africa/Mbabane'), (b'Africa/Tripoli', b'(GMT+0200) Africa/Tripoli'), (b'Africa/Windhoek', b'(GMT+0200) Africa/Windhoek'), (b'Asia/Amman', b'(GMT+0200) Asia/Amman'), (b'Asia/Beirut', b'(GMT+0200) Asia/Beirut'), (b'Asia/Damascus', b'(GMT+0200) Asia/Damascus'), (b'Asia/Gaza', b'(GMT+0200) Asia/Gaza'), (b'Asia/Hebron', b'(GMT+0200) Asia/Hebron'), (b'Asia/Jerusalem', b'(GMT+0200) Asia/Jerusalem'), (b'Asia/Nicosia', b'(GMT+0200) Asia/Nicosia'), (b'Europe/Athens', b'(GMT+0200) Europe/Athens'), (b'Europe/Bucharest', b'(GMT+0200) Europe/Bucharest'), (b'Europe/Chisinau', b'(GMT+0200) Europe/Chisinau'), (b'Europe/Helsinki', b'(GMT+0200) Europe/Helsinki'), (b'Europe/Istanbul', b'(GMT+0200) Europe/Istanbul'), (b'Europe/Kaliningrad', b'(GMT+0200) Europe/Kaliningrad'), (b'Europe/Kiev', b'(GMT+0200) Europe/Kiev'), (b'Europe/Mariehamn', b'(GMT+0200) Europe/Mariehamn'), (b'Europe/Riga', b'(GMT+0200) Europe/Riga'), (b'Europe/Sofia', b'(GMT+0200) Europe/Sofia'), (b'Europe/Tallinn', b'(GMT+0200) Europe/Tallinn'), (b'Europe/Uzhgorod', b'(GMT+0200) Europe/Uzhgorod'), (b'Europe/Vilnius', b'(GMT+0200) Europe/Vilnius'), (b'Europe/Zaporozhye', b'(GMT+0200) Europe/Zaporozhye'), (b'Africa/Addis_Ababa', b'(GMT+0300) Africa/Addis_Ababa'), (b'Africa/Asmara', b'(GMT+0300) Africa/Asmara'), (b'Africa/Dar_es_Salaam', b'(GMT+0300) Africa/Dar_es_Salaam'), (b'Africa/Djibouti', b'(GMT+0300) Africa/Djibouti'), (b'Africa/Juba', b'(GMT+0300) Africa/Juba'), (b'Africa/Kampala', b'(GMT+0300) Africa/Kampala'), (b'Africa/Khartoum', b'(GMT+0300) Africa/Khartoum'), (b'Africa/Mogadishu', b'(GMT+0300) Africa/Mogadishu'), (b'Africa/Nairobi', b'(GMT+0300) Africa/Nairobi'), (b'Antarctica/Syowa', b'(GMT+0300) Antarctica/Syowa'), (b'Asia/Aden', b'(GMT+0300) Asia/Aden'), (b'Asia/Baghdad', b'(GMT+0300) Asia/Baghdad'), (b'Asia/Bahrain', b'(GMT+0300) Asia/Bahrain'), (b'Asia/Kuwait', b'(GMT+0300) Asia/Kuwait'), (b'Asia/Qatar', b'(GMT+0300) Asia/Qatar'), (b'Asia/Riyadh', b'(GMT+0300) Asia/Riyadh'), (b'Europe/Minsk', b'(GMT+0300) Europe/Minsk'), (b'Europe/Moscow', b'(GMT+0300) Europe/Moscow'), (b'Europe/Simferopol', b'(GMT+0300) Europe/Simferopol'), (b'Europe/Volgograd', b'(GMT+0300) Europe/Volgograd'), (b'Indian/Antananarivo', b'(GMT+0300) Indian/Antananarivo'), (b'Indian/Comoro', b'(GMT+0300) Indian/Comoro'), (b'Indian/Mayotte', b'(GMT+0300) Indian/Mayotte'), (b'Asia/Tehran', b'(GMT+0330) Asia/Tehran'), (b'Asia/Baku', b'(GMT+0400) Asia/Baku'), (b'Asia/Dubai', b'(GMT+0400) Asia/Dubai'), (b'Asia/Muscat', b'(GMT+0400) Asia/Muscat'), (b'Asia/Tbilisi', b'(GMT+0400) Asia/Tbilisi'), (b'Asia/Yerevan', b'(GMT+0400) Asia/Yerevan'), (b'Europe/Samara', b'(GMT+0400) Europe/Samara'), (b'Indian/Mahe', b'(GMT+0400) Indian/Mahe'), (b'Indian/Mauritius', b'(GMT+0400) Indian/Mauritius'), (b'Indian/Reunion', b'(GMT+0400) Indian/Reunion'), (b'Asia/Kabul', b'(GMT+0430) Asia/Kabul'), (b'Antarctica/Mawson', b'(GMT+0500) Antarctica/Mawson'), (b'Asia/Aqtau', b'(GMT+0500) Asia/Aqtau'), (b'Asia/Aqtobe', b'(GMT+0500) Asia/Aqtobe'), (b'Asia/Ashgabat', b'(GMT+0500) Asia/Ashgabat'), (b'Asia/Dushanbe', b'(GMT+0500) Asia/Dushanbe'), (b'Asia/Karachi', b'(GMT+0500) Asia/Karachi'), (b'Asia/Oral', b'(GMT+0500) Asia/Oral'), (b'Asia/Samarkand', b'(GMT+0500) Asia/Samarkand'), (b'Asia/Tashkent', b'(GMT+0500) Asia/Tashkent'), (b'Asia/Yekaterinburg', b'(GMT+0500) Asia/Yekaterinburg'), (b'Indian/Kerguelen', b'(GMT+0500) Indian/Kerguelen'), (b'Indian/Maldives', b'(GMT+0500) Indian/Maldives'), (b'Asia/Colombo', b'(GMT+0530) Asia/Colombo'), (b'Asia/Kolkata', b'(GMT+0530) Asia/Kolkata'), (b'Asia/Kathmandu', b'(GMT+0545) Asia/Kathmandu'), (b'Antarctica/Vostok', b'(GMT+0600) Antarctica/Vostok'), (b'Asia/Almaty', b'(GMT+0600) Asia/Almaty'), (b'Asia/Bishkek', b'(GMT+0600) Asia/Bishkek'), (b'Asia/Dhaka', b'(GMT+0600) Asia/Dhaka'), (b'Asia/Novosibirsk', b'(GMT+0600) Asia/Novosibirsk'), (b'Asia/Omsk', b'(GMT+0600) Asia/Omsk'), (b'Asia/Qyzylorda', b'(GMT+0600) Asia/Qyzylorda'), (b'Asia/Thimphu', b'(GMT+0600) Asia/Thimphu'), (b'Asia/Urumqi', b'(GMT+0600) Asia/Urumqi'), (b'Indian/Chagos', b'(GMT+0600) Indian/Chagos'), (b'Asia/Rangoon', b'(GMT+0630) Asia/Rangoon'), (b'Indian/Cocos', b'(GMT+0630) Indian/Cocos'), (b'Antarctica/Davis', b'(GMT+0700) Antarctica/Davis'), (b'Asia/Bangkok', b'(GMT+0700) Asia/Bangkok'), (b'Asia/Ho_Chi_Minh', b'(GMT+0700) Asia/Ho_Chi_Minh'), (b'Asia/Hovd', b'(GMT+0700) Asia/Hovd'), (b'Asia/Jakarta', b'(GMT+0700) Asia/Jakarta'), (b'Asia/Krasnoyarsk', b'(GMT+0700) Asia/Krasnoyarsk'), (b'Asia/Novokuznetsk', b'(GMT+0700) Asia/Novokuznetsk'), (b'Asia/Phnom_Penh', b'(GMT+0700) Asia/Phnom_Penh'), (b'Asia/Pontianak', b'(GMT+0700) Asia/Pontianak'), (b'Asia/Vientiane', b'(GMT+0700) Asia/Vientiane'), (b'Indian/Christmas', b'(GMT+0700) Indian/Christmas'), (b'Antarctica/Casey', b'(GMT+0800) Antarctica/Casey'), (b'Asia/Brunei', b'(GMT+0800) Asia/Brunei'), (b'Asia/Chita', b'(GMT+0800) Asia/Chita'), (b'Asia/Choibalsan', b'(GMT+0800) Asia/Choibalsan'), (b'Asia/Hong_Kong', b'(GMT+0800) Asia/Hong_Kong'), (b'Asia/Irkutsk', b'(GMT+0800) Asia/Irkutsk'), (b'Asia/Kuala_Lumpur', b'(GMT+0800) Asia/Kuala_Lumpur'), (b'Asia/Kuching', b'(GMT+0800) Asia/Kuching'), (b'Asia/Macau', b'(GMT+0800) Asia/Macau'), (b'Asia/Makassar', b'(GMT+0800) Asia/Makassar'), (b'Asia/Manila', b'(GMT+0800) Asia/Manila'), (b'Asia/Shanghai', b'(GMT+0800) Asia/Shanghai'), (b'Asia/Singapore', b'(GMT+0800) Asia/Singapore'), (b'Asia/Taipei', b'(GMT+0800) Asia/Taipei'), (b'Asia/Ulaanbaatar', b'(GMT+0800) Asia/Ulaanbaatar'), (b'Australia/Perth', b'(GMT+0800) Australia/Perth'), (b'Australia/Eucla', b'(GMT+0845) Australia/Eucla'), (b'Asia/Dili', b'(GMT+0900) Asia/Dili'), (b'Asia/Jayapura', b'(GMT+0900) Asia/Jayapura'), (b'Asia/Khandyga', b'(GMT+0900) Asia/Khandyga'), (b'Asia/Pyongyang', b'(GMT+0900) Asia/Pyongyang'), (b'Asia/Seoul', b'(GMT+0900) Asia/Seoul'), (b'Asia/Tokyo', b'(GMT+0900) Asia/Tokyo'), (b'Asia/Yakutsk', b'(GMT+0900) Asia/Yakutsk'), (b'Pacific/Palau', b'(GMT+0900) Pacific/Palau'), (b'Australia/Darwin', b'(GMT+0930) Australia/Darwin'), (b'Antarctica/DumontDUrville', b'(GMT+1000) Antarctica/DumontDUrville'), (b'Asia/Magadan', b'(GMT+1000) Asia/Magadan'), (b'Asia/Sakhalin', b'(GMT+1000) Asia/Sakhalin'), (b'Asia/Ust-Nera', b'(GMT+1000) Asia/Ust-Nera'), (b'Asia/Vladivostok', b'(GMT+1000) Asia/Vladivostok'), (b'Australia/Brisbane', b'(GMT+1000) Australia/Brisbane'), (b'Australia/Lindeman', b'(GMT+1000) Australia/Lindeman'), (b'Pacific/Chuuk', b'(GMT+1000) Pacific/Chuuk'), (b'Pacific/Guam', b'(GMT+1000) Pacific/Guam'), (b'Pacific/Port_Moresby', b'(GMT+1000) Pacific/Port_Moresby'), (b'Pacific/Saipan', b'(GMT+1000) Pacific/Saipan'), (b'Australia/Adelaide', b'(GMT+1030) Australia/Adelaide'), (b'Australia/Broken_Hill', b'(GMT+1030) Australia/Broken_Hill'), (b'Antarctica/Macquarie', b'(GMT+1100) Antarctica/Macquarie'), (b'Asia/Srednekolymsk', b'(GMT+1100) Asia/Srednekolymsk'), (b'Australia/Currie', b'(GMT+1100) Australia/Currie'), (b'Australia/Hobart', b'(GMT+1100) Australia/Hobart'), (b'Australia/Lord_Howe', b'(GMT+1100) Australia/Lord_Howe'), (b'Australia/Melbourne', b'(GMT+1100) Australia/Melbourne'), (b'Australia/Sydney', b'(GMT+1100) Australia/Sydney'), (b'Pacific/Efate', b'(GMT+1100) Pacific/Efate'), (b'Pacific/Guadalcanal', b'(GMT+1100) Pacific/Guadalcanal'), (b'Pacific/Kosrae', b'(GMT+1100) Pacific/Kosrae'), (b'Pacific/Noumea', b'(GMT+1100) Pacific/Noumea'), (b'Pacific/Pohnpei', b'(GMT+1100) Pacific/Pohnpei'), (b'Pacific/Norfolk', b'(GMT+1130) Pacific/Norfolk'), (b'Asia/Anadyr', b'(GMT+1200) Asia/Anadyr'), (b'Asia/Kamchatka', b'(GMT+1200) Asia/Kamchatka'), (b'Pacific/Funafuti', b'(GMT+1200) Pacific/Funafuti'), (b'Pacific/Kwajalein', b'(GMT+1200) Pacific/Kwajalein'), (b'Pacific/Majuro', b'(GMT+1200) Pacific/Majuro'), (b'Pacific/Nauru', b'(GMT+1200) Pacific/Nauru'), (b'Pacific/Tarawa', b'(GMT+1200) Pacific/Tarawa'), (b'Pacific/Wake', b'(GMT+1200) Pacific/Wake'), (b'Pacific/Wallis', b'(GMT+1200) Pacific/Wallis'), (b'Antarctica/McMurdo', b'(GMT+1300) Antarctica/McMurdo'), (b'Pacific/Auckland', b'(GMT+1300) Pacific/Auckland'), (b'Pacific/Enderbury', b'(GMT+1300) Pacific/Enderbury'), (b'Pacific/Fakaofo', b'(GMT+1300) Pacific/Fakaofo'), (b'Pacific/Fiji', b'(GMT+1300) Pacific/Fiji'), (b'Pacific/Tongatapu', b'(GMT+1300) Pacific/Tongatapu'), (b'Pacific/Chatham', b'(GMT+1345) Pacific/Chatham'), (b'Pacific/Apia', b'(GMT+1400) Pacific/Apia'), (b'Pacific/Kiritimati', b'(GMT+1400) Pacific/Kiritimati')]),
+ field=timezones.fields.TimeZoneField(default=b'America/New_York', max_length=100, choices=[(b'Pacific/Midway', b'(GMT-1100) Pacific/Midway'), (b'Pacific/Niue', b'(GMT-1100) Pacific/Niue'), (b'Pacific/Pago_Pago', b'(GMT-1100) Pacific/Pago_Pago'), (b'America/Adak', b'(GMT-1000) America/Adak'), (b'Pacific/Honolulu', b'(GMT-1000) Pacific/Honolulu'), (b'Pacific/Johnston', b'(GMT-1000) Pacific/Johnston'), (b'Pacific/Rarotonga', b'(GMT-1000) Pacific/Rarotonga'), (b'Pacific/Tahiti', b'(GMT-1000) Pacific/Tahiti'), (b'US/Hawaii', b'(GMT-1000) US/Hawaii'), (b'Pacific/Marquesas', b'(GMT-0930) Pacific/Marquesas'), (b'America/Anchorage', b'(GMT-0900) America/Anchorage'), (b'America/Juneau', b'(GMT-0900) America/Juneau'), (b'America/Nome', b'(GMT-0900) America/Nome'), (b'America/Sitka', b'(GMT-0900) America/Sitka'), (b'America/Yakutat', b'(GMT-0900) America/Yakutat'), (b'Pacific/Gambier', b'(GMT-0900) Pacific/Gambier'), (b'US/Alaska', b'(GMT-0900) US/Alaska'), (b'America/Dawson', b'(GMT-0800) America/Dawson'), (b'America/Los_Angeles', b'(GMT-0800) America/Los_Angeles'), (b'America/Metlakatla', b'(GMT-0800) America/Metlakatla'), (b'America/Santa_Isabel', b'(GMT-0800) America/Santa_Isabel'), (b'America/Tijuana', b'(GMT-0800) America/Tijuana'), (b'America/Vancouver', b'(GMT-0800) America/Vancouver'), (b'America/Whitehorse', b'(GMT-0800) America/Whitehorse'), (b'Pacific/Pitcairn', b'(GMT-0800) Pacific/Pitcairn'), (b'US/Pacific', b'(GMT-0800) US/Pacific'), (b'America/Boise', b'(GMT-0700) America/Boise'), (b'America/Cambridge_Bay', b'(GMT-0700) America/Cambridge_Bay'), (b'America/Chihuahua', b'(GMT-0700) America/Chihuahua'), (b'America/Creston', b'(GMT-0700) America/Creston'), (b'America/Dawson_Creek', b'(GMT-0700) America/Dawson_Creek'), (b'America/Denver', b'(GMT-0700) America/Denver'), (b'America/Edmonton', b'(GMT-0700) America/Edmonton'), (b'America/Hermosillo', b'(GMT-0700) America/Hermosillo'), (b'America/Inuvik', b'(GMT-0700) America/Inuvik'), (b'America/Mazatlan', b'(GMT-0700) America/Mazatlan'), (b'America/Ojinaga', b'(GMT-0700) America/Ojinaga'), (b'America/Phoenix', b'(GMT-0700) America/Phoenix'), (b'America/Yellowknife', b'(GMT-0700) America/Yellowknife'), (b'US/Arizona', b'(GMT-0700) US/Arizona'), (b'US/Mountain', b'(GMT-0700) US/Mountain'), (b'America/Bahia_Banderas', b'(GMT-0600) America/Bahia_Banderas'), (b'America/Belize', b'(GMT-0600) America/Belize'), (b'America/Cancun', b'(GMT-0600) America/Cancun'), (b'America/Chicago', b'(GMT-0600) America/Chicago'), (b'America/Costa_Rica', b'(GMT-0600) America/Costa_Rica'), (b'America/El_Salvador', b'(GMT-0600) America/El_Salvador'), (b'America/Guatemala', b'(GMT-0600) America/Guatemala'), (b'America/Indiana/Knox', b'(GMT-0600) America/Indiana/Knox'), (b'America/Indiana/Tell_City', b'(GMT-0600) America/Indiana/Tell_City'), (b'America/Managua', b'(GMT-0600) America/Managua'), (b'America/Matamoros', b'(GMT-0600) America/Matamoros'), (b'America/Menominee', b'(GMT-0600) America/Menominee'), (b'America/Merida', b'(GMT-0600) America/Merida'), (b'America/Mexico_City', b'(GMT-0600) America/Mexico_City'), (b'America/Monterrey', b'(GMT-0600) America/Monterrey'), (b'America/North_Dakota/Beulah', b'(GMT-0600) America/North_Dakota/Beulah'), (b'America/North_Dakota/Center', b'(GMT-0600) America/North_Dakota/Center'), (b'America/North_Dakota/New_Salem', b'(GMT-0600) America/North_Dakota/New_Salem'), (b'America/Rainy_River', b'(GMT-0600) America/Rainy_River'), (b'America/Rankin_Inlet', b'(GMT-0600) America/Rankin_Inlet'), (b'America/Regina', b'(GMT-0600) America/Regina'), (b'America/Resolute', b'(GMT-0600) America/Resolute'), (b'America/Swift_Current', b'(GMT-0600) America/Swift_Current'), (b'America/Tegucigalpa', b'(GMT-0600) America/Tegucigalpa'), (b'America/Winnipeg', b'(GMT-0600) America/Winnipeg'), (b'Pacific/Galapagos', b'(GMT-0600) Pacific/Galapagos'), (b'US/Central', b'(GMT-0600) US/Central'), (b'America/Atikokan', b'(GMT-0500) America/Atikokan'), (b'America/Bogota', b'(GMT-0500) America/Bogota'), (b'America/Cayman', b'(GMT-0500) America/Cayman'), (b'America/Detroit', b'(GMT-0500) America/Detroit'), (b'America/Eirunepe', b'(GMT-0500) America/Eirunepe'), (b'America/Guayaquil', b'(GMT-0500) America/Guayaquil'), (b'America/Havana', b'(GMT-0500) America/Havana'), (b'America/Indiana/Indianapolis', b'(GMT-0500) America/Indiana/Indianapolis'), (b'America/Indiana/Marengo', b'(GMT-0500) America/Indiana/Marengo'), (b'America/Indiana/Petersburg', b'(GMT-0500) America/Indiana/Petersburg'), (b'America/Indiana/Vevay', b'(GMT-0500) America/Indiana/Vevay'), (b'America/Indiana/Vincennes', b'(GMT-0500) America/Indiana/Vincennes'), (b'America/Indiana/Winamac', b'(GMT-0500) America/Indiana/Winamac'), (b'America/Iqaluit', b'(GMT-0500) America/Iqaluit'), (b'America/Jamaica', b'(GMT-0500) America/Jamaica'), (b'America/Kentucky/Louisville', b'(GMT-0500) America/Kentucky/Louisville'), (b'America/Kentucky/Monticello', b'(GMT-0500) America/Kentucky/Monticello'), (b'America/Lima', b'(GMT-0500) America/Lima'), (b'America/Nassau', b'(GMT-0500) America/Nassau'), (b'America/New_York', b'(GMT-0500) America/New_York'), (b'America/Nipigon', b'(GMT-0500) America/Nipigon'), (b'America/Panama', b'(GMT-0500) America/Panama'), (b'America/Pangnirtung', b'(GMT-0500) America/Pangnirtung'), (b'America/Port-au-Prince', b'(GMT-0500) America/Port-au-Prince'), (b'America/Rio_Branco', b'(GMT-0500) America/Rio_Branco'), (b'America/Thunder_Bay', b'(GMT-0500) America/Thunder_Bay'), (b'America/Toronto', b'(GMT-0500) America/Toronto'), (b'Pacific/Easter', b'(GMT-0500) Pacific/Easter'), (b'US/Eastern', b'(GMT-0500) US/Eastern'), (b'America/Caracas', b'(GMT-0430) America/Caracas'), (b'America/Anguilla', b'(GMT-0400) America/Anguilla'), (b'America/Antigua', b'(GMT-0400) America/Antigua'), (b'America/Aruba', b'(GMT-0400) America/Aruba'), (b'America/Barbados', b'(GMT-0400) America/Barbados'), (b'America/Blanc-Sablon', b'(GMT-0400) America/Blanc-Sablon'), (b'America/Boa_Vista', b'(GMT-0400) America/Boa_Vista'), (b'America/Curacao', b'(GMT-0400) America/Curacao'), (b'America/Dominica', b'(GMT-0400) America/Dominica'), (b'America/Glace_Bay', b'(GMT-0400) America/Glace_Bay'), (b'America/Goose_Bay', b'(GMT-0400) America/Goose_Bay'), (b'America/Grand_Turk', b'(GMT-0400) America/Grand_Turk'), (b'America/Grenada', b'(GMT-0400) America/Grenada'), (b'America/Guadeloupe', b'(GMT-0400) America/Guadeloupe'), (b'America/Guyana', b'(GMT-0400) America/Guyana'), (b'America/Halifax', b'(GMT-0400) America/Halifax'), (b'America/Kralendijk', b'(GMT-0400) America/Kralendijk'), (b'America/La_Paz', b'(GMT-0400) America/La_Paz'), (b'America/Lower_Princes', b'(GMT-0400) America/Lower_Princes'), (b'America/Manaus', b'(GMT-0400) America/Manaus'), (b'America/Marigot', b'(GMT-0400) America/Marigot'), (b'America/Martinique', b'(GMT-0400) America/Martinique'), (b'America/Moncton', b'(GMT-0400) America/Moncton'), (b'America/Montserrat', b'(GMT-0400) America/Montserrat'), (b'America/Port_of_Spain', b'(GMT-0400) America/Port_of_Spain'), (b'America/Porto_Velho', b'(GMT-0400) America/Porto_Velho'), (b'America/Puerto_Rico', b'(GMT-0400) America/Puerto_Rico'), (b'America/Santo_Domingo', b'(GMT-0400) America/Santo_Domingo'), (b'America/St_Barthelemy', b'(GMT-0400) America/St_Barthelemy'), (b'America/St_Kitts', b'(GMT-0400) America/St_Kitts'), (b'America/St_Lucia', b'(GMT-0400) America/St_Lucia'), (b'America/St_Thomas', b'(GMT-0400) America/St_Thomas'), (b'America/St_Vincent', b'(GMT-0400) America/St_Vincent'), (b'America/Thule', b'(GMT-0400) America/Thule'), (b'America/Tortola', b'(GMT-0400) America/Tortola'), (b'Atlantic/Bermuda', b'(GMT-0400) Atlantic/Bermuda'), (b'America/St_Johns', b'(GMT-0330) America/St_Johns'), (b'America/Araguaina', b'(GMT-0300) America/Araguaina'), (b'America/Argentina/Buenos_Aires', b'(GMT-0300) America/Argentina/Buenos_Aires'), (b'America/Argentina/Catamarca', b'(GMT-0300) America/Argentina/Catamarca'), (b'America/Argentina/Cordoba', b'(GMT-0300) America/Argentina/Cordoba'), (b'America/Argentina/Jujuy', b'(GMT-0300) America/Argentina/Jujuy'), (b'America/Argentina/La_Rioja', b'(GMT-0300) America/Argentina/La_Rioja'), (b'America/Argentina/Mendoza', b'(GMT-0300) America/Argentina/Mendoza'), (b'America/Argentina/Rio_Gallegos', b'(GMT-0300) America/Argentina/Rio_Gallegos'), (b'America/Argentina/Salta', b'(GMT-0300) America/Argentina/Salta'), (b'America/Argentina/San_Juan', b'(GMT-0300) America/Argentina/San_Juan'), (b'America/Argentina/San_Luis', b'(GMT-0300) America/Argentina/San_Luis'), (b'America/Argentina/Tucuman', b'(GMT-0300) America/Argentina/Tucuman'), (b'America/Argentina/Ushuaia', b'(GMT-0300) America/Argentina/Ushuaia'), (b'America/Asuncion', b'(GMT-0300) America/Asuncion'), (b'America/Bahia', b'(GMT-0300) America/Bahia'), (b'America/Belem', b'(GMT-0300) America/Belem'), (b'America/Campo_Grande', b'(GMT-0300) America/Campo_Grande'), (b'America/Cayenne', b'(GMT-0300) America/Cayenne'), (b'America/Cuiaba', b'(GMT-0300) America/Cuiaba'), (b'America/Fortaleza', b'(GMT-0300) America/Fortaleza'), (b'America/Godthab', b'(GMT-0300) America/Godthab'), (b'America/Maceio', b'(GMT-0300) America/Maceio'), (b'America/Miquelon', b'(GMT-0300) America/Miquelon'), (b'America/Paramaribo', b'(GMT-0300) America/Paramaribo'), (b'America/Recife', b'(GMT-0300) America/Recife'), (b'America/Santarem', b'(GMT-0300) America/Santarem'), (b'America/Santiago', b'(GMT-0300) America/Santiago'), (b'Antarctica/Palmer', b'(GMT-0300) Antarctica/Palmer'), (b'Antarctica/Rothera', b'(GMT-0300) Antarctica/Rothera'), (b'Atlantic/Stanley', b'(GMT-0300) Atlantic/Stanley'), (b'America/Montevideo', b'(GMT-0200) America/Montevideo'), (b'America/Noronha', b'(GMT-0200) America/Noronha'), (b'America/Sao_Paulo', b'(GMT-0200) America/Sao_Paulo'), (b'Atlantic/South_Georgia', b'(GMT-0200) Atlantic/South_Georgia'), (b'America/Scoresbysund', b'(GMT-0100) America/Scoresbysund'), (b'Atlantic/Azores', b'(GMT-0100) Atlantic/Azores'), (b'Atlantic/Cape_Verde', b'(GMT-0100) Atlantic/Cape_Verde'), (b'Africa/Abidjan', b'(GMT+0000) Africa/Abidjan'), (b'Africa/Accra', b'(GMT+0000) Africa/Accra'), (b'Africa/Bamako', b'(GMT+0000) Africa/Bamako'), (b'Africa/Banjul', b'(GMT+0000) Africa/Banjul'), (b'Africa/Bissau', b'(GMT+0000) Africa/Bissau'), (b'Africa/Casablanca', b'(GMT+0000) Africa/Casablanca'), (b'Africa/Conakry', b'(GMT+0000) Africa/Conakry'), (b'Africa/Dakar', b'(GMT+0000) Africa/Dakar'), (b'Africa/El_Aaiun', b'(GMT+0000) Africa/El_Aaiun'), (b'Africa/Freetown', b'(GMT+0000) Africa/Freetown'), (b'Africa/Lome', b'(GMT+0000) Africa/Lome'), (b'Africa/Monrovia', b'(GMT+0000) Africa/Monrovia'), (b'Africa/Nouakchott', b'(GMT+0000) Africa/Nouakchott'), (b'Africa/Ouagadougou', b'(GMT+0000) Africa/Ouagadougou'), (b'Africa/Sao_Tome', b'(GMT+0000) Africa/Sao_Tome'), (b'America/Danmarkshavn', b'(GMT+0000) America/Danmarkshavn'), (b'Antarctica/Troll', b'(GMT+0000) Antarctica/Troll'), (b'Atlantic/Canary', b'(GMT+0000) Atlantic/Canary'), (b'Atlantic/Faroe', b'(GMT+0000) Atlantic/Faroe'), (b'Atlantic/Madeira', b'(GMT+0000) Atlantic/Madeira'), (b'Atlantic/Reykjavik', b'(GMT+0000) Atlantic/Reykjavik'), (b'Atlantic/St_Helena', b'(GMT+0000) Atlantic/St_Helena'), (b'Europe/Dublin', b'(GMT+0000) Europe/Dublin'), (b'Europe/Guernsey', b'(GMT+0000) Europe/Guernsey'), (b'Europe/Isle_of_Man', b'(GMT+0000) Europe/Isle_of_Man'), (b'Europe/Jersey', b'(GMT+0000) Europe/Jersey'), (b'Europe/Lisbon', b'(GMT+0000) Europe/Lisbon'), (b'Europe/London', b'(GMT+0000) Europe/London'), (b'GMT', b'(GMT+0000) GMT'), (b'UTC', b'(GMT+0000) UTC'), (b'Africa/Algiers', b'(GMT+0100) Africa/Algiers'), (b'Africa/Bangui', b'(GMT+0100) Africa/Bangui'), (b'Africa/Brazzaville', b'(GMT+0100) Africa/Brazzaville'), (b'Africa/Ceuta', b'(GMT+0100) Africa/Ceuta'), (b'Africa/Douala', b'(GMT+0100) Africa/Douala'), (b'Africa/Kinshasa', b'(GMT+0100) Africa/Kinshasa'), (b'Africa/Lagos', b'(GMT+0100) Africa/Lagos'), (b'Africa/Libreville', b'(GMT+0100) Africa/Libreville'), (b'Africa/Luanda', b'(GMT+0100) Africa/Luanda'), (b'Africa/Malabo', b'(GMT+0100) Africa/Malabo'), (b'Africa/Ndjamena', b'(GMT+0100) Africa/Ndjamena'), (b'Africa/Niamey', b'(GMT+0100) Africa/Niamey'), (b'Africa/Porto-Novo', b'(GMT+0100) Africa/Porto-Novo'), (b'Africa/Tunis', b'(GMT+0100) Africa/Tunis'), (b'Arctic/Longyearbyen', b'(GMT+0100) Arctic/Longyearbyen'), (b'Europe/Amsterdam', b'(GMT+0100) Europe/Amsterdam'), (b'Europe/Andorra', b'(GMT+0100) Europe/Andorra'), (b'Europe/Belgrade', b'(GMT+0100) Europe/Belgrade'), (b'Europe/Berlin', b'(GMT+0100) Europe/Berlin'), (b'Europe/Bratislava', b'(GMT+0100) Europe/Bratislava'), (b'Europe/Brussels', b'(GMT+0100) Europe/Brussels'), (b'Europe/Budapest', b'(GMT+0100) Europe/Budapest'), (b'Europe/Busingen', b'(GMT+0100) Europe/Busingen'), (b'Europe/Copenhagen', b'(GMT+0100) Europe/Copenhagen'), (b'Europe/Gibraltar', b'(GMT+0100) Europe/Gibraltar'), (b'Europe/Ljubljana', b'(GMT+0100) Europe/Ljubljana'), (b'Europe/Luxembourg', b'(GMT+0100) Europe/Luxembourg'), (b'Europe/Madrid', b'(GMT+0100) Europe/Madrid'), (b'Europe/Malta', b'(GMT+0100) Europe/Malta'), (b'Europe/Monaco', b'(GMT+0100) Europe/Monaco'), (b'Europe/Oslo', b'(GMT+0100) Europe/Oslo'), (b'Europe/Paris', b'(GMT+0100) Europe/Paris'), (b'Europe/Podgorica', b'(GMT+0100) Europe/Podgorica'), (b'Europe/Prague', b'(GMT+0100) Europe/Prague'), (b'Europe/Rome', b'(GMT+0100) Europe/Rome'), (b'Europe/San_Marino', b'(GMT+0100) Europe/San_Marino'), (b'Europe/Sarajevo', b'(GMT+0100) Europe/Sarajevo'), (b'Europe/Skopje', b'(GMT+0100) Europe/Skopje'), (b'Europe/Stockholm', b'(GMT+0100) Europe/Stockholm'), (b'Europe/Tirane', b'(GMT+0100) Europe/Tirane'), (b'Europe/Vaduz', b'(GMT+0100) Europe/Vaduz'), (b'Europe/Vatican', b'(GMT+0100) Europe/Vatican'), (b'Europe/Vienna', b'(GMT+0100) Europe/Vienna'), (b'Europe/Warsaw', b'(GMT+0100) Europe/Warsaw'), (b'Europe/Zagreb', b'(GMT+0100) Europe/Zagreb'), (b'Europe/Zurich', b'(GMT+0100) Europe/Zurich'), (b'Africa/Blantyre', b'(GMT+0200) Africa/Blantyre'), (b'Africa/Bujumbura', b'(GMT+0200) Africa/Bujumbura'), (b'Africa/Cairo', b'(GMT+0200) Africa/Cairo'), (b'Africa/Gaborone', b'(GMT+0200) Africa/Gaborone'), (b'Africa/Harare', b'(GMT+0200) Africa/Harare'), (b'Africa/Johannesburg', b'(GMT+0200) Africa/Johannesburg'), (b'Africa/Kigali', b'(GMT+0200) Africa/Kigali'), (b'Africa/Lubumbashi', b'(GMT+0200) Africa/Lubumbashi'), (b'Africa/Lusaka', b'(GMT+0200) Africa/Lusaka'), (b'Africa/Maputo', b'(GMT+0200) Africa/Maputo'), (b'Africa/Maseru', b'(GMT+0200) Africa/Maseru'), (b'Africa/Mbabane', b'(GMT+0200) Africa/Mbabane'), (b'Africa/Tripoli', b'(GMT+0200) Africa/Tripoli'), (b'Africa/Windhoek', b'(GMT+0200) Africa/Windhoek'), (b'Asia/Amman', b'(GMT+0200) Asia/Amman'), (b'Asia/Beirut', b'(GMT+0200) Asia/Beirut'), (b'Asia/Damascus', b'(GMT+0200) Asia/Damascus'), (b'Asia/Gaza', b'(GMT+0200) Asia/Gaza'), (b'Asia/Hebron', b'(GMT+0200) Asia/Hebron'), (b'Asia/Jerusalem', b'(GMT+0200) Asia/Jerusalem'), (b'Asia/Nicosia', b'(GMT+0200) Asia/Nicosia'), (b'Europe/Athens', b'(GMT+0200) Europe/Athens'), (b'Europe/Bucharest', b'(GMT+0200) Europe/Bucharest'), (b'Europe/Chisinau', b'(GMT+0200) Europe/Chisinau'), (b'Europe/Helsinki', b'(GMT+0200) Europe/Helsinki'), (b'Europe/Istanbul', b'(GMT+0200) Europe/Istanbul'), (b'Europe/Kaliningrad', b'(GMT+0200) Europe/Kaliningrad'), (b'Europe/Kiev', b'(GMT+0200) Europe/Kiev'), (b'Europe/Mariehamn', b'(GMT+0200) Europe/Mariehamn'), (b'Europe/Riga', b'(GMT+0200) Europe/Riga'), (b'Europe/Sofia', b'(GMT+0200) Europe/Sofia'), (b'Europe/Tallinn', b'(GMT+0200) Europe/Tallinn'), (b'Europe/Uzhgorod', b'(GMT+0200) Europe/Uzhgorod'), (b'Europe/Vilnius', b'(GMT+0200) Europe/Vilnius'), (b'Europe/Zaporozhye', b'(GMT+0200) Europe/Zaporozhye'), (b'Africa/Addis_Ababa', b'(GMT+0300) Africa/Addis_Ababa'), (b'Africa/Asmara', b'(GMT+0300) Africa/Asmara'), (b'Africa/Dar_es_Salaam', b'(GMT+0300) Africa/Dar_es_Salaam'), (b'Africa/Djibouti', b'(GMT+0300) Africa/Djibouti'), (b'Africa/Juba', b'(GMT+0300) Africa/Juba'), (b'Africa/Kampala', b'(GMT+0300) Africa/Kampala'), (b'Africa/Khartoum', b'(GMT+0300) Africa/Khartoum'), (b'Africa/Mogadishu', b'(GMT+0300) Africa/Mogadishu'), (b'Africa/Nairobi', b'(GMT+0300) Africa/Nairobi'), (b'Antarctica/Syowa', b'(GMT+0300) Antarctica/Syowa'), (b'Asia/Aden', b'(GMT+0300) Asia/Aden'), (b'Asia/Baghdad', b'(GMT+0300) Asia/Baghdad'), (b'Asia/Bahrain', b'(GMT+0300) Asia/Bahrain'), (b'Asia/Kuwait', b'(GMT+0300) Asia/Kuwait'), (b'Asia/Qatar', b'(GMT+0300) Asia/Qatar'), (b'Asia/Riyadh', b'(GMT+0300) Asia/Riyadh'), (b'Europe/Minsk', b'(GMT+0300) Europe/Minsk'), (b'Europe/Moscow', b'(GMT+0300) Europe/Moscow'), (b'Europe/Simferopol', b'(GMT+0300) Europe/Simferopol'), (b'Europe/Volgograd', b'(GMT+0300) Europe/Volgograd'), (b'Indian/Antananarivo', b'(GMT+0300) Indian/Antananarivo'), (b'Indian/Comoro', b'(GMT+0300) Indian/Comoro'), (b'Indian/Mayotte', b'(GMT+0300) Indian/Mayotte'), (b'Asia/Tehran', b'(GMT+0330) Asia/Tehran'), (b'Asia/Baku', b'(GMT+0400) Asia/Baku'), (b'Asia/Dubai', b'(GMT+0400) Asia/Dubai'), (b'Asia/Muscat', b'(GMT+0400) Asia/Muscat'), (b'Asia/Tbilisi', b'(GMT+0400) Asia/Tbilisi'), (b'Asia/Yerevan', b'(GMT+0400) Asia/Yerevan'), (b'Europe/Samara', b'(GMT+0400) Europe/Samara'), (b'Indian/Mahe', b'(GMT+0400) Indian/Mahe'), (b'Indian/Mauritius', b'(GMT+0400) Indian/Mauritius'), (b'Indian/Reunion', b'(GMT+0400) Indian/Reunion'), (b'Asia/Kabul', b'(GMT+0430) Asia/Kabul'), (b'Antarctica/Mawson', b'(GMT+0500) Antarctica/Mawson'), (b'Asia/Aqtau', b'(GMT+0500) Asia/Aqtau'), (b'Asia/Aqtobe', b'(GMT+0500) Asia/Aqtobe'), (b'Asia/Ashgabat', b'(GMT+0500) Asia/Ashgabat'), (b'Asia/Dushanbe', b'(GMT+0500) Asia/Dushanbe'), (b'Asia/Karachi', b'(GMT+0500) Asia/Karachi'), (b'Asia/Oral', b'(GMT+0500) Asia/Oral'), (b'Asia/Samarkand', b'(GMT+0500) Asia/Samarkand'), (b'Asia/Tashkent', b'(GMT+0500) Asia/Tashkent'), (b'Asia/Yekaterinburg', b'(GMT+0500) Asia/Yekaterinburg'), (b'Indian/Kerguelen', b'(GMT+0500) Indian/Kerguelen'), (b'Indian/Maldives', b'(GMT+0500) Indian/Maldives'), (b'Asia/Colombo', b'(GMT+0530) Asia/Colombo'), (b'Asia/Kolkata', b'(GMT+0530) Asia/Kolkata'), (b'Asia/Kathmandu', b'(GMT+0545) Asia/Kathmandu'), (b'Antarctica/Vostok', b'(GMT+0600) Antarctica/Vostok'), (b'Asia/Almaty', b'(GMT+0600) Asia/Almaty'), (b'Asia/Bishkek', b'(GMT+0600) Asia/Bishkek'), (b'Asia/Dhaka', b'(GMT+0600) Asia/Dhaka'), (b'Asia/Novosibirsk', b'(GMT+0600) Asia/Novosibirsk'), (b'Asia/Omsk', b'(GMT+0600) Asia/Omsk'), (b'Asia/Qyzylorda', b'(GMT+0600) Asia/Qyzylorda'), (b'Asia/Thimphu', b'(GMT+0600) Asia/Thimphu'), (b'Asia/Urumqi', b'(GMT+0600) Asia/Urumqi'), (b'Indian/Chagos', b'(GMT+0600) Indian/Chagos'), (b'Asia/Rangoon', b'(GMT+0630) Asia/Rangoon'), (b'Indian/Cocos', b'(GMT+0630) Indian/Cocos'), (b'Antarctica/Davis', b'(GMT+0700) Antarctica/Davis'), (b'Asia/Bangkok', b'(GMT+0700) Asia/Bangkok'), (b'Asia/Ho_Chi_Minh', b'(GMT+0700) Asia/Ho_Chi_Minh'), (b'Asia/Hovd', b'(GMT+0700) Asia/Hovd'), (b'Asia/Jakarta', b'(GMT+0700) Asia/Jakarta'), (b'Asia/Krasnoyarsk', b'(GMT+0700) Asia/Krasnoyarsk'), (b'Asia/Novokuznetsk', b'(GMT+0700) Asia/Novokuznetsk'), (b'Asia/Phnom_Penh', b'(GMT+0700) Asia/Phnom_Penh'), (b'Asia/Pontianak', b'(GMT+0700) Asia/Pontianak'), (b'Asia/Vientiane', b'(GMT+0700) Asia/Vientiane'), (b'Indian/Christmas', b'(GMT+0700) Indian/Christmas'), (b'Antarctica/Casey', b'(GMT+0800) Antarctica/Casey'), (b'Asia/Brunei', b'(GMT+0800) Asia/Brunei'), (b'Asia/Chita', b'(GMT+0800) Asia/Chita'), (b'Asia/Choibalsan', b'(GMT+0800) Asia/Choibalsan'), (b'Asia/Hong_Kong', b'(GMT+0800) Asia/Hong_Kong'), (b'Asia/Irkutsk', b'(GMT+0800) Asia/Irkutsk'), (b'Asia/Kuala_Lumpur', b'(GMT+0800) Asia/Kuala_Lumpur'), (b'Asia/Kuching', b'(GMT+0800) Asia/Kuching'), (b'Asia/Macau', b'(GMT+0800) Asia/Macau'), (b'Asia/Makassar', b'(GMT+0800) Asia/Makassar'), (b'Asia/Manila', b'(GMT+0800) Asia/Manila'), (b'Asia/Shanghai', b'(GMT+0800) Asia/Shanghai'), (b'Asia/Singapore', b'(GMT+0800) Asia/Singapore'), (b'Asia/Taipei', b'(GMT+0800) Asia/Taipei'), (b'Asia/Ulaanbaatar', b'(GMT+0800) Asia/Ulaanbaatar'), (b'Australia/Perth', b'(GMT+0800) Australia/Perth'), (b'Australia/Eucla', b'(GMT+0845) Australia/Eucla'), (b'Asia/Dili', b'(GMT+0900) Asia/Dili'), (b'Asia/Jayapura', b'(GMT+0900) Asia/Jayapura'), (b'Asia/Khandyga', b'(GMT+0900) Asia/Khandyga'), (b'Asia/Pyongyang', b'(GMT+0900) Asia/Pyongyang'), (b'Asia/Seoul', b'(GMT+0900) Asia/Seoul'), (b'Asia/Tokyo', b'(GMT+0900) Asia/Tokyo'), (b'Asia/Yakutsk', b'(GMT+0900) Asia/Yakutsk'), (b'Pacific/Palau', b'(GMT+0900) Pacific/Palau'), (b'Australia/Darwin', b'(GMT+0930) Australia/Darwin'), (b'Antarctica/DumontDUrville', b'(GMT+1000) Antarctica/DumontDUrville'), (b'Asia/Magadan', b'(GMT+1000) Asia/Magadan'), (b'Asia/Sakhalin', b'(GMT+1000) Asia/Sakhalin'), (b'Asia/Ust-Nera', b'(GMT+1000) Asia/Ust-Nera'), (b'Asia/Vladivostok', b'(GMT+1000) Asia/Vladivostok'), (b'Australia/Brisbane', b'(GMT+1000) Australia/Brisbane'), (b'Australia/Lindeman', b'(GMT+1000) Australia/Lindeman'), (b'Pacific/Bougainville', b'(GMT+1000) Pacific/Bougainville'), (b'Pacific/Chuuk', b'(GMT+1000) Pacific/Chuuk'), (b'Pacific/Guam', b'(GMT+1000) Pacific/Guam'), (b'Pacific/Port_Moresby', b'(GMT+1000) Pacific/Port_Moresby'), (b'Pacific/Saipan', b'(GMT+1000) Pacific/Saipan'), (b'Australia/Adelaide', b'(GMT+1030) Australia/Adelaide'), (b'Australia/Broken_Hill', b'(GMT+1030) Australia/Broken_Hill'), (b'Antarctica/Macquarie', b'(GMT+1100) Antarctica/Macquarie'), (b'Asia/Srednekolymsk', b'(GMT+1100) Asia/Srednekolymsk'), (b'Australia/Currie', b'(GMT+1100) Australia/Currie'), (b'Australia/Hobart', b'(GMT+1100) Australia/Hobart'), (b'Australia/Lord_Howe', b'(GMT+1100) Australia/Lord_Howe'), (b'Australia/Melbourne', b'(GMT+1100) Australia/Melbourne'), (b'Australia/Sydney', b'(GMT+1100) Australia/Sydney'), (b'Pacific/Efate', b'(GMT+1100) Pacific/Efate'), (b'Pacific/Guadalcanal', b'(GMT+1100) Pacific/Guadalcanal'), (b'Pacific/Kosrae', b'(GMT+1100) Pacific/Kosrae'), (b'Pacific/Noumea', b'(GMT+1100) Pacific/Noumea'), (b'Pacific/Pohnpei', b'(GMT+1100) Pacific/Pohnpei'), (b'Pacific/Norfolk', b'(GMT+1130) Pacific/Norfolk'), (b'Asia/Anadyr', b'(GMT+1200) Asia/Anadyr'), (b'Asia/Kamchatka', b'(GMT+1200) Asia/Kamchatka'), (b'Pacific/Funafuti', b'(GMT+1200) Pacific/Funafuti'), (b'Pacific/Kwajalein', b'(GMT+1200) Pacific/Kwajalein'), (b'Pacific/Majuro', b'(GMT+1200) Pacific/Majuro'), (b'Pacific/Nauru', b'(GMT+1200) Pacific/Nauru'), (b'Pacific/Tarawa', b'(GMT+1200) Pacific/Tarawa'), (b'Pacific/Wake', b'(GMT+1200) Pacific/Wake'), (b'Pacific/Wallis', b'(GMT+1200) Pacific/Wallis'), (b'Antarctica/McMurdo', b'(GMT+1300) Antarctica/McMurdo'), (b'Pacific/Auckland', b'(GMT+1300) Pacific/Auckland'), (b'Pacific/Enderbury', b'(GMT+1300) Pacific/Enderbury'), (b'Pacific/Fakaofo', b'(GMT+1300) Pacific/Fakaofo'), (b'Pacific/Fiji', b'(GMT+1300) Pacific/Fiji'), (b'Pacific/Tongatapu', b'(GMT+1300) Pacific/Tongatapu'), (b'Pacific/Chatham', b'(GMT+1345) Pacific/Chatham'), (b'Pacific/Apia', b'(GMT+1400) Pacific/Apia'), (b'Pacific/Kiritimati', b'(GMT+1400) Pacific/Kiritimati')]),
),
migrations.AlterField(
model_name='usercredential',
@@ -277,4 +188,14 @@
name='user',
field=models.ForeignKey(related_name=b'userdashboardviews', to=settings.AUTH_USER_MODEL),
),
+ migrations.AlterField(
+ model_name='userdeployments',
+ name='deployment',
+ field=models.ForeignKey(related_name=b'userdeployments', to='core.Deployment'),
+ ),
+ migrations.AlterField(
+ model_name='userdeployments',
+ name='user',
+ field=models.ForeignKey(related_name=b'userdeployments', to=settings.AUTH_USER_MODEL),
+ ),
]
diff --git a/planetstack/core/models/__init__.py b/planetstack/core/models/__init__.py
index 821939e..2070e16 100644
--- a/planetstack/core/models/__init__.py
+++ b/planetstack/core/models/__init__.py
@@ -5,15 +5,15 @@
from .service import ServiceAttribute
from .tag import Tag
from .role import Role
-from .site import Site,Deployment, DeploymentRole, DeploymentPrivilege, SiteDeployment
+from .site import Site,Deployment, DeploymentRole, DeploymentPrivilege, SiteDeployments
from .dashboard import DashboardView
from .user import User, UserDashboardView
from .serviceclass import ServiceClass
from .site import DeploymentLinkManager,DeploymentLinkDeletionManager
-from .slice import Slice, SliceDeployment
-from .site import SitePrivilege, SiteDeployment
-from .userdeployments import UserDeployment
-from .image import Image, ImageDeployment
+from .slice import Slice, SliceDeployments
+from .site import SitePrivilege, SiteDeployments
+from .userdeployments import UserDeployments
+from .image import Image, ImageDeployments
from .node import Node
from .serviceresource import ServiceResource
from .slice import SliceRole
diff --git a/planetstack/core/models/image.py b/planetstack/core/models/image.py
index 1bca1b9..fdeb2cc 100644
--- a/planetstack/core/models/image.py
+++ b/planetstack/core/models/image.py
@@ -14,7 +14,7 @@
def __unicode__(self): return u'%s' % (self.name)
-class ImageDeployment(PlCoreBase):
+class ImageDeployments(PlCoreBase):
objects = DeploymentLinkManager()
deleted_objects = DeploymentLinkDeletionManager()
image = models.ForeignKey(Image,related_name='imagedeployments')
diff --git a/planetstack/core/models/network.py b/planetstack/core/models/network.py
index 3c5a19b..0b3400a 100644
--- a/planetstack/core/models/network.py
+++ b/planetstack/core/models/network.py
@@ -65,6 +65,8 @@
class NetworkTemplate(PlCoreBase):
VISIBILITY_CHOICES = (('public', 'public'), ('private', 'private'))
TRANSLATION_CHOICES = (('none', 'none'), ('NAT', 'NAT'))
+ TOPOLOGY_CHOICES = (('bigswitch', 'BigSwitch'), ('physical', 'Physical'), ('custom', 'Custom'))
+ CONTROLLER_CHOICES = ((None, 'None'), ('onos', 'ONOS'), ('custom', 'Custom'))
name = models.CharField(max_length=32)
description = models.CharField(max_length=1024, blank=True, null=True)
@@ -73,6 +75,8 @@
translation = models.CharField(max_length=30, choices=TRANSLATION_CHOICES, default="none")
sharedNetworkName = models.CharField(max_length=30, blank=True, null=True)
sharedNetworkId = models.CharField(null=True, blank=True, max_length=256, help_text="Quantum network")
+ topologyKind = models.CharField(null=False, blank=False, max_length=30, choices=TOPOLOGY_CHOICES, default="BigSwitch")
+ controllerKind = models.CharField(null=True, blank=True, max_length=30, choices=CONTROLLER_CHOICES, default=None)
def __unicode__(self): return u'%s' % (self.name)
@@ -90,6 +94,10 @@
slices = models.ManyToManyField(Slice, blank=True, related_name="networks", through="NetworkSlice")
slivers = models.ManyToManyField(Sliver, blank=True, related_name="networks", through="NetworkSliver")
+ topologyParameters = models.TextField(null=True, blank=True)
+ controllerUrl = models.CharField(null=True, blank=True, max_length=1024)
+ controllerParameters = models.TextField(null=True, blank=True)
+
# for observer/manager
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")
diff --git a/planetstack/core/models/site.py b/planetstack/core/models/site.py
index 09eb786..2404e34 100644
--- a/planetstack/core/models/site.py
+++ b/planetstack/core/models/site.py
@@ -105,7 +105,7 @@
abbreviated_name = models.CharField(max_length=80)
#deployments = models.ManyToManyField('Deployment', blank=True, related_name='sites')
- deployments = models.ManyToManyField('Deployment', through='SiteDeployment', blank=True, help_text="Select which sites are allowed to host nodes in this deployment", related_name='sites')
+ deployments = models.ManyToManyField('Deployment', through='SiteDeployments', blank=True, help_text="Select which sites are allowed to host nodes in this deployment", related_name='sites')
tags = generic.GenericRelation(Tag)
def __unicode__(self): return u'%s' % (self.name)
@@ -255,7 +255,7 @@
qs = DeploymentPrivilege.objects.filter(id__in=dpriv_ids)
return qs
-class SiteDeployment(PlCoreBase):
+class SiteDeployments(PlCoreBase):
objects = DeploymentLinkManager()
deleted_objects = DeploymentLinkDeletionManager()
diff --git a/planetstack/core/models/slice.py b/planetstack/core/models/slice.py
index 24d02aa..128d605 100644
--- a/planetstack/core/models/slice.py
+++ b/planetstack/core/models/slice.py
@@ -93,7 +93,7 @@
nets = Network.objects.filter(slices=self)
nets.delete()
# delete slice deployments
- slice_deployments = SliceDeployments.objects.filter(slice=self)
+ slice_deployments = SliceDeploymentss.objects.filter(slice=self)
slice_deployments.delete()
# delete slice privilege
slice_privileges = SlicePrivilege.objects.filter(slice=self)
@@ -128,7 +128,7 @@
qs = SlicePrivilege.objects.filter(id__in=sp_ids)
return qs
-class SliceDeployment(PlCoreBase):
+class SliceDeployments(PlCoreBase):
objects = DeploymentLinkManager()
deleted_objects = DeploymentLinkDeletionManager()
@@ -144,8 +144,8 @@
@staticmethod
def select_by_user(user):
if user.is_admin:
- qs = SliceDeployment.objects.all()
+ qs = SliceDeployments.objects.all()
else:
slices = Slice.select_by_user(user)
- qs = SliceDeployment.objects.filter(slice__in=slices)
+ qs = SliceDeployments.objects.filter(slice__in=slices)
return qs
diff --git a/planetstack/core/models/userdeployments.py b/planetstack/core/models/userdeployments.py
index d0337ba..d8051bf 100644
--- a/planetstack/core/models/userdeployments.py
+++ b/planetstack/core/models/userdeployments.py
@@ -6,7 +6,7 @@
from core.models import PlCoreBase,Site,User,Deployment
from core.models import Deployment,DeploymentLinkManager,DeploymentLinkDeletionManager
-class UserDeployment(PlCoreBase):
+class UserDeployments(PlCoreBase):
objects = DeploymentLinkManager()
deleted_objects = DeploymentLinkDeletionManager()
@@ -19,7 +19,7 @@
@staticmethod
def select_by_user(user):
if user.is_admin:
- qs = UserDeployment.objects.all()
+ qs = UserDeployments.objects.all()
else:
users = Users.select_by_user(user)
qs = Usereployments.objects.filter(user__in=slices)
diff --git a/planetstack/core/static/uploadTextarea.js b/planetstack/core/static/uploadTextarea.js
new file mode 100644
index 0000000..a7f76bf
--- /dev/null
+++ b/planetstack/core/static/uploadTextarea.js
@@ -0,0 +1,19 @@
+function uploadTextarea(event,textarea_id) {
+ var input = event.target;
+
+ var reader = new FileReader();
+ //reader.onloadstart = function() {
+ // reader.abort();
+ //};
+
+ reader.onloadend = function() {
+ if (reader.error) {
+ alert(reader.error.message);
+ } else {
+ $("#" + textarea_id).val(this.result);
+ //console.log(this.result);
+ }
+ };
+
+ reader.readAsText(input.files[0]);
+};
diff --git a/planetstack/core/xoslib/dashboards/xosAdminDashboard.html b/planetstack/core/xoslib/dashboards/xosAdminDashboard.html
index 6d60535..b5dacc9 100644
--- a/planetstack/core/xoslib/dashboards/xosAdminDashboard.html
+++ b/planetstack/core/xoslib/dashboards/xosAdminDashboard.html
@@ -22,6 +22,10 @@
</tr>
</script>
+<div id="xos-confirm-dialog" title="Confirmation Required">
+ Are you sure about this?
+</div>
+
<div id="contentPanel">
<div id="contentTitle">
</div>
@@ -34,8 +38,10 @@
<button class="btn btn-high btn-info btn-xos-contentButtonPanel" onclick="$('button.btn-xos-save-leave').click()">Save</button>
<button class="btn btn-high btn-xos-contentButtonPanel" onclick="$('button.btn-xos-save-continue').click()">Save and continue editing</button>
<button class="btn btn-high btn-xos-contentButtonPanel" onclick="$('button.btn-xos-save-another').click()">Save and add another</button>
+<button class="btn btn-danger btn-xos-contentButtonPanel" onclick="$('button.btn-xos-delete').click()">Delete</button>
</div>
<div class="box save-box" id="xos-listview-button-box">
+<button class="btn btn-high btn-primary btn-xos-contentButtonPanel" onclick="$('button.btn-xos-refresh').click()">Refresh</button>
<button class="btn btn-high btn-success btn-xos-contentButtonPanel" onclick="$('button.btn-xos-add').click()">Add</button>
</div>
<div class="box" id="logPanel">
diff --git a/planetstack/core/xoslib/static/css/xosAdminSite.css b/planetstack/core/xoslib/static/css/xosAdminSite.css
index d1b4275..f09bbcf 100644
--- a/planetstack/core/xoslib/static/css/xosAdminSite.css
+++ b/planetstack/core/xoslib/static/css/xosAdminSite.css
@@ -66,6 +66,8 @@
text-decoration:none;
}
+/* these are for the inline list and detail titles */
+
.xos-list-title {
display: none;
}
@@ -74,6 +76,12 @@
display: none;
}
+/* this one goes with contenttitle */
+
+#xos-list-title-spinner {
+ display: none;
+}
+
/* undo what planetstack.css does to the progressbar */
#xos-startup-progress .ui-progressbar-value {
background-color: rgb(204,204,204) !important;
@@ -91,4 +99,6 @@
display: none;
}
-
+#xos-confirm-dialog {
+ display: none;
+}
diff --git a/planetstack/core/xoslib/static/js/xosAdminSite.js b/planetstack/core/xoslib/static/js/xosAdminSite.js
index b5d0f6c..ceb2589 100644
--- a/planetstack/core/xoslib/static/js/xosAdminSite.js
+++ b/planetstack/core/xoslib/static/js/xosAdminSite.js
@@ -26,6 +26,17 @@
XOSAdminApp.Router.navigate(detailNavLink + "/" + model.id, {trigger: true});
};
+XOSAdminApp.navigate = function(what, modelName, modelId) {
+ collection_name = modelName + "s";
+ if (what=="list") {
+ XOSAdminApp.Router.navigate(collection_name, {trigger: true})
+ } else if (what=="detail") {
+ XOSAdminApp.Router.navigate(collection_name + "/" + modelId, {trigger: true})
+ } else if (what=="add") {
+ XOSAdminApp.Router.navigate("add" + firstCharUpper(modelName), {trigger: true})
+ }
+}
+
ICON_CLASSES = {home: "icon-home", deployments: "icon-deployment", sites: "icon-site", slices: "icon-slice", users: "icon-user"};
XOSAdminApp.updateNavigationPanel = function() {
@@ -56,12 +67,10 @@
collection_name = name + "s";
region_name = name + "List";
detailNavLink = collection_name;
- listNavLink = collection_name;
detailClass = XOSDetailView.extend({
template: detail_template,
app: XOSAdminApp,
- listNavLink: listNavLink,
});
XOSAdminApp[collection_name + "DetailView"] = detailClass;
diff --git a/planetstack/core/xoslib/static/js/xoslib/xos-backbone.js b/planetstack/core/xoslib/static/js/xoslib/xos-backbone.js
index 36df6eb..f615c30 100644
--- a/planetstack/core/xoslib/static/js/xoslib/xos-backbone.js
+++ b/planetstack/core/xoslib/static/js/xoslib/xos-backbone.js
@@ -116,21 +116,27 @@
},
fetchSuccess: function(collection, response, options) {
+ //console.log("fetch succeeded " + collection.modelName);
this.failedLoad = false;
+ this.fetching = false;
if (!this.isLoaded) {
this.isLoaded = true;
Backbone.trigger("xoslib:collectionLoadChange", this);
}
+ this.trigger("fetchStateChange");
if (options["orig_success"]) {
options["orig_success"](collection, response, options);
}
},
fetchFailure: function(collection, response, options) {
+ //console.log("fetch failed " + collection.modelName);
+ this.fetching = false;
if ((!this.isLoaded) && (!this.failedLoad)) {
this.failedLoad=true;
Backbone.trigger("xoslib:collectionLoadChange", this);
}
+ this.trigger("fetchStateChange");
if (options["orig_failure"]) {
options["orig_failure"](collection, response, options);
}
@@ -138,10 +144,13 @@
fetch: function(options) {
var self=this;
+ this.fetching=true;
+ //console.log("fetch " + this.modelName);
if (!this.startedLoad) {
this.startedLoad=true;
Backbone.trigger("xoslib:collectionLoadChange", this);
}
+ this.trigger("fetchStateChange");
if (options == undefined) {
options = {};
}
@@ -161,6 +170,20 @@
}
},
+ refresh: function(refreshRelated) {
+ if (!this.fetching) {
+ this.fetch();
+ }
+ if (refreshRelated) {
+ for (related in this.relatedCollections) {
+ related = xos[related];
+ if (!related.fetching) {
+ related.fetch();
+ }
+ }
+ }
+ },
+
maybeFetch: function(options){
// Helper function to fetch only if this collection has not been fetched before.
if(this._fetched){
diff --git a/planetstack/core/xoslib/static/js/xoslib/xosHelper.js b/planetstack/core/xoslib/static/js/xoslib/xosHelper.js
index 89d0d3b..98dfb88 100644
--- a/planetstack/core/xoslib/static/js/xoslib/xosHelper.js
+++ b/planetstack/core/xoslib/static/js/xoslib/xosHelper.js
@@ -28,6 +28,23 @@
successTemplate: "#xos-success-template",
logMessageCount: 0,
+ confirmDialog: function(view, event) {
+ $("#xos-confirm-dialog").dialog({
+ autoOpen: false,
+ modal: true,
+ buttons : {
+ "Confirm" : function() {
+ $(this).dialog("close");
+ view.trigger(event);
+ },
+ "Cancel" : function() {
+ $(this).dialog("close");
+ }
+ }
+ });
+ $("#xos-confirm-dialog").dialog("open");
+ },
+
hideError: function() {
if (this.logWindowId) {
} else {
@@ -128,7 +145,7 @@
return function() {
model = new xos[collection_name].model();
detailViewClass = app[detailName];
- detailView = new detailViewClass({model: model});
+ detailView = new detailViewClass({model: model, collection:xos[collection_name]});
app[regionName].show(detailView);
$("#xos-detail-button-box").show();
$("#xos-listview-button-box").hide();
@@ -169,8 +186,13 @@
events: {"click button.btn-xos-save-continue": "submitContinueClicked",
"click button.btn-xos-save-leave": "submitLeaveClicked",
"click button.btn-xos-save-another": "submitAddAnotherClicked",
+ "click button.btn-xos-delete": "deleteClicked",
"change input": "inputChanged"},
+ initialize: function() {
+ this.on('deleteConfirmed', this.deleteConfirmed);
+ },
+
/* inputChanged is watching the onChange events of the input controls. We
do this to track when this view is 'dirty', so we can throw up a warning
if the user tries to change his slices without saving first.
@@ -193,6 +215,19 @@
this.app.showSuccess(result);
},
+ destroyError: function(model, result, xhr, infoMsgId) {
+ result["what"] = "destroy " + model.__proto__.modelName;
+ result["infoMsgId"] = infoMsgId;
+ this.app.showError(result);
+ },
+
+ destroySuccess: function(model, result, xhr, infoMsgId) {
+ result = {status: xhr.xhr.status, statusText: xhr.xhr.statusText};
+ result["what"] = "destroy " + model.__proto__.modelName;
+ result["infoMsgId"] = infoMsgId;
+ this.app.showSuccess(result);
+ },
+
submitContinueClicked: function(e) {
console.log("saveContinue");
e.preventDefault();
@@ -203,14 +238,14 @@
console.log("saveLeave");
e.preventDefault();
this.save();
- this.app.Router.navigate(this.listNavLink, {trigger: true});
- console.log("route to " + this.listNavLink);
+ this.app.navigate("list", this.model.modelName);
},
submitAddAnotherClicked: function(e) {
console.log("saveAnother");
e.preventDefault();
this.save();
+ this.app.navigate("add", this.model.modelName);
},
save: function() {
@@ -218,11 +253,36 @@
var infoMsgId = this.app.showInformational( {what: "save " + this.model.__proto__.modelName, status: "", statusText: "in progress..."} );
var data = Backbone.Syphon.serialize(this);
var that = this;
+ var isNew = !this.model.id;
this.model.save(data, {error: function(model, result, xhr) { that.saveError(model,result,xhr,infoMsgId);},
success: function(model, result, xhr) { that.saveSuccess(model,result,xhr,infoMsgId);}});
+ if (isNew) {
+ console.log(this.model);
+ this.collection.add(this.model);
+ this.collection.sort();
+ }
this.dirty = false;
},
+ destroyModel: function() {
+ this.app.hideError();
+ var infoMsgId = this.app.showInformational( {what: "destroy " + this.model.__proto__.modelName, status: "", statusText: "in progress..."} );
+ var that = this;
+ this.model.destroy({error: function(model, result, xhr) { that.destroyError(model,result,xhr,infoMsgId);},
+ success: function(model, result, xhr) { that.destroySuccess(model,result,xhr,infoMsgId);}});
+ },
+
+ deleteClicked: function(e) {
+ e.preventDefault();
+
this.app.confirmDialog(this, "deleteConfirmed");
+
},
+
+
deleteConfirmed: function() {
+
modelName = this.model.modelName;
+
this.destroyModel();
+
this.app.navigate("list", modelName);
+
},
+
tabClick: function(tabId, regionName) {
region = this.app[regionName];
if (this.currentTabRegion != undefined) {
@@ -320,16 +380,30 @@
childViewContainer: 'tbody',
events: {"click button.btn-xos-add": "addClicked",
- },
-
+ "click button.btn-xos-refresh": "refreshClicked",
+ },
+
+ _fetchStateChange: function() {
+ if (this.collection.fetching) {
+ $("#xos-list-title-spinner").show();
+ } else {
+ $("#xos-list-title-spinner").hide();
+ }
+ },
+
addClicked: function(e) {
- console.log("add");
e.preventDefault();
this.app.Router.navigate("add" + firstCharUpper(this.collection.modelName), {trigger: true});
},
- initialize: function() {
- this.listenTo(this.collection, 'change', this._renderChildren)
+
refreshClicked: function(e) {
+
e.preventDefault();
+
this.collection.refresh(refreshRelated=true);
+
},
+
+
initialize: function() {
+
this.listenTo(this.collection, 'change', this._renderChildren)
+ this.listenTo(this.collection, 'fetchStateChange', this._fetchStateChange);
// Because many of the templates use idToName(), we need to
// listen to the collections that hold the names for the ids
diff --git a/planetstack/core/xoslib/templates/xosAdmin.html b/planetstack/core/xoslib/templates/xosAdmin.html
index d543502..bc6ac02 100644
--- a/planetstack/core/xoslib/templates/xosAdmin.html
+++ b/planetstack/core/xoslib/templates/xosAdmin.html
@@ -35,7 +35,7 @@
</script>
<script type="text/template" id="xos-title-list">
- <h3><%= title %></h3>
+ <h3><img src="/static/img/brokencircle.gif" height=16 width=16 id="xos-list-title-spinner"> <%= title %></h3>
</script>
<script type="text/template" id="xos-title-detail">
@@ -56,12 +56,14 @@
<td colspan=2><button class="btn js-submit btn-xos-detail btn-xos-save-leave">Save</button>
<button class="btn js-submit btn-xos-detail btn-xos-save-continue">Save and Continue Editing</button>
<button class="btn js-submit btn-xos-detail btn-xos-save-another">Save and Add Another</button>
+ <button class="btn js-submit btn-xos-detail btn-xos-delete">Delete</button>
</td>
</tr>
</script>
<script type="text/template" id="xos-inline-list-buttons-template">
<button class="btn js-submit btn-xos-list btn-xos-add">Add</button>
+ <button class="btn js-submit btn-xos-list btn-xos-refresh">Refresh</button>
</td>
</tr>
</script>
@@ -89,7 +91,7 @@
<td class="objectLink"><%= name %></td>
<td><%= backend_type %></td>
<td><%= admin_tenant %></td>
- <td><%= sites.length %></td>
+ <td><%= typeof sites != 'undefined' && sites.length || 0 %></td>
</script>
<script type="text/template" id="xosAdmin-deployment-detail-template">
diff --git a/planetstack/ec2_observer/deleters/site_deleter.py b/planetstack/ec2_observer/deleters/site_deleter.py
index 88a4008..b8ca6a1 100644
--- a/planetstack/ec2_observer/deleters/site_deleter.py
+++ b/planetstack/ec2_observer/deleters/site_deleter.py
@@ -1,14 +1,14 @@
-from core.models import Site, SiteDeployment
+from core.models import Site, SiteDeployments
from observer.deleter import Deleter
-from observer.deleters.site_deployment_deleter import SiteDeploymentDeleter
+from observer.deleters.site_deployment_deleter import SiteDeploymentsDeleter
class SiteDeleter(Deleter):
model='Site'
def call(self, pk):
site = Site.objects.get(pk=pk)
- site_deployments = SiteDeployment.objects.filter(site=site)
- site_deployment_deleter = SiteDeploymentDeleter()
+ site_deployments = SiteDeployments.objects.filter(site=site)
+ site_deployment_deleter = SiteDeploymentsDeleter()
for site_deployment in site_deployments:
site_deployment_deleter(site_deployment.id)
site.delete()
diff --git a/planetstack/ec2_observer/deleters/site_deployment_deleter.py b/planetstack/ec2_observer/deleters/site_deployment_deleter.py
index db344cd..cc71d43 100644
--- a/planetstack/ec2_observer/deleters/site_deployment_deleter.py
+++ b/planetstack/ec2_observer/deleters/site_deployment_deleter.py
@@ -1,11 +1,11 @@
-from core.models import Site, SiteDeployment
+from core.models import Site, SiteDeployments
from observer.deleter import Deleter
-class SiteDeploymentDeleter(Deleter):
- model='SiteDeployment'
+class SiteDeploymentsDeleter(Deleter):
+ model='SiteDeployments'
def call(self, pk):
- site_deployment = SiteDeployment.objects.get(pk=pk)
+ site_deployment = SiteDeployments.objects.get(pk=pk)
if site_deployment.tenant_id:
driver = self.driver.admin_driver(deployment=site_deployment.deployment.name)
driver.delete_tenant(site_deployment.tenant_id)
diff --git a/planetstack/ec2_observer/deleters/slice_deleter.py b/planetstack/ec2_observer/deleters/slice_deleter.py
index e7c54e6..7e9dfd4 100644
--- a/planetstack/ec2_observer/deleters/slice_deleter.py
+++ b/planetstack/ec2_observer/deleters/slice_deleter.py
@@ -1,6 +1,6 @@
-from core.models import Slice, SliceDeployment, User
+from core.models import Slice, SliceDeployments, User
from observer.deleter import Deleter
-from observer.deleters.slice_deployment_deleter import SliceDeploymentDeleter
+from observer.deleters.slice_deployment_deleter import SliceDeploymentsDeleter
from util.logger import Logger, logging
logger = Logger(level=logging.INFO)
@@ -10,8 +10,8 @@
def call(self, pk):
slice = Slice.objects.get(pk=pk)
- slice_deployment_deleter = SliceDeploymentDeleter()
- for slice_deployment in SliceDeployment.objects.filter(slice=slice):
+ slice_deployment_deleter = SliceDeploymentsDeleter()
+ for slice_deployment in SliceDeployments.objects.filter(slice=slice):
try:
slice_deployment_deleter(slice_deployment.id)
except:
diff --git a/planetstack/ec2_observer/deleters/slice_deployment_deleter.py b/planetstack/ec2_observer/deleters/slice_deployment_deleter.py
index 31d26fb..6f1aec0 100644
--- a/planetstack/ec2_observer/deleters/slice_deployment_deleter.py
+++ b/planetstack/ec2_observer/deleters/slice_deployment_deleter.py
@@ -1,12 +1,12 @@
-from core.models import Slice, SliceDeployment, User
+from core.models import Slice, SliceDeployments, User
from observer.deleter import Deleter
from openstack.driver import OpenStackDriver
-class SliceDeploymentDeleter(Deleter):
- model='SliceDeployment'
+class SliceDeploymentsDeleter(Deleter):
+ model='SliceDeployments'
def call(self, pk):
- slice_deployment = SliceDeployment.objects.get(pk=pk)
+ slice_deployment = SliceDeployments.objects.get(pk=pk)
user = User.objects.get(id=slice_deployment.slice.creator.id)
driver = OpenStackDriver().admin_driver(deployment=slice_deployment.deployment.name)
client_driver = driver.client_driver(caller=user,
diff --git a/planetstack/ec2_observer/deleters/sliver_deleter.py b/planetstack/ec2_observer/deleters/sliver_deleter.py
index 732e535..097f0f7 100644
--- a/planetstack/ec2_observer/deleters/sliver_deleter.py
+++ b/planetstack/ec2_observer/deleters/sliver_deleter.py
@@ -1,4 +1,4 @@
-from core.models import Sliver, SliceDeployment
+from core.models import Sliver, SliceDeployments
from observer.deleter import Deleter
class SliverDeleter(Deleter):
diff --git a/planetstack/ec2_observer/deleters/user_deleter.py b/planetstack/ec2_observer/deleters/user_deleter.py
index 3f93060..3930eb0 100644
--- a/planetstack/ec2_observer/deleters/user_deleter.py
+++ b/planetstack/ec2_observer/deleters/user_deleter.py
@@ -1,13 +1,13 @@
-from core.models import User, UserDeployment
+from core.models import User, UserDeployments
from observer.deleter import Deleter
-from observer.deleters.user_deployment_deleter import UserDeploymentDeleter
+from observer.deleters.user_deployment_deleter import UserDeploymentsDeleter
class UserDeleter(Deleter):
model='User'
def call(self, pk):
user = User.objects.get(pk=pk)
- user_deployment_deleter = UserDeploymentDeleter()
- for user_deployment in UserDeployment.objects.filter(user=user):
+ user_deployment_deleter = UserDeploymentsDeleter()
+ for user_deployment in UserDeployments.objects.filter(user=user):
user_deployment_deleter(user_deployment.id)
user.delete()
diff --git a/planetstack/ec2_observer/deleters/user_deployment_deleter.py b/planetstack/ec2_observer/deleters/user_deployment_deleter.py
index 6d3825c..4bc7619 100644
--- a/planetstack/ec2_observer/deleters/user_deployment_deleter.py
+++ b/planetstack/ec2_observer/deleters/user_deployment_deleter.py
@@ -1,11 +1,11 @@
-from core.models import User, UserDeployment
+from core.models import User, UserDeployments
from observer.deleter import Deleter
-class UserDeploymentDeleter(Deleter):
- model='UserDeployment'
+class UserDeploymentsDeleter(Deleter):
+ model='UserDeployments'
def call(self, pk):
- user_deployment = UserDeployment.objects.get(pk=pk)
+ user_deployment = UserDeployments.objects.get(pk=pk)
if user_deployment.user.kuser_id:
driver = self.driver.admin_driver(deployment=user_deployment.deployment.name)
driver.delete_user(user_deployment.user.kuser_id)
diff --git a/planetstack/ec2_observer/steps/sync_nodes.py b/planetstack/ec2_observer/steps/sync_nodes.py
index 0fa8b61..9f032ed 100644
--- a/planetstack/ec2_observer/steps/sync_nodes.py
+++ b/planetstack/ec2_observer/steps/sync_nodes.py
@@ -20,7 +20,7 @@
return []
deployment = Deployment.objects.filter(Q(name="Amazon EC2"))[0]
- current_site_deployments = SiteDeployment.objects.filter(Q(deployment=deployment))
+ current_site_deployments = SiteDeployments.objects.filter(Q(deployment=deployment))
zone_ret = aws_run('ec2 describe-availability-zones')
zones = zone_ret['AvailabilityZones']
diff --git a/planetstack/ec2_observer/steps/sync_site_deployments.py b/planetstack/ec2_observer/steps/sync_site_deployments.py
index 5adccb7..7c24f68 100644
--- a/planetstack/ec2_observer/steps/sync_site_deployments.py
+++ b/planetstack/ec2_observer/steps/sync_site_deployments.py
@@ -7,9 +7,9 @@
from ec2_observer.awslib import *
import pdb
-class SyncSiteDeployment(SyncStep):
+class SyncSiteDeployments(SyncStep):
requested_interval=86400
- provides=[SiteDeployment]
+ provides=[SiteDeployments]
def fetch_pending(self, deletion):
if (deletion):
@@ -29,7 +29,7 @@
# The syncstep should catch it
# At any rate, we should not run if there are no deployments
deployment = Deployment.objects.filter(Q(name="Amazon EC2"))[0]
- current_site_deployments = SiteDeployment.objects.filter(Q(deployment=deployment))
+ current_site_deployments = SiteDeployments.objects.filter(Q(deployment=deployment))
site_dict = {}
for sd in current_site_deployments:
@@ -40,7 +40,7 @@
try:
site_record = site_dict[site]
except KeyError:
- sd = SiteDeployment(site=site,deployment=deployment,tenant_id=base64.urlsafe_b64encode(os.urandom(12)))
+ sd = SiteDeployments(site=site,deployment=deployment,tenant_id=base64.urlsafe_b64encode(os.urandom(12)))
updated_site_deployments.append(sd)
return updated_site_deployments
diff --git a/planetstack/ec2_observer/steps/sync_sites.py b/planetstack/ec2_observer/steps/sync_sites.py
index 0959c71..0c1c7cf 100644
--- a/planetstack/ec2_observer/steps/sync_sites.py
+++ b/planetstack/ec2_observer/steps/sync_sites.py
@@ -16,7 +16,7 @@
return []
deployment = Deployment.objects.filter(Q(name="Amazon EC2"))[0]
- current_site_deployments = SiteDeployment.objects.filter(Q(deployment=deployment))
+ current_site_deployments = SiteDeployments.objects.filter(Q(deployment=deployment))
zone_ret = aws_run('ec2 describe-availability-zones')
zones = zone_ret['AvailabilityZones']
diff --git a/planetstack/ec2_observer/steps/sync_slivers.py b/planetstack/ec2_observer/steps/sync_slivers.py
index ed75438..15cd5eb 100644
--- a/planetstack/ec2_observer/steps/sync_slivers.py
+++ b/planetstack/ec2_observer/steps/sync_slivers.py
@@ -5,7 +5,7 @@
from planetstack.config import Config
from ec2_observer.syncstep import SyncStep
from core.models.sliver import Sliver
-from core.models.slice import SlicePrivilege, SliceDeployment
+from core.models.slice import SlicePrivilege, SliceDeployments
from core.models.network import Network, NetworkSlice, NetworkDeployments
from util.logger import Logger, logging
from ec2_observer.awslib import *
@@ -30,7 +30,7 @@
my_slivers = []
for sliver in all_slivers:
- sd = SliceDeployment.objects.filter(Q(slice=sliver.slice))
+ sd = SliceDeployments.objects.filter(Q(slice=sliver.slice))
if (sd):
if (sd.deployment.name=='Amazon EC2'):
my_slivers.append(sliver)
diff --git a/planetstack/genapi.py b/planetstack/genapi.py
index 1e1fa9f..1503431 100644
--- a/planetstack/genapi.py
+++ b/planetstack/genapi.py
@@ -96,9 +96,9 @@
url(r'plstackapi/serviceclasses/(?P<pk>[a-zA-Z0-9\-]+)/$', ServiceClassDetail.as_view(), name ='serviceclass-detail'),
# url(r'plstackapi/serviceclasses/!new/$', ServiceClassNew.as_view(), name ='serviceclass-new'),
- url(r'plstackapi/payments/$', PaymentList.as_view(), name='payment-list'),
- url(r'plstackapi/payments/(?P<pk>[a-zA-Z0-9\-]+)/$', PaymentDetail.as_view(), name ='payment-detail'),
-# url(r'plstackapi/payments/!new/$', PaymentNew.as_view(), name ='payment-new'),
+ url(r'plstackapi/planetstacks/$', PlanetStackList.as_view(), name='planetstack-list'),
+ url(r'plstackapi/planetstacks/(?P<pk>[a-zA-Z0-9\-]+)/$', PlanetStackDetail.as_view(), name ='planetstack-detail'),
+# url(r'plstackapi/planetstacks/!new/$', PlanetStackNew.as_view(), name ='planetstack-new'),
url(r'plstackapi/charges/$', ChargeList.as_view(), name='charge-list'),
url(r'plstackapi/charges/(?P<pk>[a-zA-Z0-9\-]+)/$', ChargeDetail.as_view(), name ='charge-detail'),
@@ -132,14 +132,14 @@
url(r'plstackapi/dashboardviews/(?P<pk>[a-zA-Z0-9\-]+)/$', DashboardViewDetail.as_view(), name ='dashboardview-detail'),
# url(r'plstackapi/dashboardviews/!new/$', DashboardViewNew.as_view(), name ='dashboardview-new'),
- url(r'plstackapi/imagedeployments/$', ImageDeploymentsList.as_view(), name='imagedeployments-list'),
- url(r'plstackapi/imagedeployments/(?P<pk>[a-zA-Z0-9\-]+)/$', ImageDeploymentsDetail.as_view(), name ='imagedeployments-detail'),
-# url(r'plstackapi/imagedeployments/!new/$', ImageDeploymentsNew.as_view(), name ='imagedeployments-new'),
-
url(r'plstackapi/reservedresources/$', ReservedResourceList.as_view(), name='reservedresource-list'),
url(r'plstackapi/reservedresources/(?P<pk>[a-zA-Z0-9\-]+)/$', ReservedResourceDetail.as_view(), name ='reservedresource-detail'),
# url(r'plstackapi/reservedresources/!new/$', ReservedResourceNew.as_view(), name ='reservedresource-new'),
+ url(r'plstackapi/payments/$', PaymentList.as_view(), name='payment-list'),
+ url(r'plstackapi/payments/(?P<pk>[a-zA-Z0-9\-]+)/$', PaymentDetail.as_view(), name ='payment-detail'),
+# url(r'plstackapi/payments/!new/$', PaymentNew.as_view(), name ='payment-new'),
+
url(r'plstackapi/networkslices/$', NetworkSliceList.as_view(), name='networkslice-list'),
url(r'plstackapi/networkslices/(?P<pk>[a-zA-Z0-9\-]+)/$', NetworkSliceDetail.as_view(), name ='networkslice-detail'),
# url(r'plstackapi/networkslices/!new/$', NetworkSliceNew.as_view(), name ='networkslice-new'),
@@ -148,6 +148,10 @@
url(r'plstackapi/userdashboardviews/(?P<pk>[a-zA-Z0-9\-]+)/$', UserDashboardViewDetail.as_view(), name ='userdashboardview-detail'),
# url(r'plstackapi/userdashboardviews/!new/$', UserDashboardViewNew.as_view(), name ='userdashboardview-new'),
+ url(r'plstackapi/sitedeployments/$', SiteDeploymentsList.as_view(), name='sitedeployment-list'),
+ url(r'plstackapi/sitedeployments/(?P<pk>[a-zA-Z0-9\-]+)/$', SiteDeploymentsDetail.as_view(), name ='sitedeployment-detail'),
+# url(r'plstackapi/sitedeployments/!new/$', SiteDeploymentsNew.as_view(), name ='sitedeployment-new'),
+
url(r'plstackapi/planetstackprivileges/$', PlanetStackPrivilegeList.as_view(), name='planetstackprivilege-list'),
url(r'plstackapi/planetstackprivileges/(?P<pk>[a-zA-Z0-9\-]+)/$', PlanetStackPrivilegeDetail.as_view(), name ='planetstackprivilege-detail'),
# url(r'plstackapi/planetstackprivileges/!new/$', PlanetStackPrivilegeNew.as_view(), name ='planetstackprivilege-new'),
@@ -164,21 +168,17 @@
url(r'plstackapi/reservations/(?P<pk>[a-zA-Z0-9\-]+)/$', ReservationDetail.as_view(), name ='reservation-detail'),
# url(r'plstackapi/reservations/!new/$', ReservationNew.as_view(), name ='reservation-new'),
- url(r'plstackapi/slice_deployments/$', SliceDeploymentsList.as_view(), name='slicedeployments-list'),
- url(r'plstackapi/slice_deployments/(?P<pk>[a-zA-Z0-9\-]+)/$', SliceDeploymentsDetail.as_view(), name ='slicedeployments-detail'),
-# url(r'plstackapi/slice_deployments/!new/$', SliceDeploymentsNew.as_view(), name ='slicedeployments-new'),
-
url(r'plstackapi/siteprivileges/$', SitePrivilegeList.as_view(), name='siteprivilege-list'),
url(r'plstackapi/siteprivileges/(?P<pk>[a-zA-Z0-9\-]+)/$', SitePrivilegeDetail.as_view(), name ='siteprivilege-detail'),
# url(r'plstackapi/siteprivileges/!new/$', SitePrivilegeNew.as_view(), name ='siteprivilege-new'),
- url(r'plstackapi/planetstacks/$', PlanetStackList.as_view(), name='planetstack-list'),
- url(r'plstackapi/planetstacks/(?P<pk>[a-zA-Z0-9\-]+)/$', PlanetStackDetail.as_view(), name ='planetstack-detail'),
-# url(r'plstackapi/planetstacks/!new/$', PlanetStackNew.as_view(), name ='planetstack-new'),
+ url(r'plstackapi/slicedeployments/$', SliceDeploymentsList.as_view(), name='slicedeployment-list'),
+ url(r'plstackapi/slicedeployments/(?P<pk>[a-zA-Z0-9\-]+)/$', SliceDeploymentsDetail.as_view(), name ='slicedeployment-detail'),
+# url(r'plstackapi/slicedeployments/!new/$', SliceDeploymentsNew.as_view(), name ='slicedeployment-new'),
- url(r'plstackapi/user_deployments/$', UserDeploymentsList.as_view(), name='userdeployments-list'),
- url(r'plstackapi/user_deployments/(?P<pk>[a-zA-Z0-9\-]+)/$', UserDeploymentsDetail.as_view(), name ='userdeployments-detail'),
-# url(r'plstackapi/user_deployments/!new/$', UserDeploymentsNew.as_view(), name ='userdeployments-new'),
+ url(r'plstackapi/userdeployments/$', UserDeploymentsList.as_view(), name='userdeployment-list'),
+ url(r'plstackapi/userdeployments/(?P<pk>[a-zA-Z0-9\-]+)/$', UserDeploymentsDetail.as_view(), name ='userdeployment-detail'),
+# url(r'plstackapi/userdeployments/!new/$', UserDeploymentsNew.as_view(), name ='userdeployment-new'),
url(r'plstackapi/accounts/$', AccountList.as_view(), name='account-list'),
url(r'plstackapi/accounts/(?P<pk>[a-zA-Z0-9\-]+)/$', AccountDetail.as_view(), name ='account-detail'),
@@ -196,6 +196,10 @@
url(r'plstackapi/deploymentprivileges/(?P<pk>[a-zA-Z0-9\-]+)/$', DeploymentPrivilegeDetail.as_view(), name ='deploymentprivilege-detail'),
# url(r'plstackapi/deploymentprivileges/!new/$', DeploymentPrivilegeNew.as_view(), name ='deploymentprivilege-new'),
+ url(r'plstackapi/imagedeployments/$', ImageDeploymentsList.as_view(), name='imagedeployment-list'),
+ url(r'plstackapi/imagedeployments/(?P<pk>[a-zA-Z0-9\-]+)/$', ImageDeploymentsDetail.as_view(), name ='imagedeployment-detail'),
+# url(r'plstackapi/imagedeployments/!new/$', ImageDeploymentsNew.as_view(), name ='imagedeployment-new'),
+
url(r'plstackapi/deploymentroles/$', DeploymentRoleList.as_view(), name='deploymentrole-list'),
url(r'plstackapi/deploymentroles/(?P<pk>[a-zA-Z0-9\-]+)/$', DeploymentRoleDetail.as_view(), name ='deploymentrole-detail'),
# url(r'plstackapi/deploymentroles/!new/$', DeploymentRoleNew.as_view(), name ='deploymentrole-new'),
@@ -204,10 +208,6 @@
url(r'plstackapi/usercredentials/(?P<pk>[a-zA-Z0-9\-]+)/$', UserCredentialDetail.as_view(), name ='usercredential-detail'),
# url(r'plstackapi/usercredentials/!new/$', UserCredentialNew.as_view(), name ='usercredential-new'),
- url(r'plstackapi/sitedeployments/$', SiteDeploymentsList.as_view(), name='sitedeployments-list'),
- url(r'plstackapi/sitedeployments/(?P<pk>[a-zA-Z0-9\-]+)/$', SiteDeploymentsDetail.as_view(), name ='sitedeployments-detail'),
-# url(r'plstackapi/sitedeployments/!new/$', SiteDeploymentsNew.as_view(), name ='sitedeployments-new'),
-
url(r'plstackapi/slicetags/$', SliceTagList.as_view(), name='slicetag-list'),
url(r'plstackapi/slicetags/(?P<pk>[a-zA-Z0-9\-]+)/$', SliceTagDetail.as_view(), name ='slicetag-detail'),
# url(r'plstackapi/slicetags/!new/$', SliceTagNew.as_view(), name ='slicetag-new'),
@@ -246,7 +246,7 @@
'networks': reverse('network-list', request=request, format=format),
'services': reverse('service-list', request=request, format=format),
'serviceclasses': reverse('serviceclass-list', request=request, format=format),
- 'payments': reverse('payment-list', request=request, format=format),
+ 'planetstacks': reverse('planetstack-list', request=request, format=format),
'charges': reverse('charge-list', request=request, format=format),
'roles': reverse('role-list', request=request, format=format),
'usableobjects': reverse('usableobject-list', request=request, format=format),
@@ -255,25 +255,25 @@
'slivers': reverse('sliver-list', request=request, format=format),
'nodes': reverse('node-list', request=request, format=format),
'dashboardviews': reverse('dashboardview-list', request=request, format=format),
- 'imagedeploymentses': reverse('imagedeployments-list', request=request, format=format),
'reservedresources': reverse('reservedresource-list', request=request, format=format),
+ 'payments': reverse('payment-list', request=request, format=format),
'networkslices': reverse('networkslice-list', request=request, format=format),
'userdashboardviews': reverse('userdashboardview-list', request=request, format=format),
+ 'sitedeployments': reverse('sitedeployment-list', request=request, format=format),
'planetstackprivileges': reverse('planetstackprivilege-list', request=request, format=format),
'users': reverse('user-list', request=request, format=format),
'deployments': reverse('deployment-list', request=request, format=format),
'reservations': reverse('reservation-list', request=request, format=format),
- 'slicedeploymentses': reverse('slicedeployments-list', request=request, format=format),
'siteprivileges': reverse('siteprivilege-list', request=request, format=format),
- 'planetstacks': reverse('planetstack-list', request=request, format=format),
- 'userdeploymentses': reverse('userdeployments-list', request=request, format=format),
+ 'slicedeployments': reverse('slicedeployment-list', request=request, format=format),
+ 'userdeployments': reverse('userdeployment-list', request=request, format=format),
'accounts': reverse('account-list', request=request, format=format),
'networkparametertypes': reverse('networkparametertype-list', request=request, format=format),
'sitecredentials': reverse('sitecredential-list', request=request, format=format),
'deploymentprivileges': reverse('deploymentprivilege-list', request=request, format=format),
+ 'imagedeployments': reverse('imagedeployment-list', request=request, format=format),
'deploymentroles': reverse('deploymentrole-list', request=request, format=format),
'usercredentials': reverse('usercredential-list', request=request, format=format),
- 'sitedeploymentses': reverse('sitedeployments-list', request=request, format=format),
'slicetags': reverse('slicetag-list', request=request, format=format),
'networktemplates': reverse('networktemplate-list', request=request, format=format),
'routers': reverse('router-list', request=request, format=format),
@@ -576,7 +576,7 @@
class Meta:
model = Network
- fields = ('id','created','updated','enacted','backend_status','deleted','name','template','subnet','ports','labels','owner','guaranteedBandwidth','permitAllSlices','network_id','router_id','subnet_id','routers','availableRouters','routers','routers',)
+ fields = ('id','created','updated','enacted','backend_status','deleted','name','template','subnet','ports','labels','owner','guaranteedBandwidth','permitAllSlices','topologyParameters','controllerUrl','controllerParameters','network_id','router_id','subnet_id','routers','availableRouters','routers','routers',)
class NetworkIdSerializer(serializers.ModelSerializer):
id = serializers.Field()
@@ -599,7 +599,7 @@
class Meta:
model = Network
- fields = ('id','created','updated','enacted','backend_status','deleted','name','template','subnet','ports','labels','owner','guaranteedBandwidth','permitAllSlices','network_id','router_id','subnet_id','routers','availableRouters','routers','routers',)
+ fields = ('id','created','updated','enacted','backend_status','deleted','name','template','subnet','ports','labels','owner','guaranteedBandwidth','permitAllSlices','topologyParameters','controllerUrl','controllerParameters','network_id','router_id','subnet_id','routers','availableRouters','routers','routers',)
@@ -638,19 +638,19 @@
-class PaymentSerializer(serializers.HyperlinkedModelSerializer):
+class PlanetStackSerializer(serializers.HyperlinkedModelSerializer):
id = serializers.Field()
class Meta:
- model = Payment
- fields = ('id','created','updated','enacted','backend_status','deleted','account','amount','date',)
+ model = PlanetStack
+ fields = ('id','created','updated','enacted','backend_status','deleted','description',)
-class PaymentIdSerializer(serializers.ModelSerializer):
+class PlanetStackIdSerializer(serializers.ModelSerializer):
id = serializers.Field()
class Meta:
- model = Payment
- fields = ('id','created','updated','enacted','backend_status','deleted','account','amount','date',)
+ model = PlanetStack
+ fields = ('id','created','updated','enacted','backend_status','deleted','description',)
@@ -807,23 +807,6 @@
-class ImageDeploymentsSerializer(serializers.HyperlinkedModelSerializer):
- id = serializers.Field()
-
- class Meta:
- model = ImageDeployments
- fields = ('id','created','updated','enacted','backend_status','deleted','image','deployment','glance_image_id',)
-
-class ImageDeploymentsIdSerializer(serializers.ModelSerializer):
- id = serializers.Field()
-
- class Meta:
- model = ImageDeployments
- fields = ('id','created','updated','enacted','backend_status','deleted','image','deployment','glance_image_id',)
-
-
-
-
class ReservedResourceSerializer(serializers.HyperlinkedModelSerializer):
id = serializers.Field()
@@ -841,6 +824,23 @@
+class PaymentSerializer(serializers.HyperlinkedModelSerializer):
+ id = serializers.Field()
+
+ class Meta:
+ model = Payment
+ fields = ('id','created','updated','enacted','backend_status','deleted','account','amount','date',)
+
+class PaymentIdSerializer(serializers.ModelSerializer):
+ id = serializers.Field()
+
+ class Meta:
+ model = Payment
+ fields = ('id','created','updated','enacted','backend_status','deleted','account','amount','date',)
+
+
+
+
class NetworkSliceSerializer(serializers.HyperlinkedModelSerializer):
id = serializers.Field()
@@ -875,6 +875,23 @@
+class SiteDeploymentsSerializer(serializers.HyperlinkedModelSerializer):
+ id = serializers.Field()
+
+ class Meta:
+ model = SiteDeployments
+ fields = ('id','created','updated','enacted','backend_status','deleted','site','deployment','tenant_id',)
+
+class SiteDeploymentsIdSerializer(serializers.ModelSerializer):
+ id = serializers.Field()
+
+ class Meta:
+ model = SiteDeployments
+ fields = ('id','created','updated','enacted','backend_status','deleted','site','deployment','tenant_id',)
+
+
+
+
class PlanetStackPrivilegeSerializer(serializers.HyperlinkedModelSerializer):
id = serializers.Field()
@@ -975,23 +992,6 @@
-class SliceDeploymentsSerializer(serializers.HyperlinkedModelSerializer):
- id = serializers.Field()
-
- class Meta:
- model = SliceDeployments
- fields = ('id','created','updated','enacted','backend_status','deleted','slice','deployment','tenant_id','network_id','router_id','subnet_id',)
-
-class SliceDeploymentsIdSerializer(serializers.ModelSerializer):
- id = serializers.Field()
-
- class Meta:
- model = SliceDeployments
- fields = ('id','created','updated','enacted','backend_status','deleted','slice','deployment','tenant_id','network_id','router_id','subnet_id',)
-
-
-
-
class SitePrivilegeSerializer(serializers.HyperlinkedModelSerializer):
id = serializers.Field()
@@ -1009,19 +1009,19 @@
-class PlanetStackSerializer(serializers.HyperlinkedModelSerializer):
+class SliceDeploymentsSerializer(serializers.HyperlinkedModelSerializer):
id = serializers.Field()
class Meta:
- model = PlanetStack
- fields = ('id','created','updated','enacted','backend_status','deleted','description',)
+ model = SliceDeployments
+ fields = ('id','created','updated','enacted','backend_status','deleted','slice','deployment','tenant_id','network_id','router_id','subnet_id',)
-class PlanetStackIdSerializer(serializers.ModelSerializer):
+class SliceDeploymentsIdSerializer(serializers.ModelSerializer):
id = serializers.Field()
class Meta:
- model = PlanetStack
- fields = ('id','created','updated','enacted','backend_status','deleted','description',)
+ model = SliceDeployments
+ fields = ('id','created','updated','enacted','backend_status','deleted','slice','deployment','tenant_id','network_id','router_id','subnet_id',)
@@ -1111,6 +1111,23 @@
+class ImageDeploymentsSerializer(serializers.HyperlinkedModelSerializer):
+ id = serializers.Field()
+
+ class Meta:
+ model = ImageDeployments
+ fields = ('id','created','updated','enacted','backend_status','deleted','image','deployment','glance_image_id',)
+
+class ImageDeploymentsIdSerializer(serializers.ModelSerializer):
+ id = serializers.Field()
+
+ class Meta:
+ model = ImageDeployments
+ fields = ('id','created','updated','enacted','backend_status','deleted','image','deployment','glance_image_id',)
+
+
+
+
class DeploymentRoleSerializer(serializers.HyperlinkedModelSerializer):
id = serializers.Field()
@@ -1145,23 +1162,6 @@
-class SiteDeploymentsSerializer(serializers.HyperlinkedModelSerializer):
- id = serializers.Field()
-
- class Meta:
- model = SiteDeployments
- fields = ('id','created','updated','enacted','backend_status','deleted','site','deployment','tenant_id',)
-
-class SiteDeploymentsIdSerializer(serializers.ModelSerializer):
- id = serializers.Field()
-
- class Meta:
- model = SiteDeployments
- fields = ('id','created','updated','enacted','backend_status','deleted','site','deployment','tenant_id',)
-
-
-
-
class SliceTagSerializer(serializers.HyperlinkedModelSerializer):
id = serializers.Field()
@@ -1184,14 +1184,14 @@
class Meta:
model = NetworkTemplate
- fields = ('id','created','updated','enacted','backend_status','deleted','name','description','guaranteedBandwidth','visibility','translation','sharedNetworkName','sharedNetworkId',)
+ fields = ('id','created','updated','enacted','backend_status','deleted','name','description','guaranteedBandwidth','visibility','translation','sharedNetworkName','sharedNetworkId','topologyKind','controllerKind',)
class NetworkTemplateIdSerializer(serializers.ModelSerializer):
id = serializers.Field()
class Meta:
model = NetworkTemplate
- fields = ('id','created','updated','enacted','backend_status','deleted','name','description','guaranteedBandwidth','visibility','translation','sharedNetworkName','sharedNetworkId',)
+ fields = ('id','created','updated','enacted','backend_status','deleted','name','description','guaranteedBandwidth','visibility','translation','sharedNetworkName','sharedNetworkId','topologyKind','controllerKind',)
@@ -1266,7 +1266,7 @@
ServiceClass: ServiceClassSerializer,
- Payment: PaymentSerializer,
+ PlanetStack: PlanetStackSerializer,
Charge: ChargeSerializer,
@@ -1284,14 +1284,16 @@
DashboardView: DashboardViewSerializer,
- ImageDeployments: ImageDeploymentsSerializer,
-
ReservedResource: ReservedResourceSerializer,
+ Payment: PaymentSerializer,
+
NetworkSlice: NetworkSliceSerializer,
UserDashboardView: UserDashboardViewSerializer,
+ SiteDeployments: SiteDeploymentsSerializer,
+
PlanetStackPrivilege: PlanetStackPrivilegeSerializer,
User: UserSerializer,
@@ -1300,11 +1302,9 @@
Reservation: ReservationSerializer,
- SliceDeployments: SliceDeploymentsSerializer,
-
SitePrivilege: SitePrivilegeSerializer,
- PlanetStack: PlanetStackSerializer,
+ SliceDeployments: SliceDeploymentsSerializer,
UserDeployments: UserDeploymentsSerializer,
@@ -1316,12 +1316,12 @@
DeploymentPrivilege: DeploymentPrivilegeSerializer,
+ ImageDeployments: ImageDeploymentsSerializer,
+
DeploymentRole: DeploymentRoleSerializer,
UserCredential: UserCredentialSerializer,
- SiteDeployments: SiteDeploymentsSerializer,
-
SliceTag: SliceTagSerializer,
NetworkTemplate: NetworkTemplateSerializer,
@@ -2520,7 +2520,7 @@
serializer_class = NetworkSerializer
id_serializer_class = NetworkIdSerializer
filter_backends = (filters.DjangoFilterBackend,)
- filter_fields = ('id','created','updated','enacted','backend_status','deleted','name','template','subnet','ports','labels','owner','guaranteedBandwidth','permitAllSlices','network_id','router_id','subnet_id','routers','availableRouters','routers','routers',)
+ filter_fields = ('id','created','updated','enacted','backend_status','deleted','name','template','subnet','ports','labels','owner','guaranteedBandwidth','permitAllSlices','topologyParameters','controllerUrl','controllerParameters','network_id','router_id','subnet_id','routers','availableRouters','routers','routers',)
def get_serializer_class(self):
no_hyperlinks = self.request.QUERY_PARAMS.get('no_hyperlinks', False)
@@ -2758,12 +2758,12 @@
-class PaymentList(generics.ListCreateAPIView):
- queryset = Payment.objects.select_related().all()
- serializer_class = PaymentSerializer
- id_serializer_class = PaymentIdSerializer
+class PlanetStackList(generics.ListCreateAPIView):
+ queryset = PlanetStack.objects.select_related().all()
+ serializer_class = PlanetStackSerializer
+ id_serializer_class = PlanetStackIdSerializer
filter_backends = (filters.DjangoFilterBackend,)
- filter_fields = ('id','created','updated','enacted','backend_status','deleted','account','amount','date',)
+ filter_fields = ('id','created','updated','enacted','backend_status','deleted','description',)
def get_serializer_class(self):
no_hyperlinks = self.request.QUERY_PARAMS.get('no_hyperlinks', False)
@@ -2773,7 +2773,7 @@
return self.serializer_class
def get_queryset(self):
- return Payment.select_by_user(self.request.user)
+ return PlanetStack.select_by_user(self.request.user)
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.DATA, files=request.FILES)
@@ -2782,21 +2782,21 @@
obj = serializer.object
obj.caller = request.user
if obj.can_update(request.user):
- return super(PaymentList, self).create(request, *args, **kwargs)
+ return super(PlanetStackList, self).create(request, *args, **kwargs)
else:
raise Exception("failed obj.can_update")
- ret = super(PaymentList, self).create(request, *args, **kwargs)
+ ret = super(PlanetStackList, self).create(request, *args, **kwargs)
if (ret.status_code%100 != 200):
raise Exception(ret.data)
return ret
-class PaymentDetail(PlanetStackRetrieveUpdateDestroyAPIView):
- queryset = Payment.objects.select_related().all()
- serializer_class = PaymentSerializer
- id_serializer_class = PaymentIdSerializer
+class PlanetStackDetail(PlanetStackRetrieveUpdateDestroyAPIView):
+ queryset = PlanetStack.objects.select_related().all()
+ serializer_class = PlanetStackSerializer
+ id_serializer_class = PlanetStackIdSerializer
def get_serializer_class(self):
no_hyperlinks = self.request.QUERY_PARAMS.get('no_hyperlinks', False)
@@ -2806,7 +2806,7 @@
return self.serializer_class
def get_queryset(self):
- return Payment.select_by_user(self.request.user)
+ return PlanetStack.select_by_user(self.request.user)
# update() is handled by PlanetStackRetrieveUpdateDestroyAPIView
@@ -2817,9 +2817,9 @@
filled with defaults. I solved it another way, so this code may soon be
abandoned.
-class PaymentNew(GenericAPIView):
- serializer_class = PaymentSerializer
- id_serializer_class = PaymentIdSerializer
+class PlanetStackNew(GenericAPIView):
+ serializer_class = PlanetStackSerializer
+ id_serializer_class = PlanetStackIdSerializer
def get(self, request, *args, **kwargs):
return self.makenew(request, *args, **kwargs)
@@ -2832,7 +2832,7 @@
return self.serializer_class
def makenew(self, request, *args, **kwargs):
- obj = Payment()
+ obj = PlanetStack()
serializer = self.get_serializer(obj)
return Response(serializer.data)
"""
@@ -3487,87 +3487,6 @@
-class ImageDeploymentsList(generics.ListCreateAPIView):
- queryset = ImageDeployments.objects.select_related().all()
- serializer_class = ImageDeploymentsSerializer
- id_serializer_class = ImageDeploymentsIdSerializer
- filter_backends = (filters.DjangoFilterBackend,)
- filter_fields = ('id','created','updated','enacted','backend_status','deleted','image','deployment','glance_image_id',)
-
- def get_serializer_class(self):
- no_hyperlinks = self.request.QUERY_PARAMS.get('no_hyperlinks', False)
- if (no_hyperlinks):
- return self.id_serializer_class
- else:
- return self.serializer_class
-
- def get_queryset(self):
- return ImageDeployments.select_by_user(self.request.user)
-
- def create(self, request, *args, **kwargs):
- serializer = self.get_serializer(data=request.DATA, files=request.FILES)
- if not (serializer.is_valid()):
- raise Exception("failed serializer.is_valid: " + str(serializer.errors))
- obj = serializer.object
- obj.caller = request.user
- if obj.can_update(request.user):
- return super(ImageDeploymentsList, self).create(request, *args, **kwargs)
- else:
- raise Exception("failed obj.can_update")
-
- ret = super(ImageDeploymentsList, self).create(request, *args, **kwargs)
- if (ret.status_code%100 != 200):
- raise Exception(ret.data)
-
- return ret
-
-
-class ImageDeploymentsDetail(PlanetStackRetrieveUpdateDestroyAPIView):
- queryset = ImageDeployments.objects.select_related().all()
- serializer_class = ImageDeploymentsSerializer
- id_serializer_class = ImageDeploymentsIdSerializer
-
- def get_serializer_class(self):
- no_hyperlinks = self.request.QUERY_PARAMS.get('no_hyperlinks', False)
- if (no_hyperlinks):
- return self.id_serializer_class
- else:
- return self.serializer_class
-
- def get_queryset(self):
- return ImageDeployments.select_by_user(self.request.user)
-
- # update() is handled by PlanetStackRetrieveUpdateDestroyAPIView
-
- # destroy() is handled by PlanetStackRetrieveUpdateDestroyAPIView
-
-"""
- XXX smbaker: my intent was to create a view that would return 'new' objects
- filled with defaults. I solved it another way, so this code may soon be
- abandoned.
-
-class ImageDeploymentsNew(GenericAPIView):
- serializer_class = ImageDeploymentsSerializer
- id_serializer_class = ImageDeploymentsIdSerializer
-
- def get(self, request, *args, **kwargs):
- return self.makenew(request, *args, **kwargs)
-
- def get_serializer_class(self):
- no_hyperlinks = self.request.QUERY_PARAMS.get('no_hyperlinks', False)
- if (no_hyperlinks):
- return self.id_serializer_class
- else:
- return self.serializer_class
-
- def makenew(self, request, *args, **kwargs):
- obj = ImageDeployments()
- serializer = self.get_serializer(obj)
- return Response(serializer.data)
-"""
-
-
-
class ReservedResourceList(generics.ListCreateAPIView):
queryset = ReservedResource.objects.select_related().all()
serializer_class = ReservedResourceSerializer
@@ -3649,6 +3568,87 @@
+class PaymentList(generics.ListCreateAPIView):
+ queryset = Payment.objects.select_related().all()
+ serializer_class = PaymentSerializer
+ id_serializer_class = PaymentIdSerializer
+ filter_backends = (filters.DjangoFilterBackend,)
+ filter_fields = ('id','created','updated','enacted','backend_status','deleted','account','amount','date',)
+
+ def get_serializer_class(self):
+ no_hyperlinks = self.request.QUERY_PARAMS.get('no_hyperlinks', False)
+ if (no_hyperlinks):
+ return self.id_serializer_class
+ else:
+ return self.serializer_class
+
+ def get_queryset(self):
+ return Payment.select_by_user(self.request.user)
+
+ def create(self, request, *args, **kwargs):
+ serializer = self.get_serializer(data=request.DATA, files=request.FILES)
+ if not (serializer.is_valid()):
+ raise Exception("failed serializer.is_valid: " + str(serializer.errors))
+ obj = serializer.object
+ obj.caller = request.user
+ if obj.can_update(request.user):
+ return super(PaymentList, self).create(request, *args, **kwargs)
+ else:
+ raise Exception("failed obj.can_update")
+
+ ret = super(PaymentList, self).create(request, *args, **kwargs)
+ if (ret.status_code%100 != 200):
+ raise Exception(ret.data)
+
+ return ret
+
+
+class PaymentDetail(PlanetStackRetrieveUpdateDestroyAPIView):
+ queryset = Payment.objects.select_related().all()
+ serializer_class = PaymentSerializer
+ id_serializer_class = PaymentIdSerializer
+
+ def get_serializer_class(self):
+ no_hyperlinks = self.request.QUERY_PARAMS.get('no_hyperlinks', False)
+ if (no_hyperlinks):
+ return self.id_serializer_class
+ else:
+ return self.serializer_class
+
+ def get_queryset(self):
+ return Payment.select_by_user(self.request.user)
+
+ # update() is handled by PlanetStackRetrieveUpdateDestroyAPIView
+
+ # destroy() is handled by PlanetStackRetrieveUpdateDestroyAPIView
+
+"""
+ XXX smbaker: my intent was to create a view that would return 'new' objects
+ filled with defaults. I solved it another way, so this code may soon be
+ abandoned.
+
+class PaymentNew(GenericAPIView):
+ serializer_class = PaymentSerializer
+ id_serializer_class = PaymentIdSerializer
+
+ def get(self, request, *args, **kwargs):
+ return self.makenew(request, *args, **kwargs)
+
+ def get_serializer_class(self):
+ no_hyperlinks = self.request.QUERY_PARAMS.get('no_hyperlinks', False)
+ if (no_hyperlinks):
+ return self.id_serializer_class
+ else:
+ return self.serializer_class
+
+ def makenew(self, request, *args, **kwargs):
+ obj = Payment()
+ serializer = self.get_serializer(obj)
+ return Response(serializer.data)
+"""
+
+
+
class NetworkSliceList(generics.ListCreateAPIView):
queryset = NetworkSlice.objects.select_related().all()
serializer_class = NetworkSliceSerializer
@@ -3811,6 +3811,87 @@
+class SiteDeploymentsList(generics.ListCreateAPIView):
+ queryset = SiteDeployments.objects.select_related().all()
+ serializer_class = SiteDeploymentsSerializer
+ id_serializer_class = SiteDeploymentsIdSerializer
+ filter_backends = (filters.DjangoFilterBackend,)
+ filter_fields = ('id','created','updated','enacted','backend_status','deleted','site','deployment','tenant_id',)
+
+ def get_serializer_class(self):
+ no_hyperlinks = self.request.QUERY_PARAMS.get('no_hyperlinks', False)
+ if (no_hyperlinks):
+ return self.id_serializer_class
+ else:
+ return self.serializer_class
+
+ def get_queryset(self):
+ return SiteDeployments.select_by_user(self.request.user)
+
+ def create(self, request, *args, **kwargs):
+ serializer = self.get_serializer(data=request.DATA, files=request.FILES)
+ if not (serializer.is_valid()):
+ raise Exception("failed serializer.is_valid: " + str(serializer.errors))
+ obj = serializer.object
+ obj.caller = request.user
+ if obj.can_update(request.user):
+ return super(SiteDeploymentsList, self).create(request, *args, **kwargs)
+ else:
+ raise Exception("failed obj.can_update")
+
+ ret = super(SiteDeploymentsList, self).create(request, *args, **kwargs)
+ if (ret.status_code%100 != 200):
+ raise Exception(ret.data)
+
+ return ret
+
+
+class SiteDeploymentsDetail(PlanetStackRetrieveUpdateDestroyAPIView):
+ queryset = SiteDeployments.objects.select_related().all()
+ serializer_class = SiteDeploymentsSerializer
+ id_serializer_class = SiteDeploymentsIdSerializer
+
+ def get_serializer_class(self):
+ no_hyperlinks = self.request.QUERY_PARAMS.get('no_hyperlinks', False)
+ if (no_hyperlinks):
+ return self.id_serializer_class
+ else:
+ return self.serializer_class
+
+ def get_queryset(self):
+ return SiteDeployments.select_by_user(self.request.user)
+
+ # update() is handled by PlanetStackRetrieveUpdateDestroyAPIView
+
+ # destroy() is handled by PlanetStackRetrieveUpdateDestroyAPIView
+
+"""
+ XXX smbaker: my intent was to create a view that would return 'new' objects
+ filled with defaults. I solved it another way, so this code may soon be
+ abandoned.
+
+class SiteDeploymentsNew(GenericAPIView):
+ serializer_class = SiteDeploymentsSerializer
+ id_serializer_class = SiteDeploymentsIdSerializer
+
+ def get(self, request, *args, **kwargs):
+ return self.makenew(request, *args, **kwargs)
+
+ def get_serializer_class(self):
+ no_hyperlinks = self.request.QUERY_PARAMS.get('no_hyperlinks', False)
+ if (no_hyperlinks):
+ return self.id_serializer_class
+ else:
+ return self.serializer_class
+
+ def makenew(self, request, *args, **kwargs):
+ obj = SiteDeployments()
+ serializer = self.get_serializer(obj)
+ return Response(serializer.data)
+"""
+
+
+
class PlanetStackPrivilegeList(generics.ListCreateAPIView):
queryset = PlanetStackPrivilege.objects.select_related().all()
serializer_class = PlanetStackPrivilegeSerializer
@@ -4135,87 +4216,6 @@
-class SliceDeploymentsList(generics.ListCreateAPIView):
- queryset = SliceDeployments.objects.select_related().all()
- serializer_class = SliceDeploymentsSerializer
- id_serializer_class = SliceDeploymentsIdSerializer
- filter_backends = (filters.DjangoFilterBackend,)
- filter_fields = ('id','created','updated','enacted','backend_status','deleted','slice','deployment','tenant_id','network_id','router_id','subnet_id',)
-
- def get_serializer_class(self):
- no_hyperlinks = self.request.QUERY_PARAMS.get('no_hyperlinks', False)
- if (no_hyperlinks):
- return self.id_serializer_class
- else:
- return self.serializer_class
-
- def get_queryset(self):
- return SliceDeployments.select_by_user(self.request.user)
-
- def create(self, request, *args, **kwargs):
- serializer = self.get_serializer(data=request.DATA, files=request.FILES)
- if not (serializer.is_valid()):
- raise Exception("failed serializer.is_valid: " + str(serializer.errors))
- obj = serializer.object
- obj.caller = request.user
- if obj.can_update(request.user):
- return super(SliceDeploymentsList, self).create(request, *args, **kwargs)
- else:
- raise Exception("failed obj.can_update")
-
- ret = super(SliceDeploymentsList, self).create(request, *args, **kwargs)
- if (ret.status_code%100 != 200):
- raise Exception(ret.data)
-
- return ret
-
-
-class SliceDeploymentsDetail(PlanetStackRetrieveUpdateDestroyAPIView):
- queryset = SliceDeployments.objects.select_related().all()
- serializer_class = SliceDeploymentsSerializer
- id_serializer_class = SliceDeploymentsIdSerializer
-
- def get_serializer_class(self):
- no_hyperlinks = self.request.QUERY_PARAMS.get('no_hyperlinks', False)
- if (no_hyperlinks):
- return self.id_serializer_class
- else:
- return self.serializer_class
-
- def get_queryset(self):
- return SliceDeployments.select_by_user(self.request.user)
-
- # update() is handled by PlanetStackRetrieveUpdateDestroyAPIView
-
- # destroy() is handled by PlanetStackRetrieveUpdateDestroyAPIView
-
-"""
- XXX smbaker: my intent was to create a view that would return 'new' objects
- filled with defaults. I solved it another way, so this code may soon be
- abandoned.
-
-class SliceDeploymentsNew(GenericAPIView):
- serializer_class = SliceDeploymentsSerializer
- id_serializer_class = SliceDeploymentsIdSerializer
-
- def get(self, request, *args, **kwargs):
- return self.makenew(request, *args, **kwargs)
-
- def get_serializer_class(self):
- no_hyperlinks = self.request.QUERY_PARAMS.get('no_hyperlinks', False)
- if (no_hyperlinks):
- return self.id_serializer_class
- else:
- return self.serializer_class
-
- def makenew(self, request, *args, **kwargs):
- obj = SliceDeployments()
- serializer = self.get_serializer(obj)
- return Response(serializer.data)
-"""
-
-
-
class SitePrivilegeList(generics.ListCreateAPIView):
queryset = SitePrivilege.objects.select_related().all()
serializer_class = SitePrivilegeSerializer
@@ -4297,12 +4297,12 @@
-class PlanetStackList(generics.ListCreateAPIView):
- queryset = PlanetStack.objects.select_related().all()
- serializer_class = PlanetStackSerializer
- id_serializer_class = PlanetStackIdSerializer
+class SliceDeploymentsList(generics.ListCreateAPIView):
+ queryset = SliceDeployments.objects.select_related().all()
+ serializer_class = SliceDeploymentsSerializer
+ id_serializer_class = SliceDeploymentsIdSerializer
filter_backends = (filters.DjangoFilterBackend,)
- filter_fields = ('id','created','updated','enacted','backend_status','deleted','description',)
+ filter_fields = ('id','created','updated','enacted','backend_status','deleted','slice','deployment','tenant_id','network_id','router_id','subnet_id',)
def get_serializer_class(self):
no_hyperlinks = self.request.QUERY_PARAMS.get('no_hyperlinks', False)
@@ -4312,7 +4312,7 @@
return self.serializer_class
def get_queryset(self):
- return PlanetStack.select_by_user(self.request.user)
+ return SliceDeployments.select_by_user(self.request.user)
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.DATA, files=request.FILES)
@@ -4321,21 +4321,21 @@
obj = serializer.object
obj.caller = request.user
if obj.can_update(request.user):
- return super(PlanetStackList, self).create(request, *args, **kwargs)
+ return super(SliceDeploymentsList, self).create(request, *args, **kwargs)
else:
raise Exception("failed obj.can_update")
- ret = super(PlanetStackList, self).create(request, *args, **kwargs)
+ ret = super(SliceDeploymentsList, self).create(request, *args, **kwargs)
if (ret.status_code%100 != 200):
raise Exception(ret.data)
return ret
-class PlanetStackDetail(PlanetStackRetrieveUpdateDestroyAPIView):
- queryset = PlanetStack.objects.select_related().all()
- serializer_class = PlanetStackSerializer
- id_serializer_class = PlanetStackIdSerializer
+class SliceDeploymentsDetail(PlanetStackRetrieveUpdateDestroyAPIView):
+ queryset = SliceDeployments.objects.select_related().all()
+ serializer_class = SliceDeploymentsSerializer
+ id_serializer_class = SliceDeploymentsIdSerializer
def get_serializer_class(self):
no_hyperlinks = self.request.QUERY_PARAMS.get('no_hyperlinks', False)
@@ -4345,7 +4345,7 @@
return self.serializer_class
def get_queryset(self):
- return PlanetStack.select_by_user(self.request.user)
+ return SliceDeployments.select_by_user(self.request.user)
# update() is handled by PlanetStackRetrieveUpdateDestroyAPIView
@@ -4356,9 +4356,9 @@
filled with defaults. I solved it another way, so this code may soon be
abandoned.
-class PlanetStackNew(GenericAPIView):
- serializer_class = PlanetStackSerializer
- id_serializer_class = PlanetStackIdSerializer
+class SliceDeploymentsNew(GenericAPIView):
+ serializer_class = SliceDeploymentsSerializer
+ id_serializer_class = SliceDeploymentsIdSerializer
def get(self, request, *args, **kwargs):
return self.makenew(request, *args, **kwargs)
@@ -4371,7 +4371,7 @@
return self.serializer_class
def makenew(self, request, *args, **kwargs):
- obj = PlanetStack()
+ obj = SliceDeployments()
serializer = self.get_serializer(obj)
return Response(serializer.data)
"""
@@ -4783,6 +4783,87 @@
+class ImageDeploymentsList(generics.ListCreateAPIView):
+ queryset = ImageDeployments.objects.select_related().all()
+ serializer_class = ImageDeploymentsSerializer
+ id_serializer_class = ImageDeploymentsIdSerializer
+ filter_backends = (filters.DjangoFilterBackend,)
+ filter_fields = ('id','created','updated','enacted','backend_status','deleted','image','deployment','glance_image_id',)
+
+ def get_serializer_class(self):
+ no_hyperlinks = self.request.QUERY_PARAMS.get('no_hyperlinks', False)
+ if (no_hyperlinks):
+ return self.id_serializer_class
+ else:
+ return self.serializer_class
+
+ def get_queryset(self):
+ return ImageDeployments.select_by_user(self.request.user)
+
+ def create(self, request, *args, **kwargs):
+ serializer = self.get_serializer(data=request.DATA, files=request.FILES)
+ if not (serializer.is_valid()):
+ raise Exception("failed serializer.is_valid: " + str(serializer.errors))
+ obj = serializer.object
+ obj.caller = request.user
+ if obj.can_update(request.user):
+ return super(ImageDeploymentsList, self).create(request, *args, **kwargs)
+ else:
+ raise Exception("failed obj.can_update")
+
+ ret = super(ImageDeploymentsList, self).create(request, *args, **kwargs)
+ if (ret.status_code%100 != 200):
+ raise Exception(ret.data)
+
+ return ret
+
+
+class ImageDeploymentsDetail(PlanetStackRetrieveUpdateDestroyAPIView):
+ queryset = ImageDeployments.objects.select_related().all()
+ serializer_class = ImageDeploymentsSerializer
+ id_serializer_class = ImageDeploymentsIdSerializer
+
+ def get_serializer_class(self):
+ no_hyperlinks = self.request.QUERY_PARAMS.get('no_hyperlinks', False)
+ if (no_hyperlinks):
+ return self.id_serializer_class
+ else:
+ return self.serializer_class
+
+ def get_queryset(self):
+ return ImageDeployments.select_by_user(self.request.user)
+
+ # update() is handled by PlanetStackRetrieveUpdateDestroyAPIView
+
+ # destroy() is handled by PlanetStackRetrieveUpdateDestroyAPIView
+
+"""
+ XXX smbaker: my intent was to create a view that would return 'new' objects
+ filled with defaults. I solved it another way, so this code may soon be
+ abandoned.
+
+class ImageDeploymentsNew(GenericAPIView):
+ serializer_class = ImageDeploymentsSerializer
+ id_serializer_class = ImageDeploymentsIdSerializer
+
+ def get(self, request, *args, **kwargs):
+ return self.makenew(request, *args, **kwargs)
+
+ def get_serializer_class(self):
+ no_hyperlinks = self.request.QUERY_PARAMS.get('no_hyperlinks', False)
+ if (no_hyperlinks):
+ return self.id_serializer_class
+ else:
+ return self.serializer_class
+
+ def makenew(self, request, *args, **kwargs):
+ obj = ImageDeployments()
+ serializer = self.get_serializer(obj)
+ return Response(serializer.data)
+"""
+
+
+
class DeploymentRoleList(generics.ListCreateAPIView):
queryset = DeploymentRole.objects.select_related().all()
serializer_class = DeploymentRoleSerializer
@@ -4945,87 +5026,6 @@
-class SiteDeploymentsList(generics.ListCreateAPIView):
- queryset = SiteDeployments.objects.select_related().all()
- serializer_class = SiteDeploymentsSerializer
- id_serializer_class = SiteDeploymentsIdSerializer
- filter_backends = (filters.DjangoFilterBackend,)
- filter_fields = ('id','created','updated','enacted','backend_status','deleted','site','deployment','tenant_id',)
-
- def get_serializer_class(self):
- no_hyperlinks = self.request.QUERY_PARAMS.get('no_hyperlinks', False)
- if (no_hyperlinks):
- return self.id_serializer_class
- else:
- return self.serializer_class
-
- def get_queryset(self):
- return SiteDeployments.select_by_user(self.request.user)
-
- def create(self, request, *args, **kwargs):
- serializer = self.get_serializer(data=request.DATA, files=request.FILES)
- if not (serializer.is_valid()):
- raise Exception("failed serializer.is_valid: " + str(serializer.errors))
- obj = serializer.object
- obj.caller = request.user
- if obj.can_update(request.user):
- return super(SiteDeploymentsList, self).create(request, *args, **kwargs)
- else:
- raise Exception("failed obj.can_update")
-
- ret = super(SiteDeploymentsList, self).create(request, *args, **kwargs)
- if (ret.status_code%100 != 200):
- raise Exception(ret.data)
-
- return ret
-
-
-class SiteDeploymentsDetail(PlanetStackRetrieveUpdateDestroyAPIView):
- queryset = SiteDeployments.objects.select_related().all()
- serializer_class = SiteDeploymentsSerializer
- id_serializer_class = SiteDeploymentsIdSerializer
-
- def get_serializer_class(self):
- no_hyperlinks = self.request.QUERY_PARAMS.get('no_hyperlinks', False)
- if (no_hyperlinks):
- return self.id_serializer_class
- else:
- return self.serializer_class
-
- def get_queryset(self):
- return SiteDeployments.select_by_user(self.request.user)
-
- # update() is handled by PlanetStackRetrieveUpdateDestroyAPIView
-
- # destroy() is handled by PlanetStackRetrieveUpdateDestroyAPIView
-
-"""
- XXX smbaker: my intent was to create a view that would return 'new' objects
- filled with defaults. I solved it another way, so this code may soon be
- abandoned.
-
-class SiteDeploymentsNew(GenericAPIView):
- serializer_class = SiteDeploymentsSerializer
- id_serializer_class = SiteDeploymentsIdSerializer
-
- def get(self, request, *args, **kwargs):
- return self.makenew(request, *args, **kwargs)
-
- def get_serializer_class(self):
- no_hyperlinks = self.request.QUERY_PARAMS.get('no_hyperlinks', False)
- if (no_hyperlinks):
- return self.id_serializer_class
- else:
- return self.serializer_class
-
- def makenew(self, request, *args, **kwargs):
- obj = SiteDeployments()
- serializer = self.get_serializer(obj)
- return Response(serializer.data)
-"""
-
-
-
class SliceTagList(generics.ListCreateAPIView):
queryset = SliceTag.objects.select_related().all()
serializer_class = SliceTagSerializer
@@ -5112,7 +5112,7 @@
serializer_class = NetworkTemplateSerializer
id_serializer_class = NetworkTemplateIdSerializer
filter_backends = (filters.DjangoFilterBackend,)
- filter_fields = ('id','created','updated','enacted','backend_status','deleted','name','description','guaranteedBandwidth','visibility','translation','sharedNetworkName','sharedNetworkId',)
+ filter_fields = ('id','created','updated','enacted','backend_status','deleted','name','description','guaranteedBandwidth','visibility','translation','sharedNetworkName','sharedNetworkId','topologyKind','controllerKind',)
def get_serializer_class(self):
no_hyperlinks = self.request.QUERY_PARAMS.get('no_hyperlinks', False)
diff --git a/planetstack/model_policies/model_policy_Network.py b/planetstack/model_policies/model_policy_Network.py
index 88c9f1d..f48b25a 100644
--- a/planetstack/model_policies/model_policy_Network.py
+++ b/planetstack/model_policies/model_policy_Network.py
@@ -1,11 +1,11 @@
from core.models import *
def handle(network):
- from core.models import SliceDeployment,NetworkDeployments
+ from core.models import SliceDeployments,NetworkDeployments
from collections import defaultdict
# network deployments are not visible to users. We must ensure
# networks are deployed at all deploymets available to their slices.
- slice_deployments = SliceDeployment.objects.all()
+ slice_deployments = SliceDeployments.objects.all()
slice_deploy_lookup = defaultdict(list)
for slice_deployment in slice_deployments:
slice_deploy_lookup[slice_deployment.slice].append(slice_deployment.deployment)
diff --git a/planetstack/model_policies/model_policy_Slice.py b/planetstack/model_policies/model_policy_Slice.py
index 7b436b4..ee34b14 100644
--- a/planetstack/model_policies/model_policy_Slice.py
+++ b/planetstack/model_policies/model_policy_Slice.py
@@ -1,13 +1,13 @@
def handle(slice):
- from core.models import SiteDeployment,SliceDeployment,Deployment,Network,NetworkSlice,NetworkTemplate
+ from core.models import SiteDeployments,SliceDeployments,Deployment,Network,NetworkSlice,NetworkTemplate
from collections import defaultdict
- site_deployments = SiteDeployment.objects.all()
+ site_deployments = SiteDeployments.objects.all()
site_deploy_lookup = defaultdict(list)
for site_deployment in site_deployments:
site_deploy_lookup[site_deployment.site].append(site_deployment.deployment)
- slice_deployments = SliceDeployment.objects.all()
+ slice_deployments = SliceDeployments.objects.all()
slice_deploy_lookup = defaultdict(list)
for slice_deployment in slice_deployments:
slice_deploy_lookup[slice_deployment.slice].append(slice_deployment.deployment)
@@ -19,7 +19,7 @@
for expected_deployment in expected_deployments:
if slice not in slice_deploy_lookup or \
expected_deployment not in slice_deploy_lookup[slice]:
- sd = SliceDeployment(slice=slice, deployment=expected_deployment)
+ sd = SliceDeployments(slice=slice, deployment=expected_deployment)
sd.save()
# make sure slice has at least 1 public and 1 private networkd
diff --git a/planetstack/model_policies/model_policy_User.py b/planetstack/model_policies/model_policy_User.py
index cc8bbe6..6118a7b 100644
--- a/planetstack/model_policies/model_policy_User.py
+++ b/planetstack/model_policies/model_policy_User.py
@@ -1,16 +1,16 @@
from core.models import *
def handle(user):
- from core.models import Deployment,SiteDeployment,UserDeployment
+ from core.models import Deployment,SiteDeployments,UserDeployments
from collections import defaultdict
deployments = Deployment.objects.all()
- site_deployments = SiteDeployment.objects.all()
+ site_deployments = SiteDeployments.objects.all()
site_deploy_lookup = defaultdict(list)
for site_deployment in site_deployments:
site_deploy_lookup[site_deployment.site].append(site_deployment.deployment)
user_deploy_lookup = defaultdict(list)
- for user_deployment in UserDeployment.objects.all():
+ for user_deployment in UserDeployments.objects.all():
user_deploy_lookup[user_deployment.user].append(user_deployment.deployment)
all_deployments = Deployment.objects.filter()
@@ -27,6 +27,6 @@
if not user in user_deploy_lookup or \
expected_deployment not in user_deploy_lookup[user]:
# add new record
- ud = UserDeployment(user=user, deployment=expected_deployment)
+ ud = UserDeployments(user=user, deployment=expected_deployment)
ud.save()
diff --git a/planetstack/openstack_observer/steps/__init__.py b/planetstack/openstack_observer/steps/__init__.py
index 74f38b7..0151af3 100644
--- a/planetstack/openstack_observer/steps/__init__.py
+++ b/planetstack/openstack_observer/steps/__init__.py
@@ -12,5 +12,5 @@
#from .sync_roles import SyncRoles
#from .sync_nodes import SyncNodes
#from .sync_images import SyncImages
-#from .sync_image_deployments import SyncImageDeployment
+#from .sync_image_deployments import SyncImageDeployments
#from .garbage_collector import GarbageCollector
diff --git a/planetstack/openstack_observer/steps/sync_image_deployments.py b/planetstack/openstack_observer/steps/sync_image_deployments.py
index 4bdad87..20c22a2 100644
--- a/planetstack/openstack_observer/steps/sync_image_deployments.py
+++ b/planetstack/openstack_observer/steps/sync_image_deployments.py
@@ -5,24 +5,24 @@
from planetstack.config import Config
from observer.openstacksyncstep import OpenStackSyncStep
from core.models import Deployment
-from core.models import Image, ImageDeployment
+from core.models import Image, ImageDeployments
from util.logger import Logger, logging
logger = Logger(level=logging.INFO)
-class SyncImageDeployment(OpenStackSyncStep):
- provides=[ImageDeployment]
+class SyncImageDeployments(OpenStackSyncStep):
+ provides=[ImageDeployments]
requested_interval=0
def fetch_pending(self, deleted):
if (deleted):
return []
- # smbaker: commented out automatic creation of ImageDeployment as
+ # smbaker: commented out automatic creation of ImageDeployments as
# as they will now be configured in GUI. Not sure if this is
# sufficient.
# # ensure images are available across all deployments
-# image_deployments = ImageDeployment.objects.all()
+# image_deployments = ImageDeployments.objects.all()
# image_deploy_lookup = defaultdict(list)
# for image_deployment in image_deployments:
# image_deploy_lookup[image_deployment.image].append(image_deployment.deployment)
@@ -33,11 +33,11 @@
# for expected_deployment in expected_deployments:
# if image not in image_deploy_lookup or \
# expected_deployment not in image_deploy_lookup[image]:
-# id = ImageDeployment(image=image, deployment=expected_deployment)
+# id = ImageDeployments(image=image, deployment=expected_deployment)
# id.save()
# now we return all images that need to be enacted
- return ImageDeployment.objects.filter(Q(enacted__lt=F('updated')) | Q(enacted=None))
+ return ImageDeployments.objects.filter(Q(enacted__lt=F('updated')) | Q(enacted=None))
def sync_record(self, image_deployment):
logger.info("Working on image %s on deployment %s" % (image_deployment.image.name, image_deployment.deployment.name))
diff --git a/planetstack/openstack_observer/steps/sync_site_deployments.py b/planetstack/openstack_observer/steps/sync_site_deployments.py
index 27b8648..b5e9f9a 100644
--- a/planetstack/openstack_observer/steps/sync_site_deployments.py
+++ b/planetstack/openstack_observer/steps/sync_site_deployments.py
@@ -6,9 +6,9 @@
from core.models.site import *
from observer.ansible import *
-class SyncSiteDeployment(OpenStackSyncStep):
+class SyncSiteDeployments(OpenStackSyncStep):
requested_interval=0
- provides=[SiteDeployment, Site]
+ provides=[SiteDeployments, Site]
def sync_record(self, site_deployment):
diff --git a/planetstack/openstack_observer/steps/sync_site_privileges.py b/planetstack/openstack_observer/steps/sync_site_privileges.py
index 78da7b2..d07b279 100644
--- a/planetstack/openstack_observer/steps/sync_site_privileges.py
+++ b/planetstack/openstack_observer/steps/sync_site_privileges.py
@@ -3,7 +3,7 @@
from django.db.models import F, Q
from planetstack.config import Config
from observer.openstacksyncstep import OpenStackSyncStep
-from core.models import User, UserDeployment, SitePrivilege, SiteDeployment
+from core.models import User, UserDeployments, SitePrivilege, SiteDeployments
class SyncSitePrivileges(OpenStackSyncStep):
requested_interval=0
@@ -18,9 +18,9 @@
def sync_record(self, site_priv):
# sync site privileges at all site deployments
- site_deployments = SiteDeployment.objects.filter(site=site_priv.site)
+ site_deployments = SiteDeployments.objects.filter(site=site_priv.site)
for site_deployment in site_deployments:
- user_deployments = UserDeployment.objects.filter(deployment=site_deployment.deployment)
+ user_deployments = UserDeployments.objects.filter(deployment=site_deployment.deployment)
if user_deployments:
kuser_id = user_deployments[0].kuser_id
driver = self.driver.admin_driver(deployment=site_deployment.deployment.name)
diff --git a/planetstack/openstack_observer/steps/sync_sites.py b/planetstack/openstack_observer/steps/sync_sites.py
index 4672878..c560a6a 100644
--- a/planetstack/openstack_observer/steps/sync_sites.py
+++ b/planetstack/openstack_observer/steps/sync_sites.py
@@ -14,7 +14,7 @@
site.save()
def delete_record(self, site):
- site_deployments = SiteDeployment.objects.filter(site=site)
- site_deployment_deleter = SyncSiteDeployment().delete_record
+ site_deployments = SiteDeployments.objects.filter(site=site)
+ site_deployment_deleter = SyncSiteDeployments().delete_record
for site_deployment in site_deployments:
site_deployment_deleter(site_deployment)
diff --git a/planetstack/openstack_observer/steps/sync_slice_deployments.py b/planetstack/openstack_observer/steps/sync_slice_deployments.py
index 2bc2082..97196d6 100644
--- a/planetstack/openstack_observer/steps/sync_slice_deployments.py
+++ b/planetstack/openstack_observer/steps/sync_slice_deployments.py
@@ -5,23 +5,23 @@
from django.db.models import F, Q
from planetstack.config import Config
from observer.openstacksyncstep import OpenStackSyncStep
-from core.models.site import Deployment, SiteDeployment
-from core.models.slice import Slice, SliceDeployment
-from core.models.userdeployments import UserDeployment
+from core.models.site import Deployment, SiteDeployments
+from core.models.slice import Slice, SliceDeployments
+from core.models.userdeployments import UserDeployments
from util.logger import Logger, logging
from observer.ansible import *
logger = Logger(level=logging.INFO)
-class SyncSliceDeployment(OpenStackSyncStep):
- provides=[SliceDeployment]
+class SyncSliceDeployments(OpenStackSyncStep):
+ provides=[SliceDeployments]
requested_interval=0
def fetch_pending(self, deleted):
if (deleted):
- return SliceDeployment.deleted_objects.all()
+ return SliceDeployments.deleted_objects.all()
else:
- return SliceDeployment.objects.filter(Q(enacted__lt=F('updated')) | Q(enacted=None))
+ return SliceDeployments.objects.filter(Q(enacted__lt=F('updated')) | Q(enacted=None))
def get_next_subnet(self, deployment=None):
# limit ourself to 10.0.x.x for now
@@ -48,7 +48,7 @@
logger.info("deployment %r has no admin_user, skipping" % slice_deployment.deployment)
return
- deployment_users = UserDeployment.objects.filter(user=slice_deployment.slice.creator,
+ deployment_users = UserDeployments.objects.filter(user=slice_deployment.slice.creator,
deployment=slice_deployment.deployment)
if not deployment_users:
logger.info("slice createor %s has not accout at deployment %s" % (slice_deployment.slice.creator, slice_deployment.deployment.name))
diff --git a/planetstack/openstack_observer/steps/sync_slice_memberships.py b/planetstack/openstack_observer/steps/sync_slice_memberships.py
index f51a96b..b1cd223 100644
--- a/planetstack/openstack_observer/steps/sync_slice_memberships.py
+++ b/planetstack/openstack_observer/steps/sync_slice_memberships.py
@@ -4,7 +4,7 @@
from planetstack.config import Config
from observer.openstacksyncstep import OpenStackSyncStep
from core.models.slice import *
-from core.models.userdeployments import UserDeployment
+from core.models.userdeployments import UserDeployments
from util.logger import Logger, logging
logger = Logger(level=logging.INFO)
@@ -22,11 +22,11 @@
def sync_record(self, slice_memb):
# sync slice memberships at all slice deployments
logger.info("syncing slice privilege: %s %s" % (slice_memb.slice.name, slice_memb.user.email))
- slice_deployments = SliceDeployment.objects.filter(slice=slice_memb.slice)
+ slice_deployments = SliceDeployments.objects.filter(slice=slice_memb.slice)
for slice_deployment in slice_deployments:
if not slice_deployment.tenant_id:
continue
- user_deployments = UserDeployment.objects.filter(deployment=slice_deployment.deployment,
+ user_deployments = UserDeployments.objects.filter(deployment=slice_deployment.deployment,
user=slice_memb.user)
if user_deployments:
kuser_id = user_deployments[0].kuser_id
diff --git a/planetstack/openstack_observer/steps/sync_slices.py b/planetstack/openstack_observer/steps/sync_slices.py
index 6d6ca46..a6073b6 100644
--- a/planetstack/openstack_observer/steps/sync_slices.py
+++ b/planetstack/openstack_observer/steps/sync_slices.py
@@ -4,7 +4,7 @@
from django.db.models import F, Q
from planetstack.config import Config
from observer.openstacksyncstep import OpenStackSyncStep
-from core.models.slice import Slice, SliceDeployment
+from core.models.slice import Slice, SliceDeployments
from util.logger import Logger, logging
from observer.steps.sync_slice_deployments import *
@@ -15,14 +15,14 @@
requested_interval=0
def sync_record(self, slice):
- for slice_deployment in SliceDeployment.objects.filter(slice=slice):
+ for slice_deployment in SliceDeployments.objects.filter(slice=slice):
# bump the 'updated' timestamp and trigger observer to update
# slice across all deployments
slice_deployment.save()
def delete_record(self, slice):
- slice_deployment_deleter = SyncSliceDeployment().delete_record
- for slice_deployment in SliceDeployment.objects.filter(slice=slice):
+ slice_deployment_deleter = SyncSliceDeployments().delete_record
+ for slice_deployment in SliceDeployments.objects.filter(slice=slice):
try:
slice_deployment_deleter(slice_deployment)
except Exception,e:
diff --git a/planetstack/openstack_observer/steps/sync_slivers.py b/planetstack/openstack_observer/steps/sync_slivers.py
index 133c0e0..8237896 100644
--- a/planetstack/openstack_observer/steps/sync_slivers.py
+++ b/planetstack/openstack_observer/steps/sync_slivers.py
@@ -4,7 +4,7 @@
from planetstack.config import Config
from observer.openstacksyncstep import OpenStackSyncStep
from core.models.sliver import Sliver
-from core.models.slice import Slice, SlicePrivilege, SliceDeployment
+from core.models.slice import Slice, SlicePrivilege, SliceDeployments
from core.models.network import Network, NetworkSlice, NetworkDeployments
from util.logger import Logger, logging
from observer.ansible import *
diff --git a/planetstack/openstack_observer/steps/sync_user_deployments.py b/planetstack/openstack_observer/steps/sync_user_deployments.py
index 69faa9f..2e8256f 100644
--- a/planetstack/openstack_observer/steps/sync_user_deployments.py
+++ b/planetstack/openstack_observer/steps/sync_user_deployments.py
@@ -5,25 +5,25 @@
from django.db.models import F, Q
from planetstack.config import Config
from observer.openstacksyncstep import OpenStackSyncStep
-from core.models.site import SiteDeployment, Deployment
+from core.models.site import SiteDeployments, Deployment
from core.models.user import User
-from core.models.userdeployments import UserDeployment
+from core.models.userdeployments import UserDeployments
from util.logger import Logger, logging
from observer.ansible import *
logger = Logger(level=logging.INFO)
-class SyncUserDeployment(OpenStackSyncStep):
- provides=[UserDeployment, User]
+class SyncUserDeployments(OpenStackSyncStep):
+ provides=[UserDeployments, User]
requested_interval=0
def fetch_pending(self, deleted):
if (deleted):
- return UserDeployment.deleted_objects.all()
+ return UserDeployments.deleted_objects.all()
else:
- return UserDeployment.objects.filter(Q(enacted__lt=F('updated')) | Q(enacted=None))
+ return UserDeployments.objects.filter(Q(enacted__lt=F('updated')) | Q(enacted=None))
def sync_record(self, user_deployment):
logger.info("sync'ing user %s at deployment %s" % (user_deployment.user, user_deployment.deployment.name))
@@ -39,7 +39,7 @@
roles = []
# setup user deployment home site roles
if user_deployment.user.site:
- site_deployments = SiteDeployment.objects.filter(site=user_deployment.user.site,
+ site_deployments = SiteDeployments.objects.filter(site=user_deployment.user.site,
deployment=user_deployment.deployment)
if site_deployments:
# need the correct tenant id for site at the deployment
@@ -50,7 +50,7 @@
if user_deployment.user.is_admin:
roles.append('admin')
else:
- raise Exception('Internal error. Missing SiteDeployment for user %s'%user_deployment.user.email)
+ raise Exception('Internal error. Missing SiteDeployments for user %s'%user_deployment.user.email)
else:
raise Exception('Siteless user %s'%user_deployment.user.email)
diff --git a/planetstack/openstack_observer/steps/sync_users.py b/planetstack/openstack_observer/steps/sync_users.py
index 242b8be..a22c213 100644
--- a/planetstack/openstack_observer/steps/sync_users.py
+++ b/planetstack/openstack_observer/steps/sync_users.py
@@ -5,20 +5,20 @@
from planetstack.config import Config
from observer.openstacksyncstep import OpenStackSyncStep
from core.models.user import User
-from core.models.userdeployments import UserDeployment
-from observer.steps.sync_user_deployments import SyncUserDeployment
+from core.models.userdeployments import UserDeployments
+from observer.steps.sync_user_deployments import SyncUserDeployments
class SyncUsers(OpenStackSyncStep):
provides=[User]
requested_interval=0
def sync_record(self, user):
- for user_deployment in UserDeployment.objects.filter(user=user):
+ for user_deployment in UserDeployments.objects.filter(user=user):
# bump the 'updated' field so user account are updated across
# deployments.
user_deployment.save()
def delete_record(self, user):
- user_deployment_deleter = SyncUserDeployment().delete_record
- for user_deployment in UserDeployment.objects.filter(user=user):
+ user_deployment_deleter = SyncUserDeployments().delete_record
+ for user_deployment in UserDeployments.objects.filter(user=user):
user_deployment_deleter(user_deployment)
diff --git a/planetstack/servcomp/migrations/0001_initial.py b/planetstack/servcomp/migrations/0001_initial.py
new file mode 100644
index 0000000..f7fd1ea
--- /dev/null
+++ b/planetstack/servcomp/migrations/0001_initial.py
@@ -0,0 +1,83 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import models, migrations
+import django.utils.timezone
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('core', '0005_network_ports'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='Composition',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('created', models.DateTimeField(default=django.utils.timezone.now, auto_now_add=True)),
+ ('updated', models.DateTimeField(default=django.utils.timezone.now, auto_now=True)),
+ ('enacted', models.DateTimeField(default=None, null=True)),
+ ('backend_status', models.CharField(default=b'Provisioning in progress', max_length=140)),
+ ('deleted', models.BooleanField(default=False)),
+ ('name', models.CharField(max_length=255)),
+ ],
+ options={
+ },
+ bases=(models.Model,),
+ ),
+ migrations.CreateModel(
+ name='CompositionService',
+ fields=[
+ ('service_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='core.Service')),
+ ],
+ options={
+ 'verbose_name': 'Service Composition Service',
+ },
+ bases=('core.service', models.Model),
+ ),
+ migrations.CreateModel(
+ name='CompositionServiceThrough',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('created', models.DateTimeField(default=django.utils.timezone.now, auto_now_add=True)),
+ ('updated', models.DateTimeField(default=django.utils.timezone.now, auto_now=True)),
+ ('enacted', models.DateTimeField(default=None, null=True)),
+ ('backend_status', models.CharField(default=b'Provisioning in progress', max_length=140)),
+ ('deleted', models.BooleanField(default=False)),
+ ('order', models.IntegerField(default=0)),
+ ('composition', models.ForeignKey(to='servcomp.Composition')),
+ ('service', models.ForeignKey(related_name=b'compositions', to='core.Service')),
+ ],
+ options={
+ 'ordering': ('order',),
+ },
+ bases=(models.Model,),
+ ),
+ migrations.CreateModel(
+ name='EndUser',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('created', models.DateTimeField(default=django.utils.timezone.now, auto_now_add=True)),
+ ('updated', models.DateTimeField(default=django.utils.timezone.now, auto_now=True)),
+ ('enacted', models.DateTimeField(default=None, null=True)),
+ ('backend_status', models.CharField(default=b'Provisioning in progress', max_length=140)),
+ ('deleted', models.BooleanField(default=False)),
+ ('email', models.CharField(max_length=255)),
+ ('firstName', models.CharField(max_length=80)),
+ ('lastName', models.CharField(max_length=80)),
+ ('macAddress', models.CharField(max_length=80)),
+ ('composition', models.ForeignKey(related_name=b'endUsers', blank=True, to='servcomp.Composition', null=True)),
+ ],
+ options={
+ },
+ bases=(models.Model,),
+ ),
+ migrations.AddField(
+ model_name='composition',
+ name='services',
+ field=models.ManyToManyField(to='core.Service', through='servcomp.CompositionServiceThrough', blank=True),
+ preserve_default=True,
+ ),
+ ]
diff --git a/planetstack/servcomp/migrations/__init__.py b/planetstack/servcomp/migrations/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/planetstack/servcomp/migrations/__init__.py
diff --git a/planetstack/syndicate_observer/syndicatelib_config/config.py b/planetstack/syndicate_observer/syndicatelib_config/config.py
deleted file mode 120000
index c2ca3ee..0000000
--- a/planetstack/syndicate_observer/syndicatelib_config/config.py
+++ /dev/null
@@ -1 +0,0 @@
-config-opencloud.py
\ No newline at end of file
diff --git a/planetstack/syndicate_observer/syndicatelib_config/config.py b/planetstack/syndicate_observer/syndicatelib_config/config.py
new file mode 100644
index 0000000..54000ff
--- /dev/null
+++ b/planetstack/syndicate_observer/syndicatelib_config/config.py
@@ -0,0 +1,73 @@
+#!/usr/bin/python
+
+# ---------------------------------
+# This is the configuration file used by the Syndicate observer.
+# It is a well-formed Python file, and will be imported into the
+# observer as a Python module. This means you can run any config-
+# generation code here you like, but all of the following global
+# variables must be defined.
+# ---------------------------------
+
+# URL to the Syndicate SMI. For example, https://syndicate-metadata.appspot.com
+SYNDICATE_SMI_URL="http://localhost:8080"
+
+# If you are going to use OpenID to authenticate the Syndicate sliver daemon,
+# this is the OpenID provider URL. It is currently used only to generate
+# identity pages for users, so you can put whatever you want here for now.
+SYNDICATE_OPENID_TRUSTROOT="http://localhost:8081"
+
+# This is the observer's user account on Syndicate. You must create it out-of-band
+# prior to using the observer, and it must be an admin user since it will
+# create other users (i.e. for slices).
+SYNDICATE_OPENCLOUD_USER="jcnelson@cs.princeton.edu"
+
+# This is the password for the observer to authenticate itself to Syndicate.
+SYNDICATE_OPENCLOUD_PASSWORD="nya"
+
+# If the observer uses public-key authentication with Syndicate, you will
+# need to identify the absolute path to its private key here. It must be
+# a 4096-bit PEM-encoded RSA key, and the Syndicate observer's user account
+# must have been given the public key on activation.
+SYNDICATE_OPENCLOUD_PKEY=None
+
+# This is the location on disk where Syndicate observer code can be found,
+# if it is not already in the Python path. This is optional.
+SYNDICATE_PYTHONPATH="/root/syndicate/build/out/python"
+
+# This is the location of the observer's private key. It must be an absolute
+# path, and refer to a 4096-bit PEM-encoded RSA key.
+SYNDICATE_PRIVATE_KEY="/opt/planetstack/syndicate_observer/syndicatelib_config/pollserver.pem"
+
+# This is the master secret used to generate secrets to seal sensitive information sent to the
+# Syndicate sliver mount daemons. It is also used to seal sensitive information
+# stored to the Django database.
+# TODO: think of a way to not have to store this on disk. Maybe we feed into the
+# observer when it starts up?
+SYNDICATE_OPENCLOUD_SECRET="e4988309a5005edb8ea185f16f607938c0fb7657e4d7609853bcb7c4884d1c92"
+
+# This is the default port number on which a Syndicate Replica Gateway
+# will be provisioned. It's a well-known port, and can be the same across
+# slivers, since in OpenCloud, an RG instance only listens to localhost.
+SYNDICATE_RG_DEFAULT_PORT=38800
+
+# This is the absolute path to the RG's storage driver (which will be automatically
+# pushed to slivers by Syndicate). See https://github.com/jcnelson/syndicate/wiki/Replica-Gateways
+SYNDICATE_RG_CLOSURE=None
+
+# This is the port number the observer listens on for GETs from the Syndicate sliver mount
+# daemons. Normally, the oserver pushes (encrypted) commands to the daemons, but if the
+# daemons are NAT'ed or temporarily partitioned, they will pull commands instead.
+SYNDICATE_HTTP_PORT=65321
+
+# This is the path to the logfile for the observer's HTTP server.
+SYNDICATE_HTTP_LOGFILE="/tmp/syndicate-observer.log"
+
+# This is the number of seconds to wait for pushing a slice credential before timing out.
+SYNDICATE_HTTP_PUSH_TIMEOUT=60
+
+# This is the port number the Syndicate sliver mount daemons listen on. The observer will
+# push commands to them on this port.
+SYNDICATE_SLIVER_PORT=65322
+
+# If true, print verbose debug messages.
+DEBUG=True
diff --git a/planetstack/templates/admin/base.html b/planetstack/templates/admin/base.html
index f11c05c..49c6791 100644
--- a/planetstack/templates/admin/base.html
+++ b/planetstack/templates/admin/base.html
@@ -12,8 +12,8 @@
<script src="{% static 'suit/js/jquery-1.9.1.min.js' %}"></script>
<script src="http://code.jquery.com/ui/1.10.4/jquery-ui.js"></script>
<link rel="stylesheet" href="http://code.jquery.com/ui/1.10.4/themes/smoothness/jquery-ui.css">
-<script type="text/javascript" src="{% static 'log4javascript-1.4.6/log4javascript.js' %}"></script>
-
+ <script type="text/javascript" src="{% static 'log4javascript-1.4.6/log4javascript.js' %}"></script>
+ <script type="text/javascript" src="{% static 'uploadTextarea.js' %}"></script>
<script type="text/javascript">var Suit = { $: $.noConflict() }; if (!$) $ = Suit.$; </script>
{% if 'SHOW_REQUIRED_ASTERISK'|suit_conf %}
diff --git a/planetstack/urlfilter/migrations/0001_initial.py b/planetstack/urlfilter/migrations/0001_initial.py
new file mode 100644
index 0000000..da06233
--- /dev/null
+++ b/planetstack/urlfilter/migrations/0001_initial.py
@@ -0,0 +1,24 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import models, migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('core', '0005_network_ports'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='UrlFilterService',
+ fields=[
+ ('service_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='core.Service')),
+ ],
+ options={
+ 'verbose_name': 'URL Filter Service',
+ },
+ bases=('core.service', models.Model),
+ ),
+ ]
diff --git a/planetstack/urlfilter/migrations/__init__.py b/planetstack/urlfilter/migrations/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/planetstack/urlfilter/migrations/__init__.py