Skip to content

Commit

Permalink
Merge pull request #2 from respawner/master
Browse files Browse the repository at this point in the history
Sync upstream changes
  • Loading branch information
charlesmonson committed Oct 11, 2018
2 parents d1b56cd + b024b0e commit b645d7e
Show file tree
Hide file tree
Showing 97 changed files with 16,363 additions and 445 deletions.
4 changes: 2 additions & 2 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
project-static/bootstrap-4.1.2-dist/* linguist-vendored
project-static/fontawesome-5.1.0/* linguist-vendored
project-static/bootstrap-4.1.3-dist/* linguist-vendored
project-static/fontawesome-5.3.1/* linguist-vendored
project-static/js/jquery-3.3.1.min.js linguist-vendored
9 changes: 5 additions & 4 deletions docs/setup/peering-manager.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,17 @@

## Operating System Setup

First we need a proper text editor, Git to get the code and Python to run it.
First we need a proper text editor, Git and Python.
We will use Git to get the code, and Python to run it.
Peering Manager is mostly tested with Python version 3 so we will setup the
machine with this version.

```
# apt install python3 python3-dev python3-pip git vim
```

Then we have to created a directory where the code will be stored and clone the
Git repository in it.
Then we have to create a directory where the code will be stored and clone the
Git repository into it.
```
# mkdir /opt/peering-manager
# cd /opt/peering-manager
Expand All @@ -36,7 +37,7 @@ Successfully installed Django-1.11.5 Jinja2-2.9.6 Markdown-2.6.9 MarkupSafe-1.0

## Configuration

Requirements being installed we can now setup Peering Manager.
After completing requirements installation we can now setup Peering Manager.
A configuration file is needed and can be copied from the included example
file.
```
Expand Down
2 changes: 1 addition & 1 deletion peering/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class TemplateField(forms.CharField):
"""
widget = forms.Textarea
default_label = 'Template'
default_helptext = '<i class="fa fa-info-circle"></i> <a href="https://github.com/respawner/peering-manager/wiki/configuration_template" target="_blank">Jinja2 template</a> syntax is supported'
default_helptext = '<i class="fa fa-info-circle"></i> <a href="https://peering-manager.readthedocs.io/en/latest/config-template/#configuration-template" target="_blank">Jinja2 template</a> syntax is supported'

def __init__(self, *args, **kwargs):
required = kwargs.pop('required', False)
Expand Down
3 changes: 1 addition & 2 deletions peering/management/commands/peeringdb_sync_as.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,4 @@ def handle(self, *args, **options):

autonomous_systems = AutonomousSystem.objects.all()
for autonomous_system in autonomous_systems:
if autonomous_system.keep_synced_with_peeringdb:
autonomous_system.sync_with_peeringdb()
autonomous_system.sync_with_peeringdb()
70 changes: 70 additions & 0 deletions peering/migrations/0017_auto_20180802_2309.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Generated by Django 2.1 on 2018-08-02 21:09

from django.db import migrations, models
import django.utils.timezone


class Migration(migrations.Migration):

dependencies = [
('peering', '0016_auto_20180726_1307'),
]

operations = [
migrations.AddField(
model_name='autonomoussystem',
name='created',
field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
preserve_default=False,
),
migrations.AddField(
model_name='community',
name='created',
field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
preserve_default=False,
),
migrations.AddField(
model_name='community',
name='updated',
field=models.DateTimeField(auto_now=True),
),
migrations.AddField(
model_name='configurationtemplate',
name='created',
field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
preserve_default=False,
),
migrations.AddField(
model_name='internetexchange',
name='created',
field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
preserve_default=False,
),
migrations.AddField(
model_name='internetexchange',
name='updated',
field=models.DateTimeField(auto_now=True),
),
migrations.AddField(
model_name='peeringsession',
name='created',
field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
preserve_default=False,
),
migrations.AddField(
model_name='peeringsession',
name='updated',
field=models.DateTimeField(auto_now=True),
),
migrations.AddField(
model_name='router',
name='created',
field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
preserve_default=False,
),
migrations.AddField(
model_name='router',
name='updated',
field=models.DateTimeField(auto_now=True),
),
]
100 changes: 62 additions & 38 deletions peering/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,15 @@
BGP_STATE_OPENCONFIRM, BGP_STATE_ESTABLISHED,
COMMUNITY_TYPE_CHOICES, COMMUNITY_TYPE_EGRESS,
COMMUNITY_TYPE_INGRESS, PLATFORM_CHOICES,
PLATFORM_JUNOS, PLATFORM_IOSXR, PLATFORM_EOS)
PLATFORM_EOS, PLATFORM_IOS, PLATFORM_IOSXR,
PLATFORM_JUNOS)
from .fields import ASNField, CommunityField
from peeringdb.api import PeeringDB
from peeringdb.models import NetworkIXLAN, PeerRecord
from utils.models import UpdatedModel
from utils.models import CreatedUpdatedModel


class AutonomousSystem(UpdatedModel):
class AutonomousSystem(CreatedUpdatedModel):
asn = ASNField(unique=True)
name = models.CharField(max_length=128)
comment = models.TextField(blank=True)
Expand Down Expand Up @@ -75,7 +76,7 @@ def get_peering_sessions_list_url(self):
return reverse('peering:as_peering_sessions', kwargs={'asn': self.asn})

def get_peering_sessions(self):
return [session for session in self.peeringsession_set.all()]
return self.peeringsession_set.all()

def get_internet_exchanges(self):
internet_exchanges = []
Expand All @@ -87,39 +88,62 @@ def get_internet_exchanges(self):
return internet_exchanges

def get_common_internet_exchanges(self):
internet_exchanges = {}
"""
Return all IX we have in common with the AS.
"""
# Get common IX networks between us and this AS
common = PeeringDB().get_common_ix_networks_for_asns(settings.MY_ASN,
self.asn)
return InternetExchange.objects.all().filter(
peeringdb_id__in=[us.id for us, _ in common])

def get_missing_peering_sessions(self, internet_exchange):
"""
Returns a tuple of IP address lists. The first element of the tuple
is the IPv6 address list. The second element of the tuple is the IPv4
address list. Each IP address of the lists is the address of a missing
peering session with the current AS.
"""
if not internet_exchange:
return None

# Get common IX networks between us and this AS
common = PeeringDB().get_common_ix_networks_for_asns(settings.MY_ASN,
self.asn)

# Divide sessions based on the IP versions
ipv6_sessions = []
ipv4_sessions = []

# For each common networks take a look at it
for us, peer in common:
ix = None
if us.ixlan_id not in internet_exchanges:
try:
ix = InternetExchange.objects.get(peeringdb_id=us.id)
except InternetExchange.DoesNotExist:
# If we don't know this IX locally but we do in PeeringDB
# Ignore it
continue

internet_exchanges[us.ixlan_id] = {
'internet_exchange': ix,
'missing_peering_sessions': []
}

# Keep record of missing peering sessions
if (peer.ipaddr6 and not PeeringSession.does_exist(
internet_exchange=ix, autonomous_system=self,
ip_address=peer.ipaddr6)):
internet_exchanges[us.ixlan_id]['missing_peering_sessions'].append(
peer.ipaddr6)
if (peer.ipaddr4 and not PeeringSession.does_exist(
internet_exchange=ix, autonomous_system=self,
ip_address=peer.ipaddr4)):
internet_exchanges[us.ixlan_id]['missing_peering_sessions'].append(
peer.ipaddr4)
# We only care about networks matching the IX we want
if us.id == internet_exchange.peeringdb_id:
# Check on the IPv6 address
if peer.ipaddr6:
try:
ip_address = ipaddress.IPv6Address(peer.ipaddr6)
if not PeeringSession.does_exist(
internet_exchange=internet_exchange,
autonomous_system=self,
ip_address=str(ip_address)):
ipv6_sessions.append(ip_address)
except ipaddress.AddressValueError:
continue

return internet_exchanges
# Check on the IPv4 address
if peer.ipaddr4:
try:
ip_address = ipaddress.IPv4Address(peer.ipaddr4)
if not PeeringSession.does_exist(
internet_exchange=internet_exchange,
autonomous_system=self,
ip_address=str(ip_address)):
ipv4_sessions.append(ip_address)
except ipaddress.AddressValueError:
continue

return (ipv6_sessions, ipv4_sessions)

def sync_with_peeringdb(self):
"""
Expand Down Expand Up @@ -151,7 +175,7 @@ def __str__(self):
return 'AS{} - {}'.format(self.asn, self.name)


class BGPSession(models.Model):
class BGPSession(CreatedUpdatedModel):
"""
Abstract class used to define common caracteristics of BGP sessions.
Expand Down Expand Up @@ -226,7 +250,7 @@ def get_bgp_state_html(self):
return mark_safe(text)


class Community(models.Model):
class Community(CreatedUpdatedModel):
name = models.CharField(max_length=128)
value = CommunityField(max_length=50)
type = models.CharField(max_length=50, choices=COMMUNITY_TYPE_CHOICES,
Expand Down Expand Up @@ -260,7 +284,7 @@ def __str__(self):
return self.name


class ConfigurationTemplate(UpdatedModel):
class ConfigurationTemplate(CreatedUpdatedModel):
name = models.CharField(max_length=128)
template = models.TextField()
comment = models.TextField(blank=True)
Expand All @@ -276,7 +300,7 @@ def __str__(self):
return self.name


class InternetExchange(models.Model):
class InternetExchange(CreatedUpdatedModel):
peeringdb_id = models.PositiveIntegerField(blank=True, null=True)
name = models.CharField(max_length=128)
slug = models.SlugField(unique=True)
Expand Down Expand Up @@ -308,7 +332,7 @@ def get_peer_list_url(self):
return reverse('peering:ix_peers', kwargs={'slug': self.slug})

def get_peering_sessions(self):
return [session for session in self.peeringsession_set.all()]
return self.peeringsession_set.all()

def get_autonomous_systems(self):
autonomous_systems = []
Expand Down Expand Up @@ -712,7 +736,7 @@ def __str__(self):
self.ip_address)


class Router(models.Model):
class Router(CreatedUpdatedModel):
name = models.CharField(max_length=128)
hostname = models.CharField(max_length=256)
platform = models.CharField(max_length=50, choices=PLATFORM_CHOICES,
Expand All @@ -729,7 +753,7 @@ def get_absolute_url(self):

def can_napalm_get_bgp_neighbors_detail(self):
return False if not self.platform else self.platform in [
PLATFORM_EOS, PLATFORM_IOSXR, PLATFORM_JUNOS
PLATFORM_EOS, PLATFORM_IOS, PLATFORM_IOSXR, PLATFORM_JUNOS
]

def get_napalm_device(self):
Expand Down
42 changes: 23 additions & 19 deletions peering/tables.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,18 @@
from utils.tables import ActionsColumn, BaseTable, SelectColumn


class PeeringSessionStateColumn(tables.TemplateColumn):
BGPSESSION_STATUS = '{{ record.get_enabled_html }}'


class BGPSessionStateColumn(tables.TemplateColumn):
template = '{{ record.get_bgp_state_html }}'

def __init__(self, *args, **kwargs):
default = kwargs.pop('default', '')
visible = kwargs.pop('visible', False)
verbose_name = kwargs.pop('verbose_name', 'State')
template_code = kwargs.pop('template_code', self.template)
super(PeeringSessionStateColumn, self).__init__(
super(BGPSessionStateColumn, self).__init__(
*args, default=default, verbose_name=verbose_name,
template_code=template_code, visible=visible, **kwargs)

Expand Down Expand Up @@ -76,7 +79,9 @@ class InternetExchangeTable(BaseTable):
name = tables.LinkColumn()
ipv6_address = tables.Column(verbose_name='IPv6 Address')
ipv4_address = tables.Column(verbose_name='IPv4 Address')
configuration_template = tables.Column(verbose_name='Template')
configuration_template = tables.RelatedLinkColumn(
verbose_name='Template', accessor='configuration_template')
router = tables.RelatedLinkColumn(verbose_name='Router', accessor='router')
actions = ActionsColumn(
template_code='<a href="{% url \'peering:ix_edit\' slug=record.slug %}" class="btn btn-sm btn-warning"><i class="fas fa-edit" aria-hidden="true"></i> Edit</a>')

Expand All @@ -86,22 +91,20 @@ class Meta(BaseTable.Meta):
'configuration_template', 'router', 'actions',)


PEERING_SESSION_STATUS = '{{ record.get_enabled_html }}'


class PeeringSessionTable(BaseTable):
"""
Table for PeeringSession lists
"""
pk = SelectColumn()
asn = tables.Column(verbose_name='ASN', accessor='autonomous_system.asn')
as_name = tables.Column(verbose_name='AS Name',
accessor='autonomous_system.name')
ix_name = tables.Column(verbose_name='IX Name',
accessor='internet_exchange.name')
as_name = tables.RelatedLinkColumn(
verbose_name='AS Name', accessor='autonomous_system',
text=lambda record: record.autonomous_system.name)
ix_name = tables.RelatedLinkColumn(verbose_name='IX Name',
accessor='internet_exchange')
ip_address = tables.Column(verbose_name='IP Address')
enabled = tables.TemplateColumn(verbose_name='Status',
template_code=PEERING_SESSION_STATUS)
template_code=BGPSESSION_STATUS)
actions = ActionsColumn(
template_code='<div class="float-right"><a href="{% url \'peering:peering_session_details\' pk=record.pk %}" class="btn btn-sm btn-info"><i class="fas fa-info-circle" aria-hidden="true"></i> Details</a> <a href="{% url \'peering:peering_session_edit\' pk=record.pk %}" class="btn btn-sm btn-warning"><i class="fas fa-edit" aria-hidden="true"></i> Edit</a></div>')

Expand All @@ -117,12 +120,13 @@ class PeeringSessionTableForIX(BaseTable):
"""
pk = SelectColumn()
asn = tables.Column(verbose_name='ASN', accessor='autonomous_system.asn')
as_name = tables.Column(verbose_name='AS Name',
accessor='autonomous_system.name')
as_name = tables.RelatedLinkColumn(
verbose_name='AS Name', accessor='autonomous_system',
text=lambda record: record.autonomous_system.name)
ip_address = tables.Column(verbose_name='IP Address')
enabled = tables.TemplateColumn(verbose_name='Status',
template_code=PEERING_SESSION_STATUS)
session_state = PeeringSessionStateColumn(accessor='bgp_state')
template_code=BGPSESSION_STATUS)
session_state = BGPSessionStateColumn(accessor='bgp_state')
actions = ActionsColumn(
template_code='<div class="float-right"><a href="{% url \'peering:peering_session_details\' pk=record.pk %}" class="btn btn-sm btn-info"><i class="fas fa-info-circle" aria-hidden="true"></i> Details</a> <a href="{% url \'peering:peering_session_edit\' pk=record.pk %}" class="btn btn-sm btn-warning"><i class="fas fa-edit" aria-hidden="true"></i> Edit</a></div>')

Expand All @@ -138,11 +142,11 @@ class PeeringSessionTableForAS(BaseTable):
"""
pk = SelectColumn()
ip_address = tables.Column(verbose_name='IP Address')
ix = tables.Column(verbose_name='Internet Exchange',
accessor='internet_exchange.name')
ix = tables.RelatedLinkColumn(verbose_name='Internet Exchange',
accessor='internet_exchange')
enabled = tables.TemplateColumn(verbose_name='Status',
template_code=PEERING_SESSION_STATUS)
session_state = PeeringSessionStateColumn(accessor='bgp_state')
template_code=BGPSESSION_STATUS)
session_state = BGPSessionStateColumn(accessor='bgp_state')
actions = ActionsColumn(
template_code='<div class="float-right"><a href="{% url \'peering:peering_session_details\' pk=record.pk %}" class="btn btn-sm btn-info"><i class="fas fa-info-circle" aria-hidden="true"></i> Details</a> <a href="{% url \'peering:peering_session_edit\' pk=record.pk %}" class="btn btn-sm btn-warning"><i class="fas fa-edit" aria-hidden="true"></i> Edit</a></div>')

Expand Down
Loading

0 comments on commit b645d7e

Please sign in to comment.