new data modeling for vOLT service; promote VOLTTenant fields from dicts to real fields
diff --git a/xos/services/cord/admin.py b/xos/services/cord/admin.py
index e7704d3..ccca02d 100644
--- a/xos/services/cord/admin.py
+++ b/xos/services/cord/admin.py
@@ -94,6 +94,64 @@
def queryset(self, request):
return VOLTTenant.get_tenant_objects_by_user(request.user)
+ volt_service = models.ForeignKey(VOLTService, related_name='volt_devices')
+ openflow_id = models.CharField(max_length=254, help_text="OpenFlow ID", null=True, blank=True)
+ driver = models.CharField(max_length=254, help_text="driver", null=True, blank=True)
+ access_agent = models.ForeignKey("AccessAgent", related_name='access_devices', blank=True, null=True)
+
+class AccessDeviceInline(XOSTabularInline):
+ model = AccessDevice
+ fields = ['volt_device','uplink','vlan']
+ readonly_fields = []
+ extra = 0
+# max_num = 0
+ suit_classes = 'suit-tab suit-tab-accessdevices'
+
+# @property
+# def selflink_reverse_path(self):
+# return "admin:cord_volttenant_change"
+
+class VOLTDeviceAdmin(ReadOnlyAwareAdmin):
+ list_display = ('backend_status_icon', 'openflow_id', 'driver' )
+ list_display_links = ('backend_status_icon', 'openflow_id')
+ fieldsets = [ (None, {'fields': ['backend_status_text','volt_service','openflow_id','driver','access_agent'],
+ 'classes':['suit-tab suit-tab-general']})]
+ readonly_fields = ('backend_status_text',)
+ inlines = [AccessDeviceInline]
+
+ suit_form_tabs = (('general','Details'), ('accessdevices','Access Devices'))
+
+class AccessDeviceAdmin(ReadOnlyAwareAdmin):
+ list_display = ('backend_status_icon', 'id', 'volt_device', 'uplink', 'vlan' )
+ list_display_links = ('backend_status_icon', 'id')
+ fieldsets = [ (None, {'fields': ['backend_status_text','volt_device','uplink','vlan'],
+ 'classes':['suit-tab suit-tab-general']})]
+ readonly_fields = ('backend_status_text',)
+
+ suit_form_tabs = (('general','Details'),)
+
+class AgentPortMappingInline(XOSTabularInline):
+ model = AgentPortMapping
+ fields = ['access_agent', 'mac', 'port']
+ readonly_fields = []
+ extra = 0
+# max_num = 0
+ suit_classes = 'suit-tab suit-tab-accessportmaps'
+
+# @property
+# def selflink_reverse_path(self):
+# return "admin:cord_volttenant_change"
+
+class AccessAgentAdmin(ReadOnlyAwareAdmin):
+ list_display = ('backend_status_icon', 'id', 'mac' )
+ list_display_links = ('backend_status_icon', 'id')
+ fieldsets = [ (None, {'fields': ['backend_status_text','volt_service','mac'],
+ 'classes':['suit-tab suit-tab-general']})]
+ readonly_fields = ('backend_status_text',)
+ inlines= [AgentPortMappingInline]
+
+ suit_form_tabs = (('general','Details'), ('accessportmaps', 'Port Mappings'))
+
#-----------------------------------------------------------------------------
# vCPE
#-----------------------------------------------------------------------------
@@ -398,6 +456,10 @@
admin.site.register(VOLTService, VOLTServiceAdmin)
admin.site.register(VOLTTenant, VOLTTenantAdmin)
+admin.site.register(VOLTDevice, VOLTDeviceAdmin)
+admin.site.register(AccessDevice, AccessDeviceAdmin)
+admin.site.register(AccessAgent, AccessAgentAdmin)
+
admin.site.register(VSGService, VSGServiceAdmin)
admin.site.register(VSGTenant, VSGTenantAdmin)
admin.site.register(VBNGService, VBNGServiceAdmin)
diff --git a/xos/services/cord/models.py b/xos/services/cord/models.py
index d3c380d..7c8ccab 100644
--- a/xos/services/cord/models.py
+++ b/xos/services/cord/models.py
@@ -188,15 +188,20 @@
class Meta:
app_label = "cord"
verbose_name = "vOLT Service"
- proxy = True
class VOLTTenant(Tenant):
- class Meta:
- proxy = True
-
KIND = VOLT_KIND
- default_attributes = {"s_tag": None, "c_tag": None}
+ class Meta:
+ app_label = "cord"
+ verbose_name = "vOLT Tenant"
+
+ s_tag = models.IntegerField(null=True, blank=True, help_text="s-tag")
+ c_tag = models.IntegerField(null=True, blank=True, help_text="c-tag")
+
+ # at some point, this should probably end up part of Tenant.
+ creator = models.ForeignKey("User", related_name='created_volts', blank=True, null=True)
+
def __init__(self, *args, **kwargs):
volt_services = VOLTService.get_service_objects().all()
if volt_services:
@@ -205,22 +210,6 @@
self.cached_vcpe = None
@property
- def s_tag(self):
- return self.get_attribute("s_tag", self.default_attributes["s_tag"])
-
- @s_tag.setter
- def s_tag(self, value):
- self.set_attribute("s_tag", value)
-
- @property
- def c_tag(self):
- return self.get_attribute("c_tag", self.default_attributes["c_tag"])
-
- @c_tag.setter
- def c_tag(self, value):
- self.set_attribute("c_tag", value)
-
- @property
def vcpe(self):
vcpe = self.get_newest_subscribed_tenant(VSGTenant)
if not vcpe:
@@ -247,28 +236,6 @@
return None
return subs[0]
- @property
- def creator(self):
- if getattr(self, "cached_creator", None):
- return self.cached_creator
- creator_id=self.get_attribute("creator_id")
- if not creator_id:
- return None
- users=User.objects.filter(id=creator_id)
- if not users:
- return None
- user=users[0]
- self.cached_creator = users[0]
- return user
-
- @creator.setter
- def creator(self, value):
- if value:
- value = value.id
- if (value != self.get_attribute("creator_id", None)):
- self.cached_creator=None
- self.set_attribute("creator_id", value)
-
def manage_vcpe(self):
# Each VOLT object owns exactly one VCPE object
@@ -337,9 +304,6 @@
super(VOLTTenant, self).save(*args, **kwargs)
model_policy_volt(self.pk)
- #self.manage_vcpe()
- #self.manage_subscriber()
- #self.cleanup_orphans()
def delete(self, *args, **kwargs):
self.cleanup_vcpe()
@@ -356,6 +320,45 @@
volt.manage_subscriber()
volt.cleanup_orphans()
+class VOLTDevice(PlCoreBase):
+ class Meta:
+ app_label = "cord"
+
+ volt_service = models.ForeignKey(VOLTService, related_name='volt_devices')
+ openflow_id = models.CharField(max_length=254, help_text="OpenFlow ID", null=True, blank=True)
+ driver = models.CharField(max_length=254, help_text="driver", null=True, blank=True)
+ access_agent = models.ForeignKey("AccessAgent", related_name='volt_devices', blank=True, null=True)
+
+ def __unicode__(self): return u'%s' % (self.openflow_id)
+
+class AccessDevice(PlCoreBase):
+ class Meta:
+ app_label = "cord"
+
+ volt_device = models.ForeignKey(VOLTDevice, related_name='access_devices')
+ uplink = models.IntegerField(null=True, blank=True)
+ vlan = models.IntegerField(null=True, blank=True)
+
+ def __unicode__(self): return u'%d:%d' % (self.uplink,self.vlan)
+
+class AccessAgent(PlCoreBase):
+ class Meta:
+ app_label = "cord"
+
+ volt_service = models.ForeignKey(VOLTService, related_name='access_agents')
+ mac = models.CharField(max_length=32, help_text="MAC Address or Access Agent", null=True, blank=True)
+
+ def __unicode__(self): return u'%s' % (self.mac)
+
+class AgentPortMapping(PlCoreBase):
+ class Meta:
+ app_label = "cord"
+
+ access_agent = models.ForeignKey(AccessAgent, related_name='access_devices')
+ mac = models.CharField(max_length=32, help_text="MAC Address", null=True, blank=True)
+ port = models.CharField(max_length=32, help_text="Openflow port ID", null=True, blank=True)
+
+
# -------------------------------------------
# VCPE
# -------------------------------------------