Source code for nsot.models.circuit

from __future__ import unicode_literals

from django.db import models

from .. import exc, util
from .resource import Resource


[docs]class Circuit(Resource): """Represents two network Interfaces that are connected""" # A-side endpoint interface endpoint_a = models.OneToOneField( 'Interface', on_delete=models.PROTECT, db_index=True, null=False, related_name='circuit_a', verbose_name='A-side endpoint Interface', help_text='Unique ID of Interface at the A-side.' ) # Z-side endpoint interface endpoint_z = models.OneToOneField( 'Interface', on_delete=models.PROTECT, db_index=True, null=True, related_name='circuit_z', verbose_name='Z-side endpoint Interface', help_text='Unique ID of Interface at the Z-side.' ) # We are currently inferring the site_id from the parent (A-side) Interface # in the .save() method site = models.ForeignKey( 'Site', db_index=True, related_name='circuits', on_delete=models.PROTECT, help_text='Unique ID of the Site this Circuit is under.' ) name = models.CharField( max_length=255, unique=True, default='', help_text=( 'Unique display name of the Circuit. If not provided, defaults to ' "'{device_a}:{interface_a}_{device_z}:{interface_z}'" ) ) # This doesn't use the built-in SlugField since we're doing our own # slugification (django.utils.text.slugify() is too agressive) name_slug = models.CharField( db_index=True, editable=False, max_length=255, null=True, unique=True, help_text=( 'Slugified version of the name field, used for the natural key' ) ) def __unicode__(self): return u'%s' % self.name class Meta: # TODO(jathan): Benchmark queries on a large database to identify # whether we need explicit indices for this model. In my initial # testing all of the common lookup fields are already indexed so this # may not be necessary. ''' index_together = [ ('endpoint_a', 'endpoint_z'), ('site', 'name_slug'), ] ''' @property def interfaces(self): """Return interfaces associated with this circuit.""" intf_list = [self.endpoint_a, self.endpoint_z] return [i for i in intf_list if i is not None] @property def addresses(self): """Return addresses associated with this circuit.""" addresses = [a for i in self.interfaces for a in i.addresses.all()] return addresses @property def devices(self): """Return devices associated with this circuit.""" return [i.device for i in self.interfaces]
[docs] def interface_for(self, device): """ Given a Device object, return the interface attached to this Circuit which belongs to that Device. If both ends of the Circuit are attached to the Device, the A-side is returned. If neither ends of this Circuit are attached to Device, then None is returned """ if self.endpoint_a.device == device: return self.endpoint_a elif self.endpoint_z and self.endpoint_z.device == device: return self.endpoint_z else: return None
[docs] def clean_site(self, value): """Always enforce that site is set.""" if value is None: return self.endpoint_a.site_id return value
def clean_endpoint_a(self, value): if Circuit.objects.filter(endpoint_z=value).exists(): raise exc.ValidationError({ 'endpoint_a': 'Interface already used as an endpoint_z' }) return self.endpoint_a def clean_endpoint_z(self, value): if Circuit.objects.filter(endpoint_a=value).exists(): raise exc.ValidationError({ 'endpoint_z': 'Interface already used as an endpoint_a' }) return self.endpoint_z def clean_name(self, value): if value: return value # Add display name of hostname:intf_hostname:intf name = '{}_{}'.format(self.endpoint_a, self.endpoint_z) return name def clean_fields(self, exclude=None): self.site_id = self.clean_site(self.site_id) self.endpoint_a = self.clean_endpoint_a(self.endpoint_a_id) self.endpoint_z = self.clean_endpoint_z(self.endpoint_z_id) self.name = self.clean_name(self.name) self.name_slug = util.slugify(self.name) def save(self, *args, **kwargs): self.full_clean() super(Circuit, self).save(*args, **kwargs) def to_dict(self): return { 'id': self.id, 'name': self.name, 'name_slug': self.name_slug, 'endpoint_a': self.endpoint_a and self.endpoint_a.name_slug, 'endpoint_z': self.endpoint_z and self.endpoint_z.name_slug, 'attributes': self.get_attributes(), }