Merge pull request #265 from netbox-community/develop

Release 0.23.0
This commit is contained in:
Christian Mäder 2020-03-30 20:51:22 +02:00 committed by GitHub
commit 5769684c98
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
38 changed files with 730 additions and 862 deletions

View File

@ -7,5 +7,4 @@ build*
docker-compose.override.yml docker-compose.override.yml
.netbox/.git* .netbox/.git*
.netbox/.travis.yml .netbox/.travis.yml
.netbox/docs
.netbox/scripts .netbox/scripts

View File

@ -12,7 +12,8 @@
[The Github repository](netbox-docker-github) houses the components needed to build Netbox as a Docker container. [The Github repository](netbox-docker-github) houses the components needed to build Netbox as a Docker container.
Images are built using this code and are released to [Docker Hub][netbox-dockerhub] once a day. Images are built using this code and are released to [Docker Hub][netbox-dockerhub] once a day.
Do you have any questions? Before opening an issue on Github, please join the [Network To Code][ntc-slack] Slack and ask for help in our [`#netbox-docker`][netbox-docker-slack] channel. Do you have any questions?
Before opening an issue on Github, please join the [Network To Code][ntc-slack] Slack and ask for help in our [`#netbox-docker`][netbox-docker-slack] channel.
[github-stargazers]: https://github.com/netbox-community/netbox-docker/stargazers [github-stargazers]: https://github.com/netbox-community/netbox-docker/stargazers
[github-release]: https://github.com/netbox-community/netbox-docker/releases [github-release]: https://github.com/netbox-community/netbox-docker/releases
@ -25,16 +26,18 @@ Do you have any questions? Before opening an issue on Github, please join the [N
## Docker Tags ## Docker Tags
* `vX.Y.Z`: Release builds, built from [releases of Netbox][netbox-releases]. * `vX.Y.Z`: These are release builds, automatically built from [the corresponding releases of Netbox][netbox-releases].
* `latest`: Release builds, built from [`master` branch of Netbox][netbox-master]. * `latest`: These are release builds, automatically built from [the `master` branch of Netbox][netbox-master].
* `snapshot`: Pre-release builds, built from the [`develop` branch of Netbox][netbox-develop]. * `snapshot`: These are pre-release builds, automatically built from the [`develop` branch of Netbox][netbox-develop].
* `develop-X.Y`: Pre-release builds, built from the corresponding [branch of Netbox][netbox-branches]. * `develop-X.Y`: These are pre-release builds, automatically built from the corresponding [branch of Netbox][netbox-branches].
Then there is currently one extra tags for each of the above labels: Then there is currently one extra tags for each of the above tags:
* `-ldap`: Contains additional dependencies and configurations for connecting Netbox to an LDAP directroy. * `-ldap`: Contains additional dependencies and configurations for connecting Netbox to an LDAP directroy.
[Learn more about that in our wiki][netbox-docker-ldap]. [Learn more about that in our wiki][netbox-docker-ldap].
New images are built and published automatically every ~24h.
[netbox-releases]: https://github.com/netbox-community/netbox/releases [netbox-releases]: https://github.com/netbox-community/netbox/releases
[netbox-master]: https://github.com/netbox-community/netbox/tree/master [netbox-master]: https://github.com/netbox-community/netbox/tree/master
[netbox-develop]: https://github.com/netbox-community/netbox/tree/develop [netbox-develop]: https://github.com/netbox-community/netbox/tree/develop
@ -43,42 +46,50 @@ Then there is currently one extra tags for each of the above labels:
## Quickstart ## Quickstart
To get Netbox up and running in Docker: To get Netbox Docker up and running run the following commands.
There is a more complete [_Getting Started_ guide on our wiki][wiki-getting-started] which explains every step.
```bash ```bash
git clone -b release https://github.com/netbox-community/netbox-docker.git git clone -b release https://github.com/netbox-community/netbox-docker.git
cd netbox-docker cd netbox-docker
tee netbox-docker.override.yml <<EOF
version: '3.4'
services:
nginx:
ports:
- 8000:8080
EOF
docker-compose pull docker-compose pull
docker-compose up -d docker-compose up
``` ```
The application will be available after a few minutes. The whole application will be available after a few minutes.
Use `docker-compose port nginx 8080` to find out where to connect to. Open the URL `http://0.0.0.0:8000/` in a web-browser.
You should see the Netbox homepage.
```bash In the top-right corner you can login.
$ echo "http://$(docker-compose port nginx 8080)/"
http://0.0.0.0:32768/
# Open netbox in your default browser on macOS:
$ open "http://$(docker-compose port nginx 8080)/"
# Open netbox in your default browser on (most) linuxes:
$ xdg-open "http://$(docker-compose port nginx 8080)/" &>/dev/null &
```
Alternatively, use something like [Reception][docker-reception] to connect to _docker-compose_ projects.
The default credentials are: The default credentials are:
* Username: **admin** * Username: **admin**
* Password: **admin** * Password: **admin**
* API Token: **0123456789abcdef0123456789abcdef01234567** * API Token: **0123456789abcdef0123456789abcdef01234567**
There is a more complete [Getting Started guide on our Wiki][wiki-getting-started].
[wiki-getting-started]: https://github.com/netbox-community/netbox-docker/wiki/Getting-Started [wiki-getting-started]: https://github.com/netbox-community/netbox-docker/wiki/Getting-Started
[docker-reception]: https://github.com/nxt-engineering/reception [docker-reception]: https://github.com/nxt-engineering/reception
## Documentation
Please refer [to our wiki on Github][netbox-docker-wiki] for further information on how to use this Netbox Docker image properly.
It covers advanced topics such as using secret files, deployment to Kubernetes as well as NAPALM and LDAP configuration.
[netbox-docker-wiki]: https://github.com/netbox-community/netbox-docker/wiki/
## Getting Help
Please join [our Slack channel `#netbox-docker`][netbox-docker-slack] on the [Network To Code Slack][ntc-slack].
It's free to use and there are almost always people online that can help.
If you need help with using Netbox or developing for it or against it's API you may find the `#netbox` channel on the same Slack instance very helpful.
## Dependencies ## Dependencies
This project relies only on *Docker* and *docker-compose* meeting these requirements: This project relies only on *Docker* and *docker-compose* meeting these requirements:
@ -88,17 +99,10 @@ This project relies only on *Docker* and *docker-compose* meeting these requirem
To check the version installed on your system run `docker --version` and `docker-compose --version`. To check the version installed on your system run `docker --version` and `docker-compose --version`.
## Documentation ## Use a Specific Netbox Version
Please refer [to our wiki on Github][netbox-docker-wiki] for further information on how to use this Netbox Docker image properly. The `docker-compose.yml` file is prepared to run a specific version of Netbox, instead of `latest`.
It covers advanced topics such as using secret files, deployment to Kubernetes as well as NAPALM and LDAP configuration. To use this feature, set and export the environment-variable `VERSION` before launching `docker-compose`, as shown below.
[netbox-docker-wiki]: https://github.com/netbox-community/netbox-docker/wiki/
## Netbox Version
The `docker-compose.yml` file is prepared to run a specific version of Netbox.
To use this feature, set the environment-variable `VERSION` before launching `docker-compose`, as shown below.
`VERSION` may be set to the name of `VERSION` may be set to the name of
[any tag of the `netboxcommunity/netbox` Docker image on Docker Hub][netbox-dockerhub]. [any tag of the `netboxcommunity/netbox` Docker image on Docker Hub][netbox-dockerhub].
@ -141,10 +145,6 @@ For more details on custom builds [consult our wiki][netbox-docker-wiki-build].
[netbox-docker-wiki-build]: https://github.com/netbox-community/netbox-docker/wiki/Build [netbox-docker-wiki-build]: https://github.com/netbox-community/netbox-docker/wiki/Build
### Pre-made Docker Images
New Docker images are built and published every 24h.
## Tests ## Tests
We have a test script. We have a test script.

View File

@ -1 +1 @@
0.22.0 0.23.0

View File

@ -170,6 +170,15 @@ PAGINATE_COUNT = int(os.environ.get('PAGINATE_COUNT', 50))
# When determining the primary IP address for a device, IPv6 is preferred over IPv4 by default. Set this to True to # When determining the primary IP address for a device, IPv6 is preferred over IPv4 by default. Set this to True to
# prefer IPv4 instead. # prefer IPv4 instead.
PREFER_IPV4 = os.environ.get('PREFER_IPV4', 'False').lower() == 'true' PREFER_IPV4 = os.environ.get('PREFER_IPV4', 'False').lower() == 'true'
# This determines how often the GitHub API is called to check the latest release of NetBox in seconds. Must be at least 1 hour.
RELEASE_CHECK_TIMEOUT = os.environ.get('RELEASE_CHECK_TIMEOUT', 24 * 3600)
# This repository is used to check whether there is a new release of NetBox available. Set to None to disable the
# version check or use the URL below to check for release in the official NetBox repository.
# https://api.github.com/repos/netbox-community/netbox/releases
RELEASE_CHECK_URL = os.environ.get('RELEASE_CHECK_URL', None)
# The file path where custom reports will be stored. A trailing slash is not needed. Note that the default value of # The file path where custom reports will be stored. A trailing slash is not needed. Note that the default value of
# this setting is derived from the installed location. # this setting is derived from the installed location.
REPORTS_ROOT = os.environ.get('REPORTS_ROOT', '/etc/netbox/reports') REPORTS_ROOT = os.environ.get('REPORTS_ROOT', '/etc/netbox/reports')

View File

@ -5,6 +5,7 @@ services:
depends_on: depends_on:
- postgres - postgres
- redis - redis
- redis-cache
env_file: env/netbox.env env_file: env/netbox.env
user: '101' user: '101'
volumes: volumes:
@ -34,8 +35,15 @@ services:
command: command:
- sh - sh
- -c # this is to evaluate the $REDIS_PASSWORD from the env - -c # this is to evaluate the $REDIS_PASSWORD from the env
- redis-server --requirepass $$REDIS_PASSWORD ## $$ because of docker-compose - redis-server --appendonly yes --requirepass $$REDIS_PASSWORD ## $$ because of docker-compose
env_file: env/redis.env env_file: env/redis.env
redis-cache:
image: redis:5-alpine
command:
- sh
- -c # this is to evaluate the $REDIS_PASSWORD from the env
- redis-server --requirepass $$REDIS_PASSWORD ## $$ because of docker-compose
env_file: env/redis-cache.env
volumes: volumes:
netbox-static-files: netbox-static-files:
driver: local driver: local

View File

@ -57,7 +57,7 @@ services:
- sh - sh
- -c # this is to evaluate the $REDIS_PASSWORD from the env - -c # this is to evaluate the $REDIS_PASSWORD from the env
- redis-server --requirepass $$REDIS_PASSWORD ## $$ because of docker-compose - redis-server --requirepass $$REDIS_PASSWORD ## $$ because of docker-compose
env_file: env/redis.env env_file: env/redis-cache.env
volumes: volumes:
netbox-static-files: netbox-static-files:
driver: local driver: local

3
env/netbox.env vendored
View File

@ -20,7 +20,7 @@ REDIS_DATABASE=0
REDIS_SSL=false REDIS_SSL=false
REDIS_CACHE_HOST=redis-cache REDIS_CACHE_HOST=redis-cache
REDIS_CACHE_PASSWORD=t4Ph722qJ5QHeQ1qfu36 REDIS_CACHE_PASSWORD=t4Ph722qJ5QHeQ1qfu36
REDIS_CACHE_DATABASE=0 REDIS_CACHE_DATABASE=1
REDIS_CACHE_SSL=false REDIS_CACHE_SSL=false
SECRET_KEY=r8OwDznj!!dci#P9ghmRfdu1Ysxm0AiPeDCQhKE+N_rClfWNj SECRET_KEY=r8OwDznj!!dci#P9ghmRfdu1Ysxm0AiPeDCQhKE+N_rClfWNj
SKIP_STARTUP_SCRIPTS=false SKIP_STARTUP_SCRIPTS=false
@ -30,3 +30,4 @@ SUPERUSER_EMAIL=admin@example.com
SUPERUSER_PASSWORD=admin SUPERUSER_PASSWORD=admin
SUPERUSER_API_TOKEN=0123456789abcdef0123456789abcdef01234567 SUPERUSER_API_TOKEN=0123456789abcdef0123456789abcdef01234567
WEBHOOKS_ENABLED=true WEBHOOKS_ENABLED=true
RELEASE_CHECK_URL=https://api.github.com/repos/netbox-community/netbox/releases

View File

@ -1,42 +1,23 @@
from django.contrib.auth.models import Permission, Group, User
from users.models import Token
from ruamel.yaml import YAML
from pathlib import Path
import sys import sys
file = Path('/opt/netbox/initializers/users.yml') from django.contrib.auth.models import Group, User
if not file.is_file(): from startup_script_utils import load_yaml, set_permissions
from users.models import Token
users = load_yaml('/opt/netbox/initializers/users.yml')
if users is None:
sys.exit() sys.exit()
with file.open('r') as stream: for username, user_details in users.items():
yaml=YAML(typ='safe') if not User.objects.filter(username=username):
users = yaml.load(stream) user = User.objects.create_user(
username = username,
password = user_details.get('password', 0) or User.objects.make_random_password)
if users is not None: print("👤 Created user",username)
for username, user_details in users.items():
if not User.objects.filter(username=username):
user = User.objects.create_user(
username = username,
password = user_details.get('password', 0) or User.objects.make_random_password)
print("👤 Created user",username) if user_details.get('api_token', 0):
Token.objects.create(user=user, key=user_details['api_token'])
if user_details.get('api_token', 0): yaml_permissions = user_details.get('permissions', [])
Token.objects.create(user=user, key=user_details['api_token']) set_permissions(user.user_permissions, yaml_permissions)
yaml_permissions = user_details.get('permissions', [])
if yaml_permissions:
subject = user.user_permissions
subject.clear()
for yaml_permission in yaml_permissions:
if '*' in yaml_permission:
permission_filter = '^' + yaml_permission.replace('*','.*') + '$'
permissions = Permission.objects.filter(codename__iregex=permission_filter)
print(" ⚿ Granting", permissions.count(), "permissions matching '" + yaml_permission + "'")
else:
permissions = Permission.objects.filter(codename=yaml_permission)
print(" ⚿ Granting permission", yaml_permission)
for permission in permissions:
subject.add(permission)

View File

@ -1,41 +1,23 @@
from django.contrib.auth.models import Permission, Group, User
from ruamel.yaml import YAML
from pathlib import Path
import sys import sys
file = Path('/opt/netbox/initializers/groups.yml') from django.contrib.auth.models import Group, User
if not file.is_file(): from startup_script_utils import load_yaml, set_permissions
groups = load_yaml('/opt/netbox/initializers/groups.yml')
if groups is None:
sys.exit() sys.exit()
with file.open('r') as stream: for groupname, group_details in groups.items():
yaml=YAML(typ='safe') group, created = Group.objects.get_or_create(name=groupname)
groups = yaml.load(stream)
if groups is not None: if created:
for groupname, group_details in groups.items(): print("👥 Created group", groupname)
group, created = Group.objects.get_or_create(name=groupname)
if created: for username in group_details.get('users', []):
print("👥 Created group", groupname) user = User.objects.get(username=username)
for username in group_details.get('users', []): if user:
user = User.objects.get(username=username) user.groups.add(group)
if user: yaml_permissions = group_details.get('permissions', [])
user.groups.add(group) set_permissions(group.permissions, yaml_permissions)
yaml_permissions = group_details.get('permissions', [])
if yaml_permissions:
subject = group.permissions
subject.clear()
for yaml_permission in yaml_permissions:
if '*' in yaml_permission:
permission_filter = '^' + yaml_permission.replace('*','.*') + '$'
permissions = Permission.objects.filter(codename__iregex=permission_filter)
print(" ⚿ Granting", permissions.count(), "permissions matching '" + yaml_permission + "'")
else:
permissions = Permission.objects.filter(codename=yaml_permission)
print(" ⚿ Granting permission", yaml_permission)
for permission in permissions:
subject.add(permission)

View File

@ -1,7 +1,6 @@
from extras.models import CustomField, CustomFieldChoice from extras.models import CustomField, CustomFieldChoice
from ruamel.yaml import YAML from startup_script_utils import load_yaml
from pathlib import Path
import sys import sys
def get_class_for_class_path(class_path): def get_class_for_class_path(class_path):
@ -13,47 +12,43 @@ 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)
file = Path('/opt/netbox/initializers/custom_fields.yml') customfields = load_yaml('/opt/netbox/initializers/custom_fields.yml')
if not file.is_file():
if customfields is None:
sys.exit() sys.exit()
with file.open('r') as stream: for cf_name, cf_details in customfields.items():
yaml = YAML(typ='safe') custom_field, created = CustomField.objects.get_or_create(name = cf_name)
customfields = yaml.load(stream)
if customfields is not None: if created:
for cf_name, cf_details in customfields.items(): if cf_details.get('default', 0):
custom_field, created = CustomField.objects.get_or_create(name = cf_name) custom_field.default = cf_details['default']
if created: if cf_details.get('description', 0):
if cf_details.get('default', 0): custom_field.description = cf_details['description']
custom_field.default = cf_details['default']
if cf_details.get('description', 0): if cf_details.get('label', 0):
custom_field.description = cf_details['description'] custom_field.label = cf_details['label']
if cf_details.get('label', 0): for object_type in cf_details.get('on_objects', []):
custom_field.label = cf_details['label'] custom_field.obj_type.add(get_class_for_class_path(object_type))
for object_type in cf_details.get('on_objects', []): if cf_details.get('required', 0):
custom_field.obj_type.add(get_class_for_class_path(object_type)) custom_field.required = cf_details['required']
if cf_details.get('required', 0): if cf_details.get('type', 0):
custom_field.required = cf_details['required'] custom_field.type = cf_details['type']
if cf_details.get('type', 0): if cf_details.get('weight', 0):
custom_field.type = cf_details['type'] custom_field.weight = cf_details['weight']
if cf_details.get('weight', 0): custom_field.save()
custom_field.weight = cf_details['weight']
custom_field.save() for idx, choice_details in enumerate(cf_details.get('choices', [])):
choice, _ = CustomFieldChoice.objects.get_or_create(
field=custom_field,
value=choice_details['value'],
defaults={'weight': idx * 10}
)
for idx, choice_details in enumerate(cf_details.get('choices', [])): print("🔧 Created custom field", cf_name)
choice, _ = CustomFieldChoice.objects.get_or_create(
field=custom_field,
value=choice_details['value'],
defaults={'weight': idx * 10}
)
print("🔧 Created custom field", cf_name)

View File

@ -1,31 +1,26 @@
from dcim.models import Region from dcim.models import Region
from ruamel.yaml import YAML from startup_script_utils import load_yaml
from pathlib import Path
import sys import sys
file = Path('/opt/netbox/initializers/regions.yml') regions = load_yaml('/opt/netbox/initializers/regions.yml')
if not file.is_file():
if regions is None:
sys.exit() sys.exit()
with file.open('r') as stream: optional_assocs = {
yaml=YAML(typ='safe') 'parent': (Region, 'name')
regions = yaml.load(stream) }
optional_assocs = { for params in regions:
'parent': (Region, 'name')
}
if regions is not None: for assoc, details in optional_assocs.items():
for params in regions: if assoc in params:
model, field = details
query = { field: params.pop(assoc) }
for assoc, details in optional_assocs.items(): params[assoc] = model.objects.get(**query)
if assoc in params:
model, field = details
query = { field: params.pop(assoc) }
params[assoc] = model.objects.get(**query) region, created = Region.objects.get_or_create(**params)
region, created = Region.objects.get_or_create(**params) if created:
print("🌐 Created region", region.name)
if created:
print("🌐 Created region", region.name)

View File

@ -1,46 +1,41 @@
from dcim.models import Region, Site 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 startup_script_utils import load_yaml
from pathlib import Path
import sys import sys
file = Path('/opt/netbox/initializers/sites.yml') sites = load_yaml('/opt/netbox/initializers/sites.yml')
if not file.is_file():
if sites is None:
sys.exit() sys.exit()
with file.open('r') as stream: optional_assocs = {
yaml = YAML(typ='safe') 'region': (Region, 'name'),
sites = yaml.load(stream) 'tenant': (Tenant, 'name')
}
optional_assocs = { for params in sites:
'region': (Region, 'name'), custom_fields = params.pop('custom_fields', None)
'tenant': (Tenant, 'name')
}
if sites is not None: for assoc, details in optional_assocs.items():
for params in sites: if assoc in params:
custom_fields = params.pop('custom_fields', None) model, field = details
query = { field: params.pop(assoc) }
for assoc, details in optional_assocs.items(): params[assoc] = model.objects.get(**query)
if assoc in params:
model, field = details
query = { field: params.pop(assoc) }
params[assoc] = model.objects.get(**query) site, created = Site.objects.get_or_create(**params)
site, created = Site.objects.get_or_create(**params) if created:
if custom_fields is not None:
for cf_name, cf_value in custom_fields.items():
custom_field = CustomField.objects.get(name=cf_name)
custom_field_value = CustomFieldValue.objects.create(
field=custom_field,
obj=site,
value=cf_value
)
if created: site.custom_field_values.add(custom_field_value)
if custom_fields is not None:
for cf_name, cf_value in custom_fields.items():
custom_field = CustomField.objects.get(name=cf_name)
custom_field_value = CustomFieldValue.objects.create(
field=custom_field,
obj=site,
value=cf_value
)
site.custom_field_values.add(custom_field_value) print("📍 Created site", site.name)
print("📍 Created site", site.name)

View File

@ -1,19 +1,14 @@
from dcim.models import Manufacturer from dcim.models import Manufacturer
from ruamel.yaml import YAML from startup_script_utils import load_yaml
from pathlib import Path
import sys import sys
file = Path('/opt/netbox/initializers/manufacturers.yml') manufacturers = load_yaml('/opt/netbox/initializers/manufacturers.yml')
if not file.is_file():
if manufacturers is None:
sys.exit() sys.exit()
with file.open('r') as stream: for params in manufacturers:
yaml = YAML(typ='safe') manufacturer, created = Manufacturer.objects.get_or_create(**params)
manufacturers = yaml.load(stream)
if manufacturers is not None: if created:
for params in manufacturers: print("🏭 Created Manufacturer", manufacturer.name)
manufacturer, created = Manufacturer.objects.get_or_create(**params)
if created:
print("🏭 Created Manufacturer", manufacturer.name)

View File

@ -1,56 +1,51 @@
from dcim.models import DeviceType, Manufacturer, Region 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 startup_script_utils import load_yaml
from pathlib import Path
import sys import sys
file = Path('/opt/netbox/initializers/device_types.yml') device_types = load_yaml('/opt/netbox/initializers/device_types.yml')
if not file.is_file():
if device_types is None:
sys.exit() sys.exit()
with file.open('r') as stream: required_assocs = {
yaml = YAML(typ='safe') 'manufacturer': (Manufacturer, 'name')
device_types = yaml.load(stream) }
required_assocs = { optional_assocs = {
'manufacturer': (Manufacturer, 'name') 'region': (Region, 'name'),
} 'tenant': (Tenant, 'name')
}
optional_assocs = { for params in device_types:
'region': (Region, 'name'), custom_fields = params.pop('custom_fields', None)
'tenant': (Tenant, 'name')
}
if device_types is not None: for assoc, details in required_assocs.items():
for params in device_types: model, field = details
custom_fields = params.pop('custom_fields', None) query = { field: params.pop(assoc) }
for assoc, details in required_assocs.items(): params[assoc] = model.objects.get(**query)
model, field = details
query = { field: params.pop(assoc) }
params[assoc] = model.objects.get(**query) for assoc, details in optional_assocs.items():
if assoc in params:
model, field = details
query = { field: params.pop(assoc) }
for assoc, details in optional_assocs.items(): params[assoc] = model.objects.get(**query)
if assoc in params:
model, field = details
query = { field: params.pop(assoc) }
params[assoc] = model.objects.get(**query) device_type, created = DeviceType.objects.get_or_create(**params)
device_type, created = DeviceType.objects.get_or_create(**params) if created:
if custom_fields is not None:
for cf_name, cf_value in custom_fields.items():
custom_field = CustomField.objects.get(name=cf_name)
custom_field_value = CustomFieldValue.objects.create(
field=custom_field,
obj=device_type,
value=cf_value
)
if created: device_type.custom_field_values.add(custom_field_value)
if custom_fields is not None:
for cf_name, cf_value in custom_fields.items():
custom_field = CustomField.objects.get(name=cf_name)
custom_field_value = CustomFieldValue.objects.create(
field=custom_field,
obj=device_type,
value=cf_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

@ -1,28 +1,23 @@
from dcim.models import RackRole from dcim.models import RackRole
from ruamel.yaml import YAML
from utilities.forms import COLOR_CHOICES from utilities.forms import COLOR_CHOICES
from pathlib import Path from startup_script_utils import load_yaml
import sys import sys
file = Path('/opt/netbox/initializers/rack_roles.yml') rack_roles = load_yaml('/opt/netbox/initializers/rack_roles.yml')
if not file.is_file():
if rack_roles is None:
sys.exit() sys.exit()
with file.open('r') as stream: for params in rack_roles:
yaml=YAML(typ='safe') if 'color' in params:
rack_roles = yaml.load(stream) color = params.pop('color')
if rack_roles is not None: for color_tpl in COLOR_CHOICES:
for params in rack_roles: if color in color_tpl:
if 'color' in params: params['color'] = color_tpl[0]
color = params.pop('color')
for color_tpl in COLOR_CHOICES: rack_role, created = RackRole.objects.get_or_create(**params)
if color in color_tpl:
params['color'] = color_tpl[0]
rack_role, created = RackRole.objects.get_or_create(**params) if created:
print("🎨 Created rack role", rack_role.name)
if created:
print("🎨 Created rack role", rack_role.name)

View File

@ -1,31 +1,25 @@
from dcim.models import Site,RackGroup from dcim.models import Site,RackGroup
from ruamel.yaml import YAML from startup_script_utils import load_yaml
from pathlib import Path
import sys import sys
file = Path('/opt/netbox/initializers/rack_groups.yml') rack_groups = load_yaml('/opt/netbox/initializers/rack_groups.yml')
if not file.is_file():
if rack_groups is None:
sys.exit() sys.exit()
with file.open('r') as stream: required_assocs = {
yaml=YAML(typ='safe') 'site': (Site, 'name')
rack_groups= yaml.load(stream) }
required_assocs = { for params in rack_groups:
'site': (Site, 'name')
}
if rack_groups is not None: for assoc, details in required_assocs.items():
for params in rack_groups: model, field = details
query = { field: params.pop(assoc) }
params[assoc] = model.objects.get(**query)
for assoc, details in required_assocs.items(): rack_group, created = RackGroup.objects.get_or_create(**params)
model, field = details
query = { field: params.pop(assoc) }
params[assoc] = model.objects.get(**query)
rack_group, created = RackGroup.objects.get_or_create(**params) if created:
print("🎨 Created rack group", rack_group.name)
if created:
print("🎨 Created rack group", rack_group.name)

View File

@ -1,57 +1,52 @@
from dcim.models import Site, RackRole, Rack, RackGroup from dcim.models import Site, RackRole, Rack, RackGroup
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 startup_script_utils import load_yaml
from pathlib import Path
import sys import sys
file = Path('/opt/netbox/initializers/racks.yml') racks = load_yaml('/opt/netbox/initializers/racks.yml')
if not file.is_file():
if racks is None:
sys.exit() sys.exit()
with file.open('r') as stream: required_assocs = {
yaml = YAML(typ='safe') 'site': (Site, 'name')
racks = yaml.load(stream) }
required_assocs = { optional_assocs = {
'site': (Site, 'name') 'role': (RackRole, 'name'),
} 'tenant': (Tenant, 'name'),
'group': (RackGroup, 'name')
}
optional_assocs = { for params in racks:
'role': (RackRole, 'name'), custom_fields = params.pop('custom_fields', None)
'tenant': (Tenant, 'name'),
'group': (RackGroup, 'name')
}
if racks is not None: for assoc, details in required_assocs.items():
for params in racks: model, field = details
custom_fields = params.pop('custom_fields', None) query = { field: params.pop(assoc) }
for assoc, details in required_assocs.items(): params[assoc] = model.objects.get(**query)
model, field = details
query = { field: params.pop(assoc) }
params[assoc] = model.objects.get(**query) for assoc, details in optional_assocs.items():
if assoc in params:
model, field = details
query = { field: params.pop(assoc) }
for assoc, details in optional_assocs.items(): params[assoc] = model.objects.get(**query)
if assoc in params:
model, field = details
query = { field: params.pop(assoc) }
params[assoc] = model.objects.get(**query) rack, created = Rack.objects.get_or_create(**params)
rack, created = Rack.objects.get_or_create(**params) if created:
if custom_fields is not None:
for cf_name, cf_value in custom_fields.items():
custom_field = CustomField.objects.get(name=cf_name)
custom_field_value = CustomFieldValue.objects.create(
field=custom_field,
obj=rack,
value=cf_value
)
if created: rack.custom_field_values.add(custom_field_value)
if custom_fields is not None:
for cf_name, cf_value in custom_fields.items():
custom_field = CustomField.objects.get(name=cf_name)
custom_field_value = CustomFieldValue.objects.create(
field=custom_field,
obj=rack,
value=cf_value
)
rack.custom_field_values.add(custom_field_value) print("🔳 Created rack", rack.site, rack.name)
print("🔳 Created rack", rack.site, rack.name)

View File

@ -1,29 +1,23 @@
from dcim.models import DeviceRole from dcim.models import DeviceRole
from ruamel.yaml import YAML
from utilities.forms import COLOR_CHOICES from utilities.forms import COLOR_CHOICES
from startup_script_utils import load_yaml
from pathlib import Path
import sys import sys
file = Path('/opt/netbox/initializers/device_roles.yml') device_roles = load_yaml('/opt/netbox/initializers/device_roles.yml')
if not file.is_file():
if device_roles is None:
sys.exit() sys.exit()
with file.open('r') as stream: for params in device_roles:
yaml=YAML(typ='safe')
device_roles = yaml.load(stream)
if device_roles is not None: if 'color' in params:
for params in device_roles: color = params.pop('color')
if 'color' in params: for color_tpl in COLOR_CHOICES:
color = params.pop('color') if color in color_tpl:
params['color'] = color_tpl[0]
for color_tpl in COLOR_CHOICES: device_role, created = DeviceRole.objects.get_or_create(**params)
if color in color_tpl:
params['color'] = color_tpl[0]
device_role, created = DeviceRole.objects.get_or_create(**params) if created:
print("🎨 Created device role", device_role.name)
if created:
print("🎨 Created device role", device_role.name)

View File

@ -1,32 +1,26 @@
from dcim.models import Manufacturer, Platform from dcim.models import Manufacturer, Platform
from ruamel.yaml import YAML from startup_script_utils import load_yaml
from pathlib import Path
import sys import sys
file = Path('/opt/netbox/initializers/platforms.yml') platforms = load_yaml('/opt/netbox/initializers/platforms.yml')
if not file.is_file():
if platforms is None:
sys.exit() sys.exit()
with file.open('r') as stream: optional_assocs = {
yaml = YAML(typ='safe') 'manufacturer': (Manufacturer, 'name'),
platforms = yaml.load(stream) }
optional_assocs = { for params in platforms:
'manufacturer': (Manufacturer, 'name'),
}
if platforms is not None: for assoc, details in optional_assocs.items():
for params in platforms: if assoc in params:
model, field = details
query = { field: params.pop(assoc) }
for assoc, details in optional_assocs.items(): params[assoc] = model.objects.get(**query)
if assoc in params:
model, field = details
query = { field: params.pop(assoc) }
params[assoc] = model.objects.get(**query) platform, created = Platform.objects.get_or_create(**params)
platform, created = Platform.objects.get_or_create(**params) if created:
print("💾 Created platform", platform.name)
if created:
print("💾 Created platform", platform.name)

View File

@ -1,19 +1,14 @@
from tenancy.models import TenantGroup from tenancy.models import TenantGroup
from ruamel.yaml import YAML from startup_script_utils import load_yaml
from pathlib import Path
import sys import sys
file = Path('/opt/netbox/initializers/tenant_groups.yml') tenant_groups = load_yaml('/opt/netbox/initializers/tenant_groups.yml')
if not file.is_file():
if tenant_groups is None:
sys.exit() sys.exit()
with file.open('r') as stream: for params in tenant_groups:
yaml = YAML(typ='safe') tenant_group, created = TenantGroup.objects.get_or_create(**params)
tenant_groups = yaml.load(stream)
if tenant_groups is not None: if created:
for params in tenant_groups: print("🔳 Created Tenant Group", tenant_group.name)
tenant_group, created = TenantGroup.objects.get_or_create(**params)
if created:
print("🔳 Created Tenant Group", tenant_group.name)

View File

@ -1,45 +1,39 @@
from tenancy.models import Tenant, TenantGroup from tenancy.models import Tenant, TenantGroup
from extras.models import CustomField, CustomFieldValue from extras.models import CustomField, CustomFieldValue
from ruamel.yaml import YAML from startup_script_utils import load_yaml
from pathlib import Path
import sys import sys
file = Path('/opt/netbox/initializers/tenants.yml') tenants = load_yaml('/opt/netbox/initializers/tenants.yml')
if not file.is_file():
if tenants is None:
sys.exit() sys.exit()
with file.open('r') as stream: optional_assocs = {
yaml = YAML(typ='safe') 'group': (TenantGroup, 'name')
tenants = yaml.load(stream) }
optional_assocs = { for params in tenants:
'group': (TenantGroup, 'name') custom_fields = params.pop('custom_fields', None)
}
if tenants is not None: for assoc, details in optional_assocs.items():
for params in tenants: if assoc in params:
custom_fields = params.pop('custom_fields', None) model, field = details
query = { field: params.pop(assoc) }
for assoc, details in optional_assocs.items(): params[assoc] = model.objects.get(**query)
if assoc in params:
model, field = details
query = { field: params.pop(assoc) }
params[assoc] = model.objects.get(**query) tenant, created = Tenant.objects.get_or_create(**params)
tenant, created = Tenant.objects.get_or_create(**params) if created:
if custom_fields is not None:
for cf_name, cf_value in custom_fields.items():
custom_field = CustomField.objects.get(name=cf_name)
custom_field_value = CustomFieldValue.objects.create(
field=custom_field,
obj=tenant,
value=cf_value
)
if created: tenant.custom_field_values.add(custom_field_value)
if custom_fields is not None:
for cf_name, cf_value in custom_fields.items():
custom_field = CustomField.objects.get(name=cf_name)
custom_field_value = CustomFieldValue.objects.create(
field=custom_field,
obj=tenant,
value=cf_value
)
tenant.custom_field_values.add(custom_field_value) print("👩‍💻 Created Tenant", tenant.name)
print("👩‍💻 Created Tenant", tenant.name)

View File

@ -3,63 +3,57 @@ from ipam.models import IPAddress
from virtualization.models import Cluster from virtualization.models import Cluster
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 startup_script_utils import load_yaml
from pathlib import Path
import sys import sys
file = Path('/opt/netbox/initializers/devices.yml') devices = load_yaml('/opt/netbox/initializers/devices.yml')
if not file.is_file():
if devices is None:
sys.exit() sys.exit()
with file.open('r') as stream: required_assocs = {
yaml = YAML(typ='safe') 'device_role': (DeviceRole, 'name'),
devices = yaml.load(stream) 'device_type': (DeviceType, 'model'),
'site': (Site, 'name')
}
required_assocs = { optional_assocs = {
'device_role': (DeviceRole, 'name'), 'tenant': (Tenant, 'name'),
'device_type': (DeviceType, 'model'), 'platform': (Platform, 'name'),
'site': (Site, 'name') 'rack': (Rack, 'name'),
} 'cluster': (Cluster, 'name'),
'primary_ip4': (IPAddress, 'address'),
'primary_ip6': (IPAddress, 'address')
}
optional_assocs = { for params in devices:
'tenant': (Tenant, 'name'), custom_fields = params.pop('custom_fields', None)
'platform': (Platform, 'name'),
'rack': (Rack, 'name'),
'cluster': (Cluster, 'name'),
'primary_ip4': (IPAddress, 'address'),
'primary_ip6': (IPAddress, 'address')
}
if devices is not None: for assoc, details in required_assocs.items():
for params in devices: model, field = details
custom_fields = params.pop('custom_fields', None) query = { field: params.pop(assoc) }
for assoc, details in required_assocs.items(): params[assoc] = model.objects.get(**query)
model, field = details
query = { field: params.pop(assoc) }
params[assoc] = model.objects.get(**query) for assoc, details in optional_assocs.items():
if assoc in params:
model, field = details
query = { field: params.pop(assoc) }
for assoc, details in optional_assocs.items(): params[assoc] = model.objects.get(**query)
if assoc in params:
model, field = details
query = { field: params.pop(assoc) }
params[assoc] = model.objects.get(**query) device, created = Device.objects.get_or_create(**params)
device, created = Device.objects.get_or_create(**params) if created:
if custom_fields is not None:
for cf_name, cf_value in custom_fields.items():
custom_field = CustomField.objects.get(name=cf_name)
custom_field_value = CustomFieldValue.objects.create(
field=custom_field,
obj=device,
value=cf_value
)
if created: device.custom_field_values.add(custom_field_value)
if custom_fields is not None:
for cf_name, cf_value in custom_fields.items():
custom_field = CustomField.objects.get(name=cf_name)
custom_field_value = CustomFieldValue.objects.create(
field=custom_field,
obj=device,
value=cf_value
)
device.custom_field_values.add(custom_field_value) print("🖥️ Created device", device.name)
print("🖥️ Created device", device.name)

View File

@ -1,19 +1,14 @@
from virtualization.models import ClusterType from virtualization.models import ClusterType
from ruamel.yaml import YAML from startup_script_utils import load_yaml
from pathlib import Path
import sys import sys
file = Path('/opt/netbox/initializers/cluster_types.yml') cluster_types = load_yaml('/opt/netbox/initializers/cluster_types.yml')
if not file.is_file():
if cluster_types is None:
sys.exit() sys.exit()
with file.open('r') as stream: for params in cluster_types:
yaml = YAML(typ='safe') cluster_type, created = ClusterType.objects.get_or_create(**params)
cluster_types = yaml.load(stream)
if cluster_types is not None: if created:
for params in cluster_types: print("🧰 Created Cluster Type", cluster_type.name)
cluster_type, created = ClusterType.objects.get_or_create(**params)
if created:
print("🧰 Created Cluster Type", cluster_type.name)

View File

@ -1,19 +1,14 @@
from ipam.models import RIR from ipam.models import RIR
from ruamel.yaml import YAML from startup_script_utils import load_yaml
from pathlib import Path
import sys import sys
file = Path('/opt/netbox/initializers/rirs.yml') rirs = load_yaml('/opt/netbox/initializers/rirs.yml')
if not file.is_file():
if rirs is None:
sys.exit() sys.exit()
with file.open('r') as stream: for params in rirs:
yaml = YAML(typ='safe') rir, created = RIR.objects.get_or_create(**params)
rirs = yaml.load(stream)
if rirs is not None: if created:
for params in rirs: print("🗺️ Created RIR", rir.name)
rir, created = RIR.objects.get_or_create(**params)
if created:
print("🗺️ Created RIR", rir.name)

View File

@ -1,46 +1,42 @@
from ipam.models import Aggregate, RIR from ipam.models import Aggregate, RIR
from ruamel.yaml import YAML
from extras.models import CustomField, CustomFieldValue from extras.models import CustomField, CustomFieldValue
from netaddr import IPNetwork from netaddr import IPNetwork
from pathlib import Path from startup_script_utils import load_yaml
import sys import sys
file = Path('/opt/netbox/initializers/aggregates.yml') aggregates = load_yaml('/opt/netbox/initializers/aggregates.yml')
if not file.is_file():
if aggregates is None:
sys.exit() sys.exit()
with file.open('r') as stream: required_assocs = {
yaml = YAML(typ='safe') 'rir': (RIR, 'name')
aggregates = yaml.load(stream) }
required_assocs = { for params in aggregates:
'rir': (RIR, 'name') custom_fields = params.pop('custom_fields', None)
} params['prefix'] = IPNetwork(params['prefix'])
if aggregates is not None: for assoc, details in required_assocs.items():
for params in aggregates: model, field = details
custom_fields = params.pop('custom_fields', None) query = { field: params.pop(assoc) }
params['prefix'] = IPNetwork(params['prefix'])
for assoc, details in required_assocs.items(): params[assoc] = model.objects.get(**query)
model, field = details
query = { field: params.pop(assoc) }
params[assoc] = model.objects.get(**query) aggregate, created = Aggregate.objects.get_or_create(**params)
aggregate, created = Aggregate.objects.get_or_create(**params) if created:
if custom_fields is not None:
for cf_name, cf_value in custom_fields.items():
custom_field = CustomField.objects.get(name=cf_name)
custom_field_value = CustomFieldValue.objects.create(
field=custom_field,
obj=aggregate,
value=cf_value
)
if created: aggregate.custom_field_values.add(custom_field_value)
if custom_fields is not None:
for cf_name, cf_value in custom_fields.items():
custom_field = CustomField.objects.get(name=cf_name)
custom_field_value = CustomFieldValue.objects.create(
field=custom_field,
obj=aggregate,
value=cf_value
)
aggregate.custom_field_values.add(custom_field_value) print("🗞️ Created Aggregate", aggregate.prefix)
print("🗞️ Created Aggregate", aggregate.prefix)

View File

@ -1,57 +1,51 @@
from dcim.models import Site from dcim.models import Site
from virtualization.models import Cluster, ClusterType, ClusterGroup from virtualization.models import Cluster, ClusterType, ClusterGroup
from extras.models import CustomField, CustomFieldValue from extras.models import CustomField, CustomFieldValue
from ruamel.yaml import YAML from startup_script_utils import load_yaml
from pathlib import Path
import sys import sys
file = Path('/opt/netbox/initializers/clusters.yml') clusters = load_yaml('/opt/netbox/initializers/clusters.yml')
if not file.is_file():
if clusters is None:
sys.exit() sys.exit()
with file.open('r') as stream: required_assocs = {
yaml = YAML(typ='safe') 'type': (ClusterType, 'name')
clusters = yaml.load(stream) }
required_assocs = { optional_assocs = {
'type': (ClusterType, 'name') 'site': (Site, 'name'),
} 'group': (ClusterGroup, 'name')
}
optional_assocs = { for params in clusters:
'site': (Site, 'name'), custom_fields = params.pop('custom_fields', None)
'group': (ClusterGroup, 'name')
}
if clusters is not None: for assoc, details in required_assocs.items():
for params in clusters: model, field = details
custom_fields = params.pop('custom_fields', None) query = { field: params.pop(assoc) }
for assoc, details in required_assocs.items(): params[assoc] = model.objects.get(**query)
model, field = details
query = { field: params.pop(assoc) }
params[assoc] = model.objects.get(**query) for assoc, details in optional_assocs.items():
if assoc in params:
model, field = details
query = { field: params.pop(assoc) }
for assoc, details in optional_assocs.items(): params[assoc] = model.objects.get(**query)
if assoc in params:
model, field = details
query = { field: params.pop(assoc) }
params[assoc] = model.objects.get(**query) cluster, created = Cluster.objects.get_or_create(**params)
cluster, created = Cluster.objects.get_or_create(**params) if created:
if custom_fields is not None:
for cf_name, cf_value in custom_fields.items():
custom_field = CustomField.objects.get(name=cf_name)
custom_field_value = CustomFieldValue.objects.create(
field=custom_field,
obj=cluster,
value=cf_value
)
if created: cluster.custom_field_values.add(custom_field_value)
if custom_fields is not None:
for cf_name, cf_value in custom_fields.items():
custom_field = CustomField.objects.get(name=cf_name)
custom_field_value = CustomFieldValue.objects.create(
field=custom_field,
obj=cluster,
value=cf_value
)
cluster.custom_field_values.add(custom_field_value) print("🗄️ Created cluster", cluster.name)
print("🗄️ Created cluster", cluster.name)

View File

@ -1,46 +1,42 @@
from ipam.models import VRF from ipam.models import VRF
from tenancy.models import Tenant from tenancy.models import Tenant
from ruamel.yaml import YAML
from extras.models import CustomField, CustomFieldValue from extras.models import CustomField, CustomFieldValue
from pathlib import Path from startup_script_utils import load_yaml
import sys import sys
file = Path('/opt/netbox/initializers/vrfs.yml') vrfs = load_yaml('/opt/netbox/initializers/vrfs.yml')
if not file.is_file():
if vrfs is None:
sys.exit() sys.exit()
with file.open('r') as stream: optional_assocs = {
yaml = YAML(typ='safe') 'tenant': (Tenant, 'name')
vrfs = yaml.load(stream) }
optional_assocs = { for params in vrfs:
'tenant': (Tenant, 'name') custom_fields = params.pop('custom_fields', None)
}
if vrfs is not None: for assoc, details in optional_assocs.items():
for params in vrfs: if assoc in params:
custom_fields = params.pop('custom_fields', None) model, field = details
query = { field: params.pop(assoc) }
for assoc, details in optional_assocs.items(): params[assoc] = model.objects.get(**query)
if assoc in params:
model, field = details
query = { field: params.pop(assoc) }
params[assoc] = model.objects.get(**query) vrf, created = VRF.objects.get_or_create(**params)
vrf, created = VRF.objects.get_or_create(**params) if created:
if custom_fields is not None:
for cf_name, cf_value in custom_fields.items():
custom_field = CustomField.objects.get(name=cf_name)
custom_field_value = CustomFieldValue.objects.create(
field=custom_field,
obj=vrf,
value=cf_value
)
if created: vrf.custom_field_values.add(custom_field_value)
if custom_fields is not None:
for cf_name, cf_value in custom_fields.items():
custom_field = CustomField.objects.get(name=cf_name)
custom_field_value = CustomFieldValue.objects.create(
field=custom_field,
obj=vrf,
value=cf_value
)
vrf.custom_field_values.add(custom_field_value) print("📦 Created VRF", vrf.name)
print("📦 Created VRF", vrf.name)

View File

@ -1,19 +1,14 @@
from ipam.models import Role from ipam.models import Role
from ruamel.yaml import YAML from startup_script_utils import load_yaml
from pathlib import Path
import sys import sys
file = Path('/opt/netbox/initializers/prefix_vlan_roles.yml') roles = load_yaml('/opt/netbox/initializers/prefix_vlan_roles.yml')
if not file.is_file():
if roles is None:
sys.exit() sys.exit()
with file.open('r') as stream: for params in roles:
yaml = YAML(typ='safe') role, created = Role.objects.get_or_create(**params)
roles = yaml.load(stream)
if roles is not None: if created:
for params in roles: print("⛹️‍ Created Prefix/VLAN Role", role.name)
role, created = Role.objects.get_or_create(**params)
if created:
print("⛹️‍ Created Prefix/VLAN Role", role.name)

View File

@ -1,46 +1,40 @@
from dcim.models import Site from dcim.models import Site
from ipam.models import VLANGroup from ipam.models import VLANGroup
from extras.models import CustomField, CustomFieldValue from extras.models import CustomField, CustomFieldValue
from ruamel.yaml import YAML from startup_script_utils import load_yaml
from pathlib import Path
import sys import sys
file = Path('/opt/netbox/initializers/vlan_groups.yml') vlan_groups = load_yaml('/opt/netbox/initializers/vlan_groups.yml')
if not file.is_file():
if vlan_groups is None:
sys.exit() sys.exit()
with file.open('r') as stream: optional_assocs = {
yaml = YAML(typ='safe') 'site': (Site, 'name')
vlan_groups = yaml.load(stream) }
optional_assocs = { for params in vlan_groups:
'site': (Site, 'name') custom_fields = params.pop('custom_fields', None)
}
if vlan_groups is not None: for assoc, details in optional_assocs.items():
for params in vlan_groups: if assoc in params:
custom_fields = params.pop('custom_fields', None) model, field = details
query = { field: params.pop(assoc) }
for assoc, details in optional_assocs.items(): params[assoc] = model.objects.get(**query)
if assoc in params:
model, field = details
query = { field: params.pop(assoc) }
params[assoc] = model.objects.get(**query) vlan_group, created = VLANGroup.objects.get_or_create(**params)
vlan_group, created = VLANGroup.objects.get_or_create(**params) if created:
if custom_fields is not None:
for cf_name, cf_value in custom_fields.items():
custom_field = CustomField.objects.get(name=cf_name)
custom_field_value = CustomFieldValue.objects.create(
field=custom_field,
obj=vlan_group,
value=cf_value
)
if created: vlan_group.custom_field_values.add(custom_field_value)
if custom_fields is not None:
for cf_name, cf_value in custom_fields.items():
custom_field = CustomField.objects.get(name=cf_name)
custom_field_value = CustomFieldValue.objects.create(
field=custom_field,
obj=vlan_group,
value=cf_value
)
vlan_group.custom_field_values.add(custom_field_value) print("🏘️ Created VLAN Group", vlan_group.name)
print("🏘️ Created VLAN Group", vlan_group.name)

View File

@ -2,50 +2,44 @@ from dcim.models import Site
from ipam.models import VLAN, VLANGroup, Role from ipam.models import VLAN, VLANGroup, Role
from tenancy.models import Tenant, TenantGroup from tenancy.models import Tenant, TenantGroup
from extras.models import CustomField, CustomFieldValue from extras.models import CustomField, CustomFieldValue
from ruamel.yaml import YAML from startup_script_utils import load_yaml
from pathlib import Path
import sys import sys
file = Path('/opt/netbox/initializers/vlans.yml') vlans = load_yaml('/opt/netbox/initializers/vlans.yml')
if not file.is_file():
if vlans is None:
sys.exit() sys.exit()
with file.open('r') as stream: optional_assocs = {
yaml = YAML(typ='safe') 'site': (Site, 'name'),
vlans = yaml.load(stream) 'tenant': (Tenant, 'name'),
'tenant_group': (TenantGroup, 'name'),
'group': (VLANGroup, 'name'),
'role': (Role, 'name')
}
optional_assocs = { for params in vlans:
'site': (Site, 'name'), custom_fields = params.pop('custom_fields', None)
'tenant': (Tenant, 'name'),
'tenant_group': (TenantGroup, 'name'),
'group': (VLANGroup, 'name'),
'role': (Role, 'name')
}
if vlans is not None: for assoc, details in optional_assocs.items():
for params in vlans: if assoc in params:
custom_fields = params.pop('custom_fields', None) model, field = details
query = { field: params.pop(assoc) }
for assoc, details in optional_assocs.items(): params[assoc] = model.objects.get(**query)
if assoc in params:
model, field = details
query = { field: params.pop(assoc) }
params[assoc] = model.objects.get(**query) vlan, created = VLAN.objects.get_or_create(**params)
vlan, created = VLAN.objects.get_or_create(**params) if created:
if custom_fields is not None:
for cf_name, cf_value in custom_fields.items():
custom_field = CustomField.objects.get(name=cf_name)
custom_field_value = CustomFieldValue.objects.create(
field=custom_field,
obj=vlan,
value=cf_value
)
if created: vlan.custom_field_values.add(custom_field_value)
if custom_fields is not None:
for cf_name, cf_value in custom_fields.items():
custom_field = CustomField.objects.get(name=cf_name)
custom_field_value = CustomFieldValue.objects.create(
field=custom_field,
obj=vlan,
value=cf_value
)
vlan.custom_field_values.add(custom_field_value) print("🏠 Created VLAN", vlan.name)
print("🏠 Created VLAN", vlan.name)

View File

@ -2,53 +2,45 @@ from dcim.models import Site
from ipam.models import Prefix, VLAN, Role, VRF from ipam.models import Prefix, VLAN, Role, VRF
from tenancy.models import Tenant, TenantGroup from tenancy.models import Tenant, TenantGroup
from extras.models import CustomField, CustomFieldValue from extras.models import CustomField, CustomFieldValue
from ruamel.yaml import YAML
from netaddr import IPNetwork from netaddr import IPNetwork
from pathlib import Path from startup_script_utils import load_yaml
import sys import sys
file = Path('/opt/netbox/initializers/prefixes.yml') prefixes = load_yaml('/opt/netbox/initializers/prefixes.yml')
if not file.is_file():
if prefixes is None:
sys.exit() sys.exit()
with file.open('r') as stream: optional_assocs = {
yaml = YAML(typ='safe') 'site': (Site, 'name'),
prefixes = yaml.load(stream) 'tenant': (Tenant, 'name'),
'tenant_group': (TenantGroup, 'name'),
'vlan': (VLAN, 'name'),
'role': (Role, 'name'),
'vrf': (VRF, 'name')
}
optional_assocs = { for params in prefixes:
'site': (Site, 'name'), custom_fields = params.pop('custom_fields', None)
'tenant': (Tenant, 'name'), params['prefix'] = IPNetwork(params['prefix'])
'tenant_group': (TenantGroup, 'name'),
'vlan': (VLAN, 'name'),
'role': (Role, 'name'),
'vrf': (VRF, 'name')
}
if prefixes is not None: for assoc, details in optional_assocs.items():
for params in prefixes: if assoc in params:
custom_fields = params.pop('custom_fields', None) model, field = details
params['prefix'] = IPNetwork(params['prefix']) query = { field: params.pop(assoc) }
params[assoc] = model.objects.get(**query)
for assoc, details in optional_assocs.items(): prefix, created = Prefix.objects.get_or_create(**params)
if assoc in params:
model, field = details
query = { field: params.pop(assoc) }
params[assoc] = model.objects.get(**query) if created:
if custom_fields is not None:
for cf_name, cf_value in custom_fields.items():
custom_field = CustomField.objects.get(name=cf_name)
custom_field_value = CustomFieldValue.objects.create(
field=custom_field,
obj=prefix,
value=cf_value
)
prefix.custom_field_values.add(custom_field_value)
prefix, created = Prefix.objects.get_or_create(**params) print("📌 Created Prefix", prefix.prefix)
if created:
if custom_fields is not None:
for cf_name, cf_value in custom_fields.items():
custom_field = CustomField.objects.get(name=cf_name)
custom_field_value = CustomFieldValue.objects.create(
field=custom_field,
obj=prefix,
value=cf_value
)
prefix.custom_field_values.add(custom_field_value)
print("📌 Created Prefix", prefix.prefix)

View File

@ -2,58 +2,52 @@ from dcim.models import Site, Platform, DeviceRole
from virtualization.models import Cluster, VirtualMachine from virtualization.models import Cluster, VirtualMachine
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 startup_script_utils import load_yaml
from pathlib import Path
import sys import sys
file = Path('/opt/netbox/initializers/virtual_machines.yml') virtual_machines = load_yaml('/opt/netbox/initializers/virtual_machines.yml')
if not file.is_file():
if virtual_machines is None:
sys.exit() sys.exit()
with file.open('r') as stream: required_assocs = {
yaml = YAML(typ='safe') 'cluster': (Cluster, 'name')
virtual_machines = yaml.load(stream) }
required_assocs = { optional_assocs = {
'cluster': (Cluster, 'name') 'tenant': (Tenant, 'name'),
} 'platform': (Platform, 'name'),
'role': (DeviceRole, 'name')
}
optional_assocs = { for params in virtual_machines:
'tenant': (Tenant, 'name'), custom_fields = params.pop('custom_fields', None)
'platform': (Platform, 'name'),
'role': (DeviceRole, 'name')
}
if virtual_machines is not None: for assoc, details in required_assocs.items():
for params in virtual_machines: model, field = details
custom_fields = params.pop('custom_fields', None) query = { field: params.pop(assoc) }
for assoc, details in required_assocs.items(): params[assoc] = model.objects.get(**query)
model, field = details
query = { field: params.pop(assoc) }
params[assoc] = model.objects.get(**query) for assoc, details in optional_assocs.items():
if assoc in params:
model, field = details
query = { field: params.pop(assoc) }
for assoc, details in optional_assocs.items(): params[assoc] = model.objects.get(**query)
if assoc in params:
model, field = details
query = { field: params.pop(assoc) }
params[assoc] = model.objects.get(**query) virtual_machine, created = VirtualMachine.objects.get_or_create(**params)
virtual_machine, created = VirtualMachine.objects.get_or_create(**params) if created:
if custom_fields is not None:
for cf_name, cf_value in custom_fields.items():
custom_field = CustomField.objects.get(name=cf_name)
custom_field_value = CustomFieldValue.objects.create(
field=custom_field,
obj=virtual_machine,
value=cf_value
)
if created: virtual_machine.custom_field_values.add(custom_field_value)
if custom_fields is not None:
for cf_name, cf_value in custom_fields.items():
custom_field = CustomField.objects.get(name=cf_name)
custom_field_value = CustomFieldValue.objects.create(
field=custom_field,
obj=virtual_machine,
value=cf_value
)
virtual_machine.custom_field_values.add(custom_field_value) print("🖥️ Created virtual machine", virtual_machine.name)
print("🖥️ Created virtual machine", virtual_machine.name)

View File

@ -1,45 +1,39 @@
from dcim.models import Interface from dcim.models import Interface
from virtualization.models import VirtualMachine from virtualization.models import VirtualMachine
from extras.models import CustomField, CustomFieldValue from extras.models import CustomField, CustomFieldValue
from ruamel.yaml import YAML from startup_script_utils import load_yaml
from pathlib import Path
import sys import sys
file = Path('/opt/netbox/initializers/virtualization_interfaces.yml') interfaces = load_yaml('/opt/netbox/initializers/virtualization_interfaces.yml')
if not file.is_file():
if interfaces is None:
sys.exit() sys.exit()
with file.open('r') as stream: required_assocs = {
yaml = YAML(typ='safe') 'virtual_machine': (VirtualMachine, 'name')
interfaces = yaml.load(stream) }
required_assocs = { for params in interfaces:
'virtual_machine': (VirtualMachine, 'name') custom_fields = params.pop('custom_fields', None)
}
if interfaces is not None: for assoc, details in required_assocs.items():
for params in interfaces: model, field = details
custom_fields = params.pop('custom_fields', None) query = { field: params.pop(assoc) }
for assoc, details in required_assocs.items(): params[assoc] = model.objects.get(**query)
model, field = details
query = { field: params.pop(assoc) }
params[assoc] = model.objects.get(**query) interface, created = Interface.objects.get_or_create(**params)
interface, created = Interface.objects.get_or_create(**params) if created:
if custom_fields is not None:
for cf_name, cf_value in custom_fields.items():
custom_field = CustomField.objects.get(name=cf_name)
custom_field_value = CustomFieldValue.objects.create(
field=custom_field,
obj=interface,
value=cf_value
)
if created: interface.custom_field_values.add(custom_field_value)
if custom_fields is not None:
for cf_name, cf_value in custom_fields.items():
custom_field = CustomField.objects.get(name=cf_name)
custom_field_value = CustomFieldValue.objects.create(
field=custom_field,
obj=interface,
value=cf_value
)
interface.custom_field_values.add(custom_field_value) print("🧷 Created interface", interface.name, interface.virtual_machine.name)
print("🧷 Created interface", interface.name, interface.virtual_machine.name)

View File

@ -1,44 +1,38 @@
from dcim.models import Interface, Device from dcim.models import Interface, Device
from extras.models import CustomField, CustomFieldValue from extras.models import CustomField, CustomFieldValue
from ruamel.yaml import YAML from startup_script_utils import load_yaml
from pathlib import Path
import sys import sys
file = Path('/opt/netbox/initializers/dcim_interfaces.yml') interfaces= load_yaml('/opt/netbox/initializers/dcim_interfaces.yml')
if not file.is_file():
if interfaces is None:
sys.exit() sys.exit()
with file.open('r') as stream: required_assocs = {
yaml = YAML(typ='safe') 'device': (Device, 'name')
interfaces = yaml.load(stream) }
required_assocs = { for params in interfaces:
'device': (Device, 'name') custom_fields = params.pop('custom_fields', None)
}
if interfaces is not None: for assoc, details in required_assocs.items():
for params in interfaces: model, field = details
custom_fields = params.pop('custom_fields', None) query = { field: params.pop(assoc) }
for assoc, details in required_assocs.items(): params[assoc] = model.objects.get(**query)
model, field = details
query = { field: params.pop(assoc) }
params[assoc] = model.objects.get(**query) interface, created = Interface.objects.get_or_create(**params)
interface, created = Interface.objects.get_or_create(**params) if created:
if custom_fields is not None:
for cf_name, cf_value in custom_fields.items():
custom_field = CustomField.objects.get(name=cf_name)
custom_field_value = CustomFieldValue.objects.create(
field=custom_field,
obj=interface,
value=cf_value
)
if created: interface.custom_field_values.add(custom_field_value)
if custom_fields is not None:
for cf_name, cf_value in custom_fields.items():
custom_field = CustomField.objects.get(name=cf_name)
custom_field_value = CustomFieldValue.objects.create(
field=custom_field,
obj=interface,
value=cf_value
)
interface.custom_field_values.add(custom_field_value) print("🧷 Created interface", interface.name, interface.device.name)
print("🧷 Created interface", interface.name, interface.device.name)

View File

@ -3,63 +3,58 @@ from dcim.models import Device, Interface
from virtualization.models import VirtualMachine from virtualization.models import VirtualMachine
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 netaddr import IPNetwork from netaddr import IPNetwork
from pathlib import Path from startup_script_utils import load_yaml
import sys import sys
file = Path('/opt/netbox/initializers/ip_addresses.yml') ip_addresses = load_yaml('/opt/netbox/initializers/ip_addresses.yml')
if not file.is_file():
if ip_addresses is None:
sys.exit() sys.exit()
with file.open('r') as stream: optional_assocs = {
yaml = YAML(typ='safe') 'tenant': (Tenant, 'name'),
ip_addresses = yaml.load(stream) 'vrf': (VRF, 'name'),
'interface': (Interface, 'name')
}
optional_assocs = { for params in ip_addresses:
'tenant': (Tenant, 'name'), vm = params.pop('virtual_machine', None)
'vrf': (VRF, 'name'), device = params.pop('device', None)
'interface': (Interface, 'name') custom_fields = params.pop('custom_fields', None)
} params['address'] = IPNetwork(params['address'])
if ip_addresses is not None: if vm and device:
for params in ip_addresses: print("IP Address can only specify one of the following: virtual_machine or device.")
vm = params.pop('virtual_machine', None) sys.exit()
device = params.pop('device', None)
custom_fields = params.pop('custom_fields', None)
params['address'] = IPNetwork(params['address'])
if vm and device: for assoc, details in optional_assocs.items():
print("IP Address can only specify one of the following: virtual_machine or device.") if assoc in params:
sys.exit() model, field = details
if assoc == 'interface':
if vm:
vm_id = VirtualMachine.objects.get(name=vm).id
query = { field: params.pop(assoc), "virtual_machine_id": vm_id }
elif device:
dev_id = Device.objects.get(name=device).id
query = { field: params.pop(assoc), "device_id": dev_id }
else:
query = { field: params.pop(assoc) }
params[assoc] = model.objects.get(**query)
for assoc, details in optional_assocs.items(): ip_address, created = IPAddress.objects.get_or_create(**params)
if assoc in params:
model, field = details
if assoc == 'interface':
if vm:
vm_id = VirtualMachine.objects.get(name=vm).id
query = { field: params.pop(assoc), "virtual_machine_id": vm_id }
elif device:
dev_id = Device.objects.get(name=device).id
query = { field: params.pop(assoc), "device_id": dev_id }
else:
query = { field: params.pop(assoc) }
params[assoc] = model.objects.get(**query)
ip_address, created = IPAddress.objects.get_or_create(**params) if created:
if custom_fields is not None:
for cf_name, cf_value in custom_fields.items():
custom_field = CustomField.objects.get(name=cf_name)
custom_field_value = CustomFieldValue.objects.create(
field=custom_field,
obj=ip_address,
value=cf_value
)
if created: ip_address.custom_field_values.add(custom_field_value)
if custom_fields is not None:
for cf_name, cf_value in custom_fields.items():
custom_field = CustomField.objects.get(name=cf_name)
custom_field_value = CustomFieldValue.objects.create(
field=custom_field,
obj=ip_address,
value=cf_value
)
ip_address.custom_field_values.add(custom_field_value) print("🧬 Created IP Address", ip_address.address)
print("🧬 Created IP Address", ip_address.address)

View File

@ -0,0 +1,2 @@
from .load_yaml import load_yaml
from .permissions import set_permissions

View File

@ -0,0 +1,10 @@
from ruamel.yaml import YAML
from pathlib import Path
def load_yaml(yaml_file: str):
yf = Path(yaml_file)
if not yf.is_file():
return None
with yf.open("r") as stream:
yaml = YAML(typ="safe")
return yaml.load(stream)

View File

@ -0,0 +1,18 @@
from django.contrib.auth.models import Permission
def set_permissions(subject, permission_filters):
if subject is None or permission_filters is None:
return
subject.clear()
for permission_filter in permission_filters:
if "*" in permission_filter:
permission_filter_regex = "^" + permission_filter.replace("*", ".*") + "$"
permissions = Permission.objects.filter(codename__iregex=permission_filter_regex)
print(" ⚿ Granting", permissions.count(), "permissions matching '" + permission_filter + "'")
else:
permissions = Permission.objects.filter(codename=permission_filter)
print(" ⚿ Granting permission", permission_filter)
for permission in permissions:
subject.add(permission)