Compare commits

..

14 Commits
0.6.0 ... 0.7.0

Author SHA1 Message Date
1fa07c6dc1 Bump VERSION file 2019-01-07 02:12:44 -08:00
c866bfff16 add note about breaking changes 2019-01-07 11:11:48 +01:00
44cdb73cc4 Merge pull request #109 from TakeMeNL/feature/105
#105 Change default api page size to 1000
2019-01-07 11:09:28 +01:00
20a86f0e98 Merge branch 'master' into feature/105 2019-01-07 10:47:15 +01:00
1f9ea8db53 Merge branch 'bdlamprecht-master' 2019-01-07 10:44:20 +01:00
db7daee86e formatted 2019-01-07 10:43:41 +01:00
0bae952410 Documenting reporting usage in README.md
Updated `README.md` on how to use the reporting feature of NetBox within this container.
2019-01-02 17:12:46 -07:00
34cd2cc577 Renamed devices.py to devices.py.example to set the example report to be disabled by default 2019-01-02 16:45:02 +00:00
e55580e3ae #105 Change default api page size to 1000 2018-12-27 22:12:17 +01:00
aab28d03ba Changing 'reports' from a volume to a mapped directory
This will allow eaiser interaction with the report functionality of the 'netbox' container.
2018-12-19 16:26:24 -07:00
eb09bf5364 Merge pull request #106 from ninech/ignore_missing_initializers
Ignore missing initializers
2018-12-19 17:03:56 +01:00
e46a7d2f7f Ignore missing initializers
Previously, the startup_scripts would fail if an initializer file was
not present. Now they just ignore missing files.
2018-12-19 14:25:58 +01:00
03eb153da4 Mention the #netbox-docker Slack channel 2018-11-12 21:54:14 +01:00
7675e8fc03 Update Breaking Changes list 2018-10-31 14:37:07 +01:00
18 changed files with 169 additions and 25 deletions

View File

@ -9,6 +9,12 @@ Before raising an issue here, answer the following questions for yourself, pleas
(Otherwise ask on the Netbox mailing list, please: https://groups.google.com/d/forum/netbox-discuss) (Otherwise ask on the Netbox mailing list, please: https://groups.google.com/d/forum/netbox-discuss)
* Have you looked through the issues already resolved? * Have you looked through the issues already resolved?
Please try this means to get help before opening an issue here:
* On the networktocode Slack in the #netbox-docker channel: http://slack.networktocode.com/
* On the networktocode Slack in the #netbox channel: http://slack.networktocode.com/
* On the Netbox mailing list: https://groups.google.com/d/forum/netbox-discuss
--> -->
## Current Behavior ## Current Behavior
@ -30,17 +36,19 @@ The output of `git rev-parse HEAD`: `XXXXX`
The command you used to start the project: `XXXXX` The command you used to start the project: `XXXXX`
The output of `docker-compose logs netbox`: The output of `docker-compose logs netbox`:
<!-- if your log is very long, create a Gist instead: https://gist.github.com -->
```
LOG LOG LOG
```
<!-- <!--
If you have get any 5xx http error, else delete this section. If your log is very long, create a Gist instead (and post the link to it): https://gist.github.com
If your log is very long, create a Gist instead: https://gist.github.com -->
```
LOG LOG LOG
```
The output of `docker-compose logs nginx`:
<!--
Only if you have gotten a 5xx http error, else delete this section.
If your log is very long, create a Gist instead (and post the link to it): https://gist.github.com
--> -->
The output of `docker-compose logs nginx`:
``` ```
LOG LOG LOG LOG LOG LOG

View File

@ -131,6 +131,18 @@ However, if you don't need this functionality, leave these blank.
[napalm-doc]: http://napalm.readthedocs.io/en/latest/index.html [napalm-doc]: http://napalm.readthedocs.io/en/latest/index.html
[netbox-napalm-doc]: https://netbox.readthedocs.io/en/latest/configuration/optional-settings/#napalm_username [netbox-napalm-doc]: https://netbox.readthedocs.io/en/latest/configuration/optional-settings/#napalm_username
### Customizable Reporting
NetBox includes [customized reporting][netbox-reports-doc] that allows the user to write Python code and determine the validity of the data within NetBox.
The `REPORTS_ROOT` variable is setup as a mapped directory within this Docker container to `/reports/` and includes the example directly from the documentation for `devices.py`.
However, it has been renamed to `devices.py.example` which prevents NetBox from recognizing it as a valid report.
This was done to avoid unnessary issues from being opened when the default does not work for someone's expectations.
To re-enable this default report, simply rename `devices.py.example` to `devices.py` and browse within the WebUI to `/extras/reports/`.
You can also dynamically add any other report to this same directory and NetBox will be able to see it without restarting the container.
[netbox-reports-doc]: https://netbox.readthedocs.io/en/stable/additional-features/reports/
### Custom Initialization Code (e.g. Automatically Setting Up Custom Fields) ### Custom Initialization Code (e.g. Automatically Setting Up Custom Fields)
When using `docker-compose`, all the python scripts present in `/opt/netbox/startup_scripts` will automatically be executed after the application boots in the context of `./manage.py`. When using `docker-compose`, all the python scripts present in `/opt/netbox/startup_scripts` will automatically be executed after the application boots in the context of `./manage.py`.
@ -368,6 +380,9 @@ Compare the version with the list below to check whether a breaking change was i
The following is a list of breaking changes of the `netbox-docker` project: The following is a list of breaking changes of the `netbox-docker` project:
* 0.7.0: The value of the `MAX_PAGE_SIZE` environment variable was changed to `1000`, which is the default of Netbox.
* 0.6.0: The naming of the default startup_scripts were changed.
If you overwrite them, you may need to adjust these scripts.
* 0.5.0: Alpine was updated to 3.8, `*.env` moved to `/env` folder * 0.5.0: Alpine was updated to 3.8, `*.env` moved to `/env` folder
* 0.4.0: In order to use Netbox webhooks you need to add Redis and a netbox-worker to your docker-compose.yml. * 0.4.0: In order to use Netbox webhooks you need to add Redis and a netbox-worker to your docker-compose.yml.
* 0.3.0: Field `filterable: <boolean` was replaced with field `filter_logic: loose/exact/disabled`. It will default to `CF_FILTER_LOOSE=loose` when not defined. * 0.3.0: Field `filterable: <boolean` was replaced with field `filter_logic: loose/exact/disabled`. It will default to `CF_FILTER_LOOSE=loose` when not defined.

View File

@ -1 +1 @@
0.6.0 0.7.0

View File

@ -15,10 +15,10 @@ services:
- ./startup_scripts:/opt/netbox/startup_scripts:ro - ./startup_scripts:/opt/netbox/startup_scripts:ro
- ./initializers:/opt/netbox/initializers:ro - ./initializers:/opt/netbox/initializers:ro
- ./configuration:/etc/netbox/config:ro - ./configuration:/etc/netbox/config:ro
- ./reports:/etc/netbox/reports:ro
- netbox-nginx-config:/etc/netbox-nginx/ - netbox-nginx-config:/etc/netbox-nginx/
- netbox-static-files:/opt/netbox/netbox/static - netbox-static-files:/opt/netbox/netbox/static
- netbox-media-files:/opt/netbox/netbox/media - netbox-media-files:/opt/netbox/netbox/media
- netbox-report-files:/etc/netbox/reports:ro
netbox-worker: netbox-worker:
<<: *netbox <<: *netbox
depends_on: depends_on:

2
env/netbox.env vendored
View File

@ -12,7 +12,7 @@ MEDIA_ROOT=/opt/netbox/netbox/media
NAPALM_USERNAME= NAPALM_USERNAME=
NAPALM_PASSWORD= NAPALM_PASSWORD=
NAPALM_TIMEOUT=10 NAPALM_TIMEOUT=10
MAX_PAGE_SIZE=0 MAX_PAGE_SIZE=1000
REDIS_HOST=redis REDIS_HOST=redis
REDIS_PASSWORD=H733Kdjndks81 REDIS_PASSWORD=H733Kdjndks81
SECRET_KEY=r8OwDznj!!dci#P9ghmRfdu1Ysxm0AiPeDCQhKE+N_rClfWNj SECRET_KEY=r8OwDznj!!dci#P9ghmRfdu1Ysxm0AiPeDCQhKE+N_rClfWNj

View File

@ -0,0 +1,46 @@
from dcim.constants import CONNECTION_STATUS_PLANNED, DEVICE_STATUS_ACTIVE
from dcim.models import ConsolePort, Device, PowerPort
from extras.reports import Report
class DeviceConnectionsReport(Report):
description = "Validate the minimum physical connections for each device"
def test_console_connection(self):
# Check that every console port for every active device has a connection defined.
for console_port in ConsolePort.objects.select_related('device').filter(device__status=DEVICE_STATUS_ACTIVE):
if console_port.connected_endpoint is None:
self.log_failure(
console_port.device,
"No console connection defined for {}".format(console_port.name)
)
elif console_port.connection_status == CONNECTION_STATUS_PLANNED:
self.log_warning(
console_port.device,
"Console connection for {} marked as planned".format(console_port.name)
)
else:
self.log_success(console_port.device)
def test_power_connections(self):
# Check that every active device has at least two connected power supplies.
for device in Device.objects.filter(status=DEVICE_STATUS_ACTIVE):
connected_ports = 0
for power_port in PowerPort.objects.filter(device=device):
if power_port.connected_endpoint is not None:
connected_ports += 1
if power_port.connection_status == CONNECTION_STATUS_PLANNED:
self.log_warning(
device,
"Power connection for {} marked as planned".format(power_port.name)
)
if connected_ports < 2:
self.log_failure(
device,
"{} connected power supplies found (2 needed)".format(connected_ports)
)
else:
self.log_success(device)

View File

@ -2,8 +2,14 @@ from django.contrib.auth.models import Permission, Group, User
from users.models import Token from users.models import Token
from ruamel.yaml import YAML from ruamel.yaml import YAML
from pathlib import Path
import sys
with open('/opt/netbox/initializers/users.yml', 'r') as stream: file = Path('/opt/netbox/initializers/users.yml')
if not file.is_file():
sys.exit()
with file.open('r') as stream:
yaml=YAML(typ='safe') yaml=YAML(typ='safe')
users = yaml.load(stream) users = yaml.load(stream)

View File

@ -1,7 +1,13 @@
from django.contrib.auth.models import Permission, Group, User from django.contrib.auth.models import Permission, Group, User
from ruamel.yaml import YAML from ruamel.yaml import YAML
from pathlib import Path
import sys
with open('/opt/netbox/initializers/groups.yml', 'r') as stream: file = Path('/opt/netbox/initializers/groups.yml')
if not file.is_file():
sys.exit()
with file.open('r') as stream:
yaml=YAML(typ='safe') yaml=YAML(typ='safe')
groups = yaml.load(stream) groups = yaml.load(stream)

View File

@ -2,6 +2,8 @@ from extras.constants import CF_TYPE_TEXT, CF_TYPE_INTEGER, CF_TYPE_BOOLEAN, CF_
from extras.models import CustomField, CustomFieldChoice from extras.models import CustomField, CustomFieldChoice
from ruamel.yaml import YAML from ruamel.yaml import YAML
from pathlib import Path
import sys
text_to_fields = { text_to_fields = {
'boolean': CF_TYPE_BOOLEAN, 'boolean': CF_TYPE_BOOLEAN,
@ -21,7 +23,11 @@ def get_class_for_class_path(class_path):
clazz = getattr(module, class_name) clazz = getattr(module, class_name)
return ContentType.objects.get_for_model(clazz) return ContentType.objects.get_for_model(clazz)
with open('/opt/netbox/initializers/custom_fields.yml', 'r') as stream: file = Path('/opt/netbox/initializers/custom_fields.yml')
if not file.is_file():
sys.exit()
with file.open('r') as stream:
yaml = YAML(typ='safe') yaml = YAML(typ='safe')
customfields = yaml.load(stream) customfields = yaml.load(stream)

View File

@ -1,7 +1,13 @@
from dcim.models import Region from dcim.models import Region
from ruamel.yaml import YAML from ruamel.yaml import YAML
from pathlib import Path
import sys
with open('/opt/netbox/initializers/regions.yml', 'r') as stream: file = Path('/opt/netbox/initializers/regions.yml')
if not file.is_file():
sys.exit()
with file.open('r') as stream:
yaml=YAML(typ='safe') yaml=YAML(typ='safe')
regions = yaml.load(stream) regions = yaml.load(stream)

View File

@ -2,8 +2,14 @@ from dcim.models import Region, Site
from extras.models import CustomField, CustomFieldValue from extras.models import CustomField, CustomFieldValue
from tenancy.models import Tenant from tenancy.models import Tenant
from ruamel.yaml import YAML from ruamel.yaml import YAML
from pathlib import Path
import sys
with open('/opt/netbox/initializers/sites.yml', 'r') as stream: file = Path('/opt/netbox/initializers/sites.yml')
if not file.is_file():
sys.exit()
with file.open('r') as stream:
yaml = YAML(typ='safe') yaml = YAML(typ='safe')
sites = yaml.load(stream) sites = yaml.load(stream)

View File

@ -1,7 +1,13 @@
from dcim.models import Manufacturer from dcim.models import Manufacturer
from ruamel.yaml import YAML from ruamel.yaml import YAML
from pathlib import Path
import sys
with open('/opt/netbox/initializers/manufacturers.yml', 'r') as stream: file = Path('/opt/netbox/initializers/manufacturers.yml')
if not file.is_file():
sys.exit()
with file.open('r') as stream:
yaml = YAML(typ='safe') yaml = YAML(typ='safe')
manufacturers = yaml.load(stream) manufacturers = yaml.load(stream)

View File

@ -2,8 +2,14 @@ from dcim.models import DeviceType, Manufacturer, Region
from tenancy.models import Tenant from tenancy.models import Tenant
from extras.models import CustomField, CustomFieldValue from extras.models import CustomField, CustomFieldValue
from ruamel.yaml import YAML from ruamel.yaml import YAML
from pathlib import Path
import sys
with open('/opt/netbox/initializers/device_types.yml', 'r') as stream: file = Path('/opt/netbox/initializers/device_types.yml')
if not file.is_file():
sys.exit()
with file.open('r') as stream:
yaml = YAML(typ='safe') yaml = YAML(typ='safe')
device_types = yaml.load(stream) device_types = yaml.load(stream)
@ -48,4 +54,3 @@ with open('/opt/netbox/initializers/device_types.yml', 'r') as stream:
device_type.custom_field_values.add(custom_field_value) device_type.custom_field_values.add(custom_field_value)
print("🔡 Created device type", device_type.manufacturer, device_type.model) print("🔡 Created device type", device_type.manufacturer, device_type.model)

View File

@ -2,7 +2,14 @@ from dcim.models import RackRole
from ruamel.yaml import YAML from ruamel.yaml import YAML
from utilities.forms import COLOR_CHOICES from utilities.forms import COLOR_CHOICES
with open('/opt/netbox/initializers/rack_roles.yml', 'r') as stream: from pathlib import Path
import sys
file = Path('/opt/netbox/initializers/rack_roles.yml')
if not file.is_file():
sys.exit()
with file.open('r') as stream:
yaml=YAML(typ='safe') yaml=YAML(typ='safe')
rack_roles = yaml.load(stream) rack_roles = yaml.load(stream)

View File

@ -3,8 +3,14 @@ from tenancy.models import Tenant
from extras.models import CustomField, CustomFieldValue from extras.models import CustomField, CustomFieldValue
from dcim.constants import RACK_TYPE_CHOICES, RACK_WIDTH_CHOICES from dcim.constants import RACK_TYPE_CHOICES, RACK_WIDTH_CHOICES
from ruamel.yaml import YAML from ruamel.yaml import YAML
from pathlib import Path
import sys
with open('/opt/netbox/initializers/racks.yml', 'r') as stream: file = Path('/opt/netbox/initializers/racks.yml')
if not file.is_file():
sys.exit()
with file.open('r') as stream:
yaml = YAML(typ='safe') yaml = YAML(typ='safe')
racks = yaml.load(stream) racks = yaml.load(stream)

View File

@ -2,7 +2,14 @@ from dcim.models import DeviceRole
from ruamel.yaml import YAML from ruamel.yaml import YAML
from utilities.forms import COLOR_CHOICES from utilities.forms import COLOR_CHOICES
with open('/opt/netbox/initializers/device_roles.yml', 'r') as stream: from pathlib import Path
import sys
file = Path('/opt/netbox/initializers/device_roles.yml')
if not file.is_file():
sys.exit()
with file.open('r') as stream:
yaml=YAML(typ='safe') yaml=YAML(typ='safe')
device_roles = yaml.load(stream) device_roles = yaml.load(stream)

View File

@ -1,7 +1,14 @@
from dcim.models import Manufacturer, Platform from dcim.models import Manufacturer, Platform
from ruamel.yaml import YAML from ruamel.yaml import YAML
with open('/opt/netbox/initializers/platforms.yml', 'r') as stream: from pathlib import Path
import sys
file = Path('/opt/netbox/initializers/platforms.yml')
if not file.is_file():
sys.exit()
with file.open('r') as stream:
yaml = YAML(typ='safe') yaml = YAML(typ='safe')
platforms = yaml.load(stream) platforms = yaml.load(stream)

View File

@ -6,7 +6,14 @@ from tenancy.models import Tenant
from extras.models import CustomField, CustomFieldValue from extras.models import CustomField, CustomFieldValue
from ruamel.yaml import YAML from ruamel.yaml import YAML
with open('/opt/netbox/initializers/devices.yml', 'r') as stream: from pathlib import Path
import sys
file = Path('/opt/netbox/initializers/devices.yml')
if not file.is_file():
sys.exit()
with file.open('r') as stream:
yaml = YAML(typ='safe') yaml = YAML(typ='safe')
devices = yaml.load(stream) devices = yaml.load(stream)