Skip to content

Commit f8e40d6

Browse files
Merge pull request #30 from networktocode/gfm-misc-cleanup
Various cleanup and enhancements
2 parents cdc8cd2 + 3f68e94 commit f8e40d6

File tree

13 files changed

+207
-83
lines changed

13 files changed

+207
-83
lines changed

netbox_onboarding/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ class OnboardingConfig(PluginConfig):
2121
"""Plugin configuration for the netbox_onboarding plugin."""
2222

2323
name = "netbox_onboarding"
24-
verbose_name = "A plugin to easily onboard new devices."
24+
verbose_name = "Device Onboarding"
2525
version = __version__
2626
author = "Network to Code"
2727
description = "A plugin for NetBox to easily onboard new devices."

netbox_onboarding/admin.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@ class OnboardingTaskAdmin(admin.ModelAdmin):
2121

2222
list_display = (
2323
"pk",
24-
"group_id",
25-
"owner",
2624
"created_device",
2725
"ip_address",
2826
"site",

netbox_onboarding/api/serializers.py

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,14 @@
2424
class OnboardingTaskSerializer(serializers.ModelSerializer):
2525
"""Serializer for the OnboardingTask model."""
2626

27-
device = serializers.CharField(required=False, help_text="Planned device name",)
27+
site = serializers.SlugRelatedField(
28+
many=False,
29+
read_only=False,
30+
queryset=Site.objects.all(),
31+
slug_field="slug",
32+
required=True,
33+
help_text="NetBox site 'slug' value",
34+
)
2835

2936
ip_address = serializers.CharField(required=True, help_text="IP Address to reach device",)
3037

@@ -34,14 +41,9 @@ class OnboardingTaskSerializer(serializers.ModelSerializer):
3441

3542
secret = serializers.CharField(required=False, write_only=True, help_text="Device secret password",)
3643

37-
site = serializers.SlugRelatedField(
38-
many=False,
39-
read_only=False,
40-
queryset=Site.objects.all(),
41-
slug_field="slug",
42-
required=True,
43-
help_text="NetBox site 'slug' value",
44-
)
44+
port = serializers.IntegerField(required=False, help_text="Device PORT to check for online")
45+
46+
timeout = serializers.IntegerField(required=False, help_text="Timeout (sec) for device connect")
4547

4648
role = serializers.SlugRelatedField(
4749
many=False,
@@ -63,34 +65,32 @@ class OnboardingTaskSerializer(serializers.ModelSerializer):
6365
help_text="NetBox Platform 'slug' value",
6466
)
6567

66-
status = serializers.CharField(required=False, help_text="Onboarding Status")
67-
68-
failed_raison = serializers.CharField(required=False, help_text="Failure reason")
68+
created_device = serializers.CharField(required=False, read_only=True, help_text="Created device name",)
6969

70-
message = serializers.CharField(required=False, help_text="Status message")
70+
status = serializers.CharField(required=False, read_only=True, help_text="Onboarding Status")
7171

72-
port = serializers.IntegerField(required=False, help_text="Device PORT to check for online")
72+
failed_reason = serializers.CharField(required=False, read_only=True, help_text="Failure reason")
7373

74-
timeout = serializers.IntegerField(required=False, help_text="Timeout (sec) for device connect")
74+
message = serializers.CharField(required=False, read_only=True, help_text="Status message")
7575

7676
class Meta: # noqa: D106 "Missing docstring in public nested class"
7777
model = OnboardingTask
7878
fields = [
7979
"id",
80-
"device",
80+
"site",
8181
"ip_address",
8282
"username",
8383
"password",
8484
"secret",
85-
"site",
85+
"port",
86+
"timeout",
8687
"role",
8788
"device_type",
8889
"platform",
90+
"created_device",
8991
"status",
90-
"failed_raison",
92+
"failed_reason",
9193
"message",
92-
"port",
93-
"timeout",
9494
]
9595

9696
def create(self, validated_data):

netbox_onboarding/forms.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ def save(self, commit=True, **kwargs):
7979
"""Save the model, and add it and the associated credentials to the onboarding worker queue."""
8080
model = super().save(commit=commit, **kwargs)
8181
if commit:
82-
credentials = Credentials(self.data["username"], self.data["password"], self.data["secret"])
82+
credentials = Credentials(self.data.get("username"), self.data.get("password"), self.data.get("secret"))
8383
get_queue("default").enqueue("netbox_onboarding.worker.onboard_device", model.pk, credentials)
8484
return model
8585

netbox_onboarding/migrations/0001_initial.py

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
# Generated by Django 3.0.6 on 2020-05-18 13:04
1+
# Generated by Django 3.0.6 on 2020-05-18 21:58
22

3-
from django.conf import settings
43
from django.db import migrations, models
54
import django.db.models.deletion
65

@@ -11,15 +10,13 @@ class Migration(migrations.Migration):
1110

1211
dependencies = [
1312
("dcim", "0105_interface_name_collation"),
14-
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
1513
]
1614

1715
operations = [
1816
migrations.CreateModel(
1917
name="OnboardingTask",
2018
fields=[
2119
("id", models.AutoField(auto_created=True, primary_key=True, serialize=False)),
22-
("group_id", models.CharField(blank=True, max_length=255)),
2320
("ip_address", models.CharField(max_length=255, null=True)),
2421
("device_type", models.CharField(max_length=255, null=True)),
2522
("status", models.CharField(max_length=255)),
@@ -34,12 +31,6 @@ class Migration(migrations.Migration):
3431
blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to="dcim.Device"
3532
),
3633
),
37-
(
38-
"owner",
39-
models.ForeignKey(
40-
blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL
41-
),
42-
),
4334
(
4435
"platform",
4536
models.ForeignKey(

netbox_onboarding/models.py

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,12 @@
1212
limitations under the License.
1313
"""
1414
from django.db import models
15-
from django.contrib.auth.models import User
1615
from .choices import OnboardingStatusChoices, OnboardingFailChoices
1716

1817

1918
class OnboardingTask(models.Model):
2019
"""The status of each onboarding Task is tracked in the OnboardingTask table."""
2120

22-
group_id = models.CharField(max_length=255, help_text="CSV Bulk Import Group ID (optional)", blank=True)
23-
24-
owner = models.ForeignKey(
25-
to=User, on_delete=models.SET_NULL, help_text="CSV Bulk Task Owner (optional)", blank=True, null=True
26-
)
27-
2821
created_device = models.ForeignKey(to="dcim.Device", on_delete=models.SET_NULL, blank=True, null=True)
2922

3023
ip_address = models.CharField(max_length=255, help_text="primary ip address for the device", null=True)
@@ -65,3 +58,7 @@ class OnboardingTask(models.Model):
6558

6659
class Meta: # noqa: D106 "missing docstring in public nested class"
6760
ordering = ["created_on"]
61+
62+
def __str__(self):
63+
"""String representation of an OnboardingTask."""
64+
return f"{self.site} : {self.ip_address}"

netbox_onboarding/navigation.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,19 +19,21 @@
1919
PluginMenuItem(
2020
link="plugins:netbox_onboarding:onboarding_task_list",
2121
link_text="Onboarding Tasks",
22-
permissions=[],
22+
permissions=["netbox_onboarding.view_onboardingtask"],
2323
buttons=(
2424
PluginMenuButton(
2525
link="plugins:netbox_onboarding:onboarding_task_add",
2626
title="Onboard",
2727
icon_class="fa fa-plus",
2828
color=ButtonColorChoices.GREEN,
29+
permissions=["netbox_onboarding.add_onboardingtask"],
2930
),
3031
PluginMenuButton(
3132
link="plugins:netbox_onboarding:onboarding_task_import",
3233
title="Bulk Onboard",
3334
icon_class="fa fa-download",
3435
color=ButtonColorChoices.BLUE,
36+
permissions=["netbox_onboarding.add_onboardingtask"],
3537
),
3638
),
3739
),

netbox_onboarding/onboard.py

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
"""
1414

1515
import logging
16-
import os
1716
import re
1817
import socket
1918

@@ -70,13 +69,14 @@ def __str__(self):
7069
class NetdevKeeper:
7170
"""Used to maintain information about the network device during the onboarding process."""
7271

73-
def __init__(self, onboarding_task, username=None, password=None):
72+
def __init__(self, onboarding_task, username=None, password=None, secret=None):
7473
"""Initialize the network device keeper instance and ensure the required configuration parameters are provided.
7574
7675
Args:
7776
onboarding_task (OnboardingTask): Task being processed
78-
username (str): Device username (if unspecified, NAPALM_USERNAME environment variable will be used)
79-
password (str): Device password (if unspecified, NAPALM_PASSWORD environment variable will be used)
77+
username (str): Device username (if unspecified, NAPALM_USERNAME settings variable will be used)
78+
password (str): Device password (if unspecified, NAPALM_PASSWORD settings variable will be used)
79+
secret (str): Device secret password (if unspecified, NAPALM_ARGS["secret"] settings variable will be used)
8080
8181
Raises:
8282
OnboardException('fail-config'):
@@ -92,8 +92,9 @@ def __init__(self, onboarding_task, username=None, password=None):
9292
self.serial_number = None
9393
self.mgmt_ifname = None
9494
self.mgmt_pflen = None
95-
self.username = username or os.environ.get("NAPALM_USERNAME", None)
96-
self.password = password or os.environ.get("NAPALM_PASSWORD", None)
95+
self.username = username or settings.NAPALM_USERNAME
96+
self.password = password or settings.NAPALM_PASSWORD
97+
self.secret = secret or settings.NAPALM_ARGS.get("secret", None)
9798

9899
def check_reachability(self):
99100
"""Ensure that the device at the mgmt-ipaddr provided is reachable.
@@ -129,6 +130,7 @@ def guess_netmiko_device_type(**kwargs):
129130
"host": kwargs.get("host"),
130131
"username": kwargs.get("username"),
131132
"password": kwargs.get("password"),
133+
"secret": kwargs.get("secret"),
132134
}
133135

134136
try:
@@ -159,7 +161,7 @@ def get_platform_slug(self):
159161
platform_slug = self.ot.platform.slug
160162
else:
161163
platform_slug = self.guess_netmiko_device_type(
162-
host=self.ot.ip_address, username=self.username, password=self.password
164+
host=self.ot.ip_address, username=self.username, password=self.password, secret=self.secret,
163165
)
164166

165167
logging.info("PLATFORM NAME is %s", platform_slug)
@@ -233,7 +235,15 @@ def get_required_info(
233235
)
234236

235237
driver = get_network_driver(driver_name)
236-
dev = driver(hostname=mgmt_ipaddr, username=self.username, password=self.password, timeout=self.ot.timeout)
238+
optional_args = settings.NAPALM_ARGS.copy()
239+
optional_args["secret"] = self.secret
240+
dev = driver(
241+
hostname=mgmt_ipaddr,
242+
username=self.username,
243+
password=self.password,
244+
timeout=self.ot.timeout,
245+
optional_args=optional_args,
246+
)
237247

238248
dev.open()
239249
logging.info("COLLECT: device facts")
@@ -265,16 +275,13 @@ def get_mgmt_info():
265275
return (if_name, if_addr_data["prefix_length"])
266276
return (default_mgmt_if, default_mgmt_pfxlen)
267277

268-
mgmt_ifname, mgmt_pflen = get_mgmt_info()
269-
270278
# retain the attributes that will be later used by NetBox processing.
271279

272280
self.hostname = facts["hostname"]
273281
self.vendor = facts["vendor"].title()
274282
self.model = facts["model"].lower()
275283
self.serial_number = facts["serial_number"]
276-
self.mgmt_ifname = mgmt_ifname
277-
self.mgmt_pflen = mgmt_pflen
284+
self.mgmt_ifname, self.mgmt_pflen = get_mgmt_info()
278285

279286

280287
# -----------------------------------------------------------------------------

netbox_onboarding/tables.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,14 @@
1212
limitations under the License.
1313
"""
1414
import django_tables2 as tables
15-
from utilities.tables import BaseTable
15+
from utilities.tables import BaseTable, ToggleColumn
1616
from .models import OnboardingTask
1717

1818

1919
class OnboardingTaskTable(BaseTable):
2020
"""Table for displaying OnboardingTask instances."""
2121

22+
pk = ToggleColumn()
2223
site = tables.LinkColumn()
2324
platform = tables.LinkColumn()
2425
created_device = tables.LinkColumn()
@@ -47,7 +48,6 @@ class Meta(BaseTable.Meta): # noqa: D106 "Missing docstring in public nested cl
4748
model = OnboardingTask
4849
fields = (
4950
"id",
50-
"owner",
5151
"created_on",
5252
"site",
5353
"platform",

netbox_onboarding/templates/netbox_onboarding/onboarding_tasks_list.html

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,16 @@
22
{% load buttons %}
33

44
{% block content %}
5+
<div class="pull-right noprint">
6+
{% if permissions.add %}
7+
{% add_button 'plugins:netbox_onboarding:onboarding_task_add' %}
8+
{% import_button 'plugins:netbox_onboarding:onboarding_task_import' %}
9+
{% endif %}
10+
</div>
511
<h1>{% block title %}Onboarding Tasks{% endblock %}</h1>
612
<div class="row">
713
<div class="col-md-9">
8-
{% include 'utilities/obj_table.html' %}
14+
{% include 'utilities/obj_table.html' with bulk_delete_url="plugins:netbox_onboarding:onboarding_task_bulk_delete" %}
915
</div>
1016
<div class="col-md-3 noprint">
1117
{% include 'inc/search_panel.html' %}

0 commit comments

Comments
 (0)