Skip to content

Commit

Permalink
Add NSO integration - initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
romanukes committed Oct 27, 2023
1 parent 511ac7d commit 45e31fd
Show file tree
Hide file tree
Showing 32 changed files with 1,955 additions and 2 deletions.
6 changes: 5 additions & 1 deletion development/creds.example.env
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,15 @@ NAUTOBOT_TOWER_PASSWORD="admin"
# - Grafana --------------------------
# GRAFANA_API_KEY="changeme"

# - IPFabric ---------------------
# - IPFabric -------------------------
# IPFABRIC_API_TOKEN="changeme"

# - Cisco Meraki ---------------------
# MERAKI_API_KEY="changeme"

# - Palo Alto Panorama ---------------
# PANORAMA_PASSWORD="changeme"

# - Cisco NSO ------------------------
# NSO_USERNAME="changeme"
# NSO_PASSWORD="changeme"
6 changes: 6 additions & 0 deletions development/development.env
Original file line number Diff line number Diff line change
Expand Up @@ -94,3 +94,9 @@ NAUTOBOT_CHATOPS_ENABLE_MERAKI="False"
NAUTOBOT_CHATOPS_ENABLE_PANORAMA="False"
PANORAMA_HOST="https://panorama.example.com"
PANORAMA_USER="admin"

# - Cisco NSO ------------------------
NAUTOBOT_CHATOPS_ENABLE_NSO="False"
# NSO_URL="https://nso.example.com"
# NSO_USERNAME="admin"
# NSO_PASSWORD="admin"
1 change: 1 addition & 0 deletions development/mattermost/dump.sql
Original file line number Diff line number Diff line change
Expand Up @@ -1597,6 +1597,7 @@ INSERT INTO `Commands` VALUES ('f74t71u6p7rpbmz7ruebja7ana','uqydyxkx4tykinw5z5u
INSERT INTO `Commands` VALUES ('j5pnszdfcpbt3f6yfs63o5bwhw','t9irqwjni3dozf3yx6tzak7k3w',1685532127072,1685532127072,0,'jactwicuqb8bu8pau8mgjydzeo','35odngbgr7yw3bf13o8kg85ngh','meraki','P','','',0,'','','Cisco Meraki','Cisco Meraki Slash Command','http://nautobot:8080/api/plugins/chatops/mattermost/slash_command/','');
INSERT INTO `Commands` VALUES ('d9irq7zuwt84pr77crnteso6da','rmdpfdjhnpg988e7ujzyom4euh',1684146546769,1684152166227,0,'jactwicuqb8bu8pau8mgjydzeo','35odngbgr7yw3bf13o8kg85ngh','nautobot','P','','',0,'','','Nautobot','Nautobot Slash Command','http://nautobot:8080/api/plugins/chatops/mattermost/slash_command/','');
INSERT INTO `Commands` VALUES ('uooffhygyigtfb4454k9yxm81h','6nf5cmz1ft8bdfykz46cs5pofo',1685702889199,1685702889199,0,'jactwicuqb8bu8pau8mgjydzeo','35odngbgr7yw3bf13o8kg85ngh','panorama','P','','',0,'','','Panorama','Panorama Slash Command','http://nautobot:8080/api/plugins/chatops/mattermost/slash_command/','');
INSERT INTO `Commands` VALUES ('tl5j19us89eftebtuj6fdplzqs','j9bcga71hl4lreaczecen7i5dz',1685832245312,1685832245312,0,'jactwicuqb8bu8pau8mgjydzeo','35odngbgr7yw3bf13o8kg85ngh','nso','P','','',0,'','','NSO','NSO Slash Command','http://nautobot:8080/api/plugins/chatops/mattermost/slash_command/','');
INSERT INTO `Drafts` VALUES (1684146834706,1684335673276,1684335673276,'jactwicuqb8bu8pau8mgjydzeo','8sz36rga1in69gaunpogq95r1w','','/nautobot','{}','[]','null');
INSERT INTO `IR_System` VALUES ('DatabaseVersion','0.63.0');
INSERT INTO `IR_UserInfo` VALUES ('jactwicuqb8bu8pau8mgjydzeo',1684387012504,'{\"disable_daily_digest\": false, \"disable_weekly_digest\": false}');
Expand Down
1 change: 1 addition & 0 deletions development/mattermost/nautobot_bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"meraki": "t9irqwjni3dozf3yx6tzak7k3w", # nosec
"nautobot": "rmdpfdjhnpg988e7ujzyom4euh", # nosec
"panorama": "6nf5cmz1ft8bdfykz46cs5pofo", # nosec
"nso": "j9bcga71hl4lreaczecen7i5dz", # nosec
}

for command, token in _COMMAND_TOKENS.items():
Expand Down
6 changes: 6 additions & 0 deletions development/nautobot_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,12 @@
"panorama_host": os.environ.get("PANORAMA_HOST"),
"panorama_password": os.environ.get("PANORAMA_PASSWORD"),
"panorama_user": os.environ.get("PANORAMA_USER"),
# - Cisco NSO ------------------------
"enable_nso": is_truthy(os.getenv("NAUTOBOT_CHATOPS_ENABLE_NSO")),
"nso_url": os.environ.get("NSO_URL"),
"nso_username": os.environ.get("NSO_USERNAME"),
"nso_password": os.environ.get("NSO_PASSWORD"),
"nso_request_timeout": os.environ.get("NSO_REQUEST_TIMEOUT", 60),
},
}

Expand Down
10 changes: 9 additions & 1 deletion nautobot_chatops/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ class NautobotChatOpsConfig(NautobotAppConfig):
"grafana_default_timespan": "",
"grafana_org_id": 1,
"grafana_default_tz": "",
# - IPFabric ---------------------
# - IPFabric -------------------------
"ipfabric_api_token": "",
"ipfabric_host": "",
"ipfabric_timeout": "",
Expand All @@ -116,6 +116,11 @@ class NautobotChatOpsConfig(NautobotAppConfig):
"panorama_host": "",
"panorama_password": "",
"panorama_user": "",
# - Cisco NSO ------------------------
"nso_url": "",
"nso_username": "",
"nso_password": "",
"nso_request_timeout": "",
}
constance_config = {
"fallback_chatops_user": ConstanceConfigItem(default="chatbot", help_text="Enable Mattermost Chat Platform."),
Expand All @@ -142,6 +147,9 @@ class NautobotChatOpsConfig(NautobotAppConfig):
"enable_panorama": ConstanceConfigItem(
default=False, help_text="Enable Panorama Integration.", field_type=bool
),
"enable_nso": ConstanceConfigItem(
default=False, help_text="Enable NSO Integration.", field_type=bool
),
}

caching_config = {}
Expand Down
Empty file.
17 changes: 17 additions & 0 deletions nautobot_chatops/integrations/nso/exceptions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
"""Custom Exceptions for the nautobot_plugin_chatops_nso plugin."""


class CommunicationError(Exception):
"""Error communicating with NSO."""


class DeviceNotFound(Exception):
"""Device not found in NSO."""


class DeviceNotSupported(Exception):
"""Device not supported in NSO."""


class DeviceLocked(Exception):
"""Device not reachable in NSO."""
26 changes: 26 additions & 0 deletions nautobot_chatops/integrations/nso/forms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
"""Forms for Nautobot."""

from django.forms import ModelForm, CharField
from nautobot.utilities.forms import BootstrapMixin
from nautobot.dcim.models.devices import Platform, DeviceRole
from nautobot.utilities.forms import DynamicModelChoiceField
from nautobot_plugin_chatops_nso.models import CommandFilter


class CommandFilterForm(BootstrapMixin, ModelForm):
"""Form for editing command filters."""

command = CharField(
max_length=200, help_text=" Supports <a href='https://pythex.org/' target='_blank'>Regular Expression</a>."
)
device_role = DynamicModelChoiceField(queryset=DeviceRole.objects.all())
platform = DynamicModelChoiceField(
queryset=Platform.objects.all(),
)

class Meta:
"""Metaclass attributes of the command filters form."""

model = CommandFilter

fields = ("command", "device_role", "platform")
14 changes: 14 additions & 0 deletions nautobot_chatops/integrations/nso/jinja_filters.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
"""Custom filters for nautobot_plugin_chatops_nso."""
from django_jinja import library
from nautobot_plugin_chatops_nso.nso import NSOClient


@library.filter
def get_nso_sync_status(device_name):
"""Pull NSO sync status for specified device."""
nso = NSOClient()
try:
response = nso.sync_status(device_name)
return response
except Exception: # pylint: disable=W0703
return "N/A"
20 changes: 20 additions & 0 deletions nautobot_chatops/integrations/nso/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
"""Django models for recording user interactions with Nautobot."""
from django.db import models
from nautobot.core.models import BaseModel


class CommandFilter(BaseModel):
"""An allowed command tied to a given object."""

command = models.CharField(max_length=200, help_text="Standard regex supported.")
device_role = models.ForeignKey(to="extras.Role", on_delete=models.CASCADE)
platform = models.ForeignKey(to="dcim.Platform", on_delete=models.CASCADE)

def __str__(self):
"""String representation of an CommandFilter."""
return f'cmd: "{self.command}; on: {self.device_role}:{self.platform}'

class Meta:
"""Meta-attributes of an CommandFilter."""

ordering = ["command", "device_role", "platform"]
41 changes: 41 additions & 0 deletions nautobot_chatops/integrations/nso/navigation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
"""Custom navigation options for the nautobot_plugin_chatops_nso plugin."""
from nautobot.core.apps import NavMenuTab, NavMenuGroup, NavMenuItem, NavMenuButton
from nautobot.utilities.choices import ButtonColorChoices

menu_items = (
NavMenuTab(
name="Plugins",
groups=(
NavMenuGroup(
name="NSO ChatOps",
weight=200,
items=(
NavMenuItem(
link="plugins:nautobot_plugin_chatops_nso:commandfilter_list",
name="Command Filters",
permissions=[
"nautobot_plugin_chatops_nso.view_commandfilter",
],
buttons=(
NavMenuButton(
link="plugins:nautobot_plugin_chatops_nso:commandfilter_add",
title="Command Filter",
icon_class="mdi mdi-plus-thick",
button_class=ButtonColorChoices.GREEN,
permissions=[
"nautobot_plugin_chatops_nso.add_commandfilter",
],
),
),
),
NavMenuItem(
link="plugins:nautobot_plugin_chatops_nso:nso_page",
name="NSO Instance Link",
permissions=[],
buttons=(),
),
),
),
),
),
)
Loading

0 comments on commit 45e31fd

Please sign in to comment.