Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

## Important notes

*JUNOS SUPPORT* - limited to upload via SCP only currently, attempts to upgrade will break things!

1. Developed on NetBox 3.4.3 and compatible (probably) with other versions, but not tested.
2. Plugin works with standalone IOS/IOS-XE boxes only. No Stacks/VSS/StackWiseVirtual at present.
3. Plugin operates with software version only, and does not consider feature set (lanlite vs lanbase, K9 vs NPE).
Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
scrapli[paramiko]
scrapli[textfsm]
junos_eznc
Empty file modified rq.sh
100644 → 100755
Empty file.
1 change: 1 addition & 0 deletions software_manager/api/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ class Meta:
"created",
"last_updated",
"image",
"supported_devicetypes",
"md5sum",
"md5sum_calculated",
"version",
Expand Down
15 changes: 15 additions & 0 deletions software_manager/choices.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@
from utilities.choices import ChoiceSet


class ImageTypeChoices(ChoiceSet):
TYPE_JUNOS = "junos"
TYPE_JUNOSSR = "junos sr"
TYPE_IOS = "ios"
TYPE_IOSXE = "iosxe"

CHOICES = (
(TYPE_JUNOS, "JUNOS"),
(TYPE_JUNOSSR, "JUNOS-SR"),
(TYPE_IOS, "IOS"),
(TYPE_IOSXE, "IOS-XE"),
)

class TaskTypeChoices(ChoiceSet):
TYPE_UPLOAD = "upload"
TYPE_UPGRADE = "upgrade"
Expand All @@ -14,10 +27,12 @@ class TaskTypeChoices(ChoiceSet):
class TaskTransferMethod(ChoiceSet):
METHOD_FTP = "ftp"
METHOD_HTTP = "http"
METHOD_SCP = "scp"

CHOICES = (
(METHOD_FTP, "ftp"),
(METHOD_HTTP, "http"),
(METHOD_SCP, "scp")
)


Expand Down
15 changes: 12 additions & 3 deletions software_manager/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@
TagFilterField,
)

from .choices import TaskStatusChoices, TaskTransferMethod, TaskTypeChoices
from .choices import TaskStatusChoices, TaskTransferMethod, TaskTypeChoices, ImageTypeChoices
from .models import GoldenImage, ScheduledTask, SoftwareImage

PLUGIN_SETTINGS = settings.PLUGINS_CONFIG.get("software_manager", dict())
CF_NAME_SW_VERSION = PLUGIN_SETTINGS.get("CF_NAME_SW_VERSION", "")
DEFAULT_TRANSFER_METHOD = PLUGIN_SETTINGS.get("DEFAULT_TRANSFER_METHOD", TaskTransferMethod.METHOD_FTP)
IMAGE_FOLDER = PLUGIN_SETTINGS.get("IMAGE_FOLDER", "")

IMAGE_FORMATS = ".bin"
IMAGE_FORMATS = ".bin,.tgz"


class ClearableFileInput(forms.ClearableFileInput):
Expand All @@ -34,14 +34,21 @@ class SoftwareImageEditForm(NetBoxModelForm):
image = forms.FileField(
required=False,
label="Image",
help_text="Image File, with .bin extension",
help_text="Image File, with .bin/.tgz extension",
widget=ClearableFileInput(attrs={"accept": IMAGE_FORMATS}),
)
md5sum = forms.CharField(
required=False,
label="MD5 Checksum",
help_text="Expected MD5 Checksum, ex: 0f58a02f3d3f1e1be8f509d2e5b58fb8",
)

supported_devicetypes = DynamicModelMultipleChoiceField(
queryset=DeviceType.objects.all(),
required=False,
label="Supported Devices",
)

version = forms.CharField(
required=True,
label="Version",
Expand All @@ -55,6 +62,8 @@ class Meta:
model = SoftwareImage
fields = [
"image",
"image_type",
"supported_devicetypes",
"md5sum",
"version",
"tags",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Generated by Django 4.1.4 on 2023-01-26 09:09

import django.core.validators
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('dcim', '0167_module_status'),
('software_manager', '0001_initial'),
]

operations = [
migrations.AddField(
model_name='softwareimage',
name='supported_devicetypes',
field=models.ManyToManyField(related_name='software_images', to='dcim.devicetype'),
),
migrations.AlterField(
model_name='softwareimage',
name='image',
field=models.FileField(blank=True, null=True, upload_to='', validators=[django.core.validators.FileExtensionValidator(allowed_extensions=['bin'])]),
),
]
19 changes: 19 additions & 0 deletions software_manager/migrations/0003_alter_softwareimage_image.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Generated by Django 4.1.4 on 2023-01-26 09:32

import django.core.validators
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('software_manager', '0002_softwareimage_supported_devicetypes_and_more'),
]

operations = [
migrations.AlterField(
model_name='softwareimage',
name='image',
field=models.FileField(blank=True, null=True, upload_to='', validators=[django.core.validators.FileExtensionValidator(allowed_extensions=['bin', '.tgz'])]),
),
]
19 changes: 19 additions & 0 deletions software_manager/migrations/0004_alter_softwareimage_image.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Generated by Django 4.1.4 on 2023-01-26 09:54

import django.core.validators
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('software_manager', '0003_alter_softwareimage_image'),
]

operations = [
migrations.AlterField(
model_name='softwareimage',
name='image',
field=models.FileField(blank=True, null=True, upload_to='software-images', validators=[django.core.validators.FileExtensionValidator(allowed_extensions=['bin', 'tgz'])]),
),
]
18 changes: 18 additions & 0 deletions software_manager/migrations/0005_softwareimage_image_type.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 4.1.4 on 2023-01-26 13:24

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('software_manager', '0004_alter_softwareimage_image'),
]

operations = [
migrations.AddField(
model_name='softwareimage',
name='image_type',
field=models.CharField(default='junos', max_length=255),
),
]
19 changes: 16 additions & 3 deletions software_manager/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from rq.job import Job
from utilities.querysets import RestrictedQuerySet

from .choices import TaskFailReasonChoices, TaskStatusChoices, TaskTransferMethod, TaskTypeChoices
from .choices import TaskFailReasonChoices, TaskStatusChoices, TaskTransferMethod, TaskTypeChoices, ImageTypeChoices

PLUGIN_SETTINGS = settings.PLUGINS_CONFIG.get("software_manager", dict())
CF_NAME_SW_VERSION = PLUGIN_SETTINGS.get("CF_NAME_SW_VERSION", "")
Expand All @@ -24,11 +24,24 @@

class SoftwareImage(NetBoxModel):
image = models.FileField(
upload_to=f"{IMAGE_FOLDER}/",
validators=[FileExtensionValidator(allowed_extensions=["bin"])],
upload_to=f"{IMAGE_FOLDER}",
validators=[FileExtensionValidator(allowed_extensions=["bin","tgz"])],
null=True,
blank=True,
)

image_type = models.CharField(
max_length=255,
choices=ImageTypeChoices,
default=ImageTypeChoices.TYPE_JUNOS,
)


supported_devicetypes = models.ManyToManyField(
to=DeviceType,
related_name="software_images",
)

md5sum = models.CharField(
max_length=36,
blank=True,
Expand Down
20 changes: 19 additions & 1 deletion software_manager/tables.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
{% endif %}
"""


SW_LIST_DOWNLOAD_IMAGE = """
{% if record.image_exists %}
<a href="{{ record.image.url }}" target="_blank" class="btn btn-sm btn-primary" title="Download Image">
Expand Down Expand Up @@ -166,11 +167,24 @@ class SoftwareImageListTable(NetBoxTable):
verbose_name="Version",
orderable=False,
)

image_type = tables.Column(
verbose_name = "Image Type",
orderable = False,
)

size = tables.TemplateColumn(
verbose_name="Size",
template_code=SW_LIST_SIZE,
orderable=False,
)

supported_devicetypes=tables.ManyToManyColumn(
orderable=False,
verbose_name = "Supported Device Types",
linkify_item=True
)

md5sum = tables.TemplateColumn(
verbose_name="MD5 Checksum",
template_code=SW_LIST_MD5SUM,
Expand All @@ -189,8 +203,10 @@ class Meta(NetBoxTable.Meta):
"pk",
"id",
"filename",
"image_type",
"version",
"size",
"supported_devicetypes",
"md5sum",
"tags",
"actions",
Expand All @@ -199,8 +215,10 @@ class Meta(NetBoxTable.Meta):
)
default_columns = (
"filename",
"image_type",
"version",
"size",
"supported_devicetypes",
"md5sum",
"tags",
"actions",
Expand Down Expand Up @@ -231,7 +249,7 @@ class GoldenImageListTable(NetBoxTable):
progress = tables.TemplateColumn(
template_code=GOLDEN_IMAGE_PROGRESS_GRAPH,
orderable=False,
verbose_name="Progress",
verbose_name="Compliance",
)

actions = tables.TemplateColumn(
Expand Down
Loading