Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6d05b1b6ca | ||
|
|
049fb045c0 | ||
|
|
9e81b94d31 | ||
|
|
18fed2c029 | ||
|
|
a02acbc561 | ||
|
|
74d648b94d | ||
|
|
e9422d70e3 |
+4
-3
@@ -9,6 +9,8 @@ Software Lifecycle Management
|
|||||||
Installation Guide
|
Installation Guide
|
||||||
~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
WARNING: This plugin is only tested with Netbox 3.2 at this time.
|
||||||
|
|
||||||
When using the Docker version of Netbox, first follow the `netbox-docker
|
When using the Docker version of Netbox, first follow the `netbox-docker
|
||||||
quickstart <https://github.com/netbox-community/netbox-docker#quickstart>`__
|
quickstart <https://github.com/netbox-community/netbox-docker#quickstart>`__
|
||||||
instructions to clone the netbox-docker repo and set up the
|
instructions to clone the netbox-docker repo and set up the
|
||||||
@@ -20,13 +22,13 @@ to install the Netbox SLM plugin:
|
|||||||
|
|
||||||
1. Add ``netbox_slm`` to the ``PLUGINS`` list in
|
1. Add ``netbox_slm`` to the ``PLUGINS`` list in
|
||||||
``configuration/extra.py``.
|
``configuration/extra.py``.
|
||||||
2. Create a ``plugin_requirements.txt`` with ``netbox-slm==0.94`` as
|
2. Create a ``plugin_requirements.txt`` with ``netbox-slm==0.98`` as
|
||||||
contents.
|
contents.
|
||||||
3. Create a ``Dockerfile-SLM`` with contents:
|
3. Create a ``Dockerfile-SLM`` with contents:
|
||||||
|
|
||||||
.. code:: dockerfile
|
.. code:: dockerfile
|
||||||
|
|
||||||
FROM netboxcommunity/netbox:v3.X.X
|
FROM netboxcommunity/netbox:v3.2.X
|
||||||
|
|
||||||
COPY ./plugin_requirements.txt /
|
COPY ./plugin_requirements.txt /
|
||||||
RUN /opt/netbox/venv/bin/pip install --no-warn-script-location -r /plugin_requirements.txt
|
RUN /opt/netbox/venv/bin/pip install --no-warn-script-location -r /plugin_requirements.txt
|
||||||
@@ -96,7 +98,6 @@ Steps
|
|||||||
|
|
||||||
$ git clone https://github.com/netbox-community/netbox
|
$ git clone https://github.com/netbox-community/netbox
|
||||||
$ cd netbox
|
$ cd netbox
|
||||||
$ git checkout f5356b8 (to pin 3.0.9)
|
|
||||||
|
|
||||||
install the virtual environment
|
install the virtual environment
|
||||||
|
|
||||||
|
|||||||
+8
-16
@@ -9,24 +9,26 @@ Software Lifecycle Management
|
|||||||
Installation Guide
|
Installation Guide
|
||||||
~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
WARNING: This plugin is only tested with Netbox 3.2 at this time.
|
||||||
|
|
||||||
When using the Docker version of Netbox, first follow the `netbox-docker
|
When using the Docker version of Netbox, first follow the `netbox-docker
|
||||||
quickstart <https://github.com/netbox-community/netbox-docker#quickstart>`__
|
quickstart <https://github.com/netbox-community/netbox-docker#quickstart>`__
|
||||||
instructions to clone the netbox-docker repo and set up the
|
instructions to clone the netbox-docker repo and set up the
|
||||||
``docker-compose.override.yml``.
|
``docker-compose.override.yml``.
|
||||||
|
|
||||||
Next, follow these instructions (based on the generic `Netbox plugin
|
Next, follow these instructions (based on the `Netbox docker variant
|
||||||
instructions <https://github.com/netbox-community/netbox-docker/wiki/Using-Netbox-Plugins>`__)
|
instructions <https://github.com/netbox-community/netbox-docker/wiki/Configuration#custom-configuration-files>`__)
|
||||||
to install the Netbox SLM plugin:
|
to install the Netbox SLM plugin:
|
||||||
|
|
||||||
1. Add ``netbox_slm`` to the ``PLUGINS`` list in
|
1. Add ``netbox_slm`` to the ``PLUGINS`` list in
|
||||||
``configuration/configuration.py``.
|
``configuration/extra.py``.
|
||||||
2. Create a ``plugin_requirements.txt`` with ``netbox-slm==0.93`` as
|
2. Create a ``plugin_requirements.txt`` with ``netbox-slm==0.98`` as
|
||||||
contents.
|
contents.
|
||||||
3. Create a ``Dockerfile-SLM`` with contents:
|
3. Create a ``Dockerfile-SLM`` with contents:
|
||||||
|
|
||||||
.. code:: dockerfile
|
.. code:: dockerfile
|
||||||
|
|
||||||
FROM netboxcommunity/netbox:v3.0.9 # The Netbox SLM plugin currently only works with v3.0.9 of Netbox due to backwards incompatible changes in newer version of Netbox
|
FROM netboxcommunity/netbox:v3.2.X
|
||||||
|
|
||||||
COPY ./plugin_requirements.txt /
|
COPY ./plugin_requirements.txt /
|
||||||
RUN /opt/netbox/venv/bin/pip install --no-warn-script-location -r /plugin_requirements.txt
|
RUN /opt/netbox/venv/bin/pip install --no-warn-script-location -r /plugin_requirements.txt
|
||||||
@@ -63,7 +65,7 @@ directory run
|
|||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
# make sure to update the version in netbox_slm/__init__.py and setup.cfg
|
# make sure to update the version in netbox_slm/__init__.py
|
||||||
$ python setup.py sdist
|
$ python setup.py sdist
|
||||||
$ twine upload dist/*
|
$ twine upload dist/*
|
||||||
|
|
||||||
@@ -87,15 +89,6 @@ Netbox Django copy with auto-reload to develop the plugin pointing to
|
|||||||
the Dockerized postgres and redis instances, basically ignoring the
|
the Dockerized postgres and redis instances, basically ignoring the
|
||||||
netbox docker runtime server.
|
netbox docker runtime server.
|
||||||
|
|
||||||
Gotcha’s
|
|
||||||
~~~~~~~~
|
|
||||||
|
|
||||||
*Netbox’s exception handler seems to supress initial Exceptions,
|
|
||||||
obfuscating missing imports or other Django related issues by re-raising
|
|
||||||
an opague error, e.g. netbox_slm plugin namespace doesnotexist. It’s
|
|
||||||
recommended to often check the runtime server or patch Netbox’s global
|
|
||||||
exception handler.*
|
|
||||||
|
|
||||||
Steps
|
Steps
|
||||||
~~~~~
|
~~~~~
|
||||||
|
|
||||||
@@ -105,7 +98,6 @@ Steps
|
|||||||
|
|
||||||
$ git clone https://github.com/netbox-community/netbox
|
$ git clone https://github.com/netbox-community/netbox
|
||||||
$ cd netbox
|
$ cd netbox
|
||||||
$ git checkout f5356b8 (to pin 3.0.9)
|
|
||||||
|
|
||||||
install the virtual environment
|
install the virtual environment
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ class SLMConfig(PluginConfig):
|
|||||||
name = 'netbox_slm'
|
name = 'netbox_slm'
|
||||||
verbose_name = 'Software Lifecycle Management'
|
verbose_name = 'Software Lifecycle Management'
|
||||||
description = 'Software Lifecycle Management'
|
description = 'Software Lifecycle Management'
|
||||||
version = '0.95'
|
version = '0.98'
|
||||||
author = 'Hedde van der Heide'
|
author = 'Hedde van der Heide'
|
||||||
author_email = 'hedde.vanderheide@ictu.nl'
|
author_email = 'hedde.vanderheide@ictu.nl'
|
||||||
base_url = 'slm'
|
base_url = 'slm'
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
# Generated by Django 3.2.9 on 2022-04-15 07:05
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('dcim', '0153_created_datetimefield'),
|
||||||
|
('virtualization', '0029_created_datetimefield'),
|
||||||
|
('netbox_slm', '0003_auto_20220407_1209'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='softwareproduct',
|
||||||
|
name='manufacturer',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='dcim.manufacturer'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='softwareproductinstallation',
|
||||||
|
name='device',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='dcim.device'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='softwareproductinstallation',
|
||||||
|
name='software_product',
|
||||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='netbox_slm.softwareproduct'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='softwareproductinstallation',
|
||||||
|
name='version',
|
||||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='netbox_slm.softwareproductversion'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='softwareproductinstallation',
|
||||||
|
name='virtualmachine',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='virtualization.virtualmachine'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='softwareproductversion',
|
||||||
|
name='software_product',
|
||||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='netbox_slm.softwareproduct'),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -17,7 +17,6 @@ class SoftwareProduct(NetBoxModel):
|
|||||||
manufacturer = models.ForeignKey(
|
manufacturer = models.ForeignKey(
|
||||||
to='dcim.Manufacturer',
|
to='dcim.Manufacturer',
|
||||||
on_delete=models.PROTECT,
|
on_delete=models.PROTECT,
|
||||||
related_name='software_products',
|
|
||||||
null=True, blank=True
|
null=True, blank=True
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -42,7 +41,6 @@ class SoftwareProductVersion(NetBoxModel):
|
|||||||
software_product = models.ForeignKey(
|
software_product = models.ForeignKey(
|
||||||
to='netbox_slm.SoftwareProduct',
|
to='netbox_slm.SoftwareProduct',
|
||||||
on_delete=models.PROTECT,
|
on_delete=models.PROTECT,
|
||||||
related_name='softwareproduct_versions'
|
|
||||||
)
|
)
|
||||||
name = models.CharField(max_length=64)
|
name = models.CharField(max_length=64)
|
||||||
|
|
||||||
@@ -67,26 +65,22 @@ class SoftwareProductInstallation(NetBoxModel):
|
|||||||
device = models.ForeignKey(
|
device = models.ForeignKey(
|
||||||
to='dcim.Device',
|
to='dcim.Device',
|
||||||
on_delete=models.PROTECT,
|
on_delete=models.PROTECT,
|
||||||
related_name='softwareproduct_installations',
|
|
||||||
null=True,
|
null=True,
|
||||||
blank=True
|
blank=True
|
||||||
)
|
)
|
||||||
virtualmachine = models.ForeignKey(
|
virtualmachine = models.ForeignKey(
|
||||||
to='virtualization.VirtualMachine',
|
to='virtualization.VirtualMachine',
|
||||||
on_delete=models.PROTECT,
|
on_delete=models.PROTECT,
|
||||||
related_name='softwareproduct_installations',
|
|
||||||
null = True,
|
null = True,
|
||||||
blank = True
|
blank = True
|
||||||
)
|
)
|
||||||
software_product = models.ForeignKey(
|
software_product = models.ForeignKey(
|
||||||
to='netbox_slm.SoftwareProduct',
|
to='netbox_slm.SoftwareProduct',
|
||||||
on_delete=models.PROTECT,
|
on_delete=models.PROTECT,
|
||||||
related_name='software_products'
|
|
||||||
)
|
)
|
||||||
version = models.ForeignKey(
|
version = models.ForeignKey(
|
||||||
to='netbox_slm.SoftwareProductVersion',
|
to='netbox_slm.SoftwareProductVersion',
|
||||||
on_delete=models.PROTECT,
|
on_delete=models.PROTECT,
|
||||||
related_name='softwareproduct_versions'
|
|
||||||
)
|
)
|
||||||
|
|
||||||
objects = RestrictedQuerySet.as_manager()
|
objects = RestrictedQuerySet.as_manager()
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import django_tables2 as tables
|
import django_tables2 as tables
|
||||||
|
|
||||||
|
from django.db.models import Count
|
||||||
from django_tables2.utils import Accessor
|
from django_tables2.utils import Accessor
|
||||||
from netbox_slm.models import SoftwareProduct, SoftwareProductVersion, SoftwareProductInstallation
|
from netbox_slm.models import SoftwareProduct, SoftwareProductVersion, SoftwareProductInstallation
|
||||||
from netbox.tables import NetBoxTable, ChoiceFieldColumn, ToggleColumn, columns
|
from netbox.tables import NetBoxTable, ChoiceFieldColumn, ToggleColumn, columns
|
||||||
@@ -45,6 +46,12 @@ class SoftwareProductTable(NetBoxTable):
|
|||||||
"installations",
|
"installations",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def order_installations(self, queryset, is_descending):
|
||||||
|
queryset = queryset.annotate(
|
||||||
|
count=Count('softwareproductinstallation__id')
|
||||||
|
).order_by(("-" if is_descending else "") + "count")
|
||||||
|
return queryset, True
|
||||||
|
|
||||||
|
|
||||||
class SoftwareProductVersionTable(NetBoxTable):
|
class SoftwareProductVersionTable(NetBoxTable):
|
||||||
"""Table for displaying SoftwareProductVersion objects."""
|
"""Table for displaying SoftwareProductVersion objects."""
|
||||||
@@ -90,6 +97,12 @@ class SoftwareProductVersionTable(NetBoxTable):
|
|||||||
"installations",
|
"installations",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def order_installations(self, queryset, is_descending):
|
||||||
|
queryset = queryset.annotate(
|
||||||
|
count=Count('softwareproductinstallation__id')
|
||||||
|
).order_by(("-" if is_descending else "") + "count")
|
||||||
|
return queryset, True
|
||||||
|
|
||||||
|
|
||||||
class SoftwareProductInstallationTable(NetBoxTable):
|
class SoftwareProductInstallationTable(NetBoxTable):
|
||||||
"""Table for displaying SoftwareProductInstallation objects."""
|
"""Table for displaying SoftwareProductInstallation objects."""
|
||||||
@@ -142,5 +155,13 @@ class SoftwareProductInstallationTable(NetBoxTable):
|
|||||||
"tags",
|
"tags",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def order_platform(self, queryset, is_descending):
|
||||||
|
queryset = queryset.order_by(("device" if is_descending else "virtualmachine"))
|
||||||
|
return queryset, True
|
||||||
|
|
||||||
|
def order_type(self, queryset, is_descending):
|
||||||
|
queryset = queryset.order_by(("device" if is_descending else "virtualmachine"))
|
||||||
|
return queryset, True
|
||||||
|
|
||||||
def render_software_product(self, value, **kwargs):
|
def render_software_product(self, value, **kwargs):
|
||||||
return f"{kwargs['record'].software_product.manufacturer.name} - {value}"
|
return f"{kwargs['record'].software_product.manufacturer.name} - {value}"
|
||||||
|
|||||||
@@ -24,6 +24,8 @@
|
|||||||
<a href="{% url 'plugins:netbox_slm:softwareproductversion' pk=version.pk %}">
|
<a href="{% url 'plugins:netbox_slm:softwareproductversion' pk=version.pk %}">
|
||||||
<span class="badge" style="color: #ffffff; background-color: #9e9e9e">{{ version }}</span>
|
<span class="badge" style="color: #ffffff; background-color: #9e9e9e">{{ version }}</span>
|
||||||
</a>
|
</a>
|
||||||
|
{% empty %}
|
||||||
|
n/a
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ class SoftwareProductView(generic.ObjectView):
|
|||||||
queryset = SoftwareProduct.objects.all()
|
queryset = SoftwareProduct.objects.all()
|
||||||
|
|
||||||
def get_extra_context(self, request, instance):
|
def get_extra_context(self, request, instance):
|
||||||
versions = instance.softwareproduct_versions.all()
|
versions = instance.softwareproductversion_set.all()
|
||||||
return {"versions": versions}
|
return {"versions": versions}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[metadata]
|
[metadata]
|
||||||
name = netbox-slm
|
name = netbox-slm
|
||||||
version = 0.95
|
version = 0.98
|
||||||
description = Software Lifecycle Management Netbox Plugin.
|
description = Software Lifecycle Management Netbox Plugin.
|
||||||
# long_description = file: README.rst
|
# long_description = file: README.rst
|
||||||
# long_description_content_type='text/x-rst'
|
# long_description_content_type='text/x-rst'
|
||||||
|
|||||||
Reference in New Issue
Block a user