osism 0.20250219.0__py3-none-any.whl → 0.20250314.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- osism/actions/manage_device.py +28 -887
- osism/api.py +18 -0
- osism/commands/netbox.py +38 -327
- osism/services/listener.py +223 -133
- osism/settings.py +2 -3
- osism/tasks/__init__.py +44 -14
- osism/tasks/netbox.py +22 -98
- osism-0.20250314.0.dist-info/AUTHORS +1 -0
- {osism-0.20250219.0.dist-info → osism-0.20250314.0.dist-info}/METADATA +14 -14
- {osism-0.20250219.0.dist-info → osism-0.20250314.0.dist-info}/RECORD +15 -19
- {osism-0.20250219.0.dist-info → osism-0.20250314.0.dist-info}/WHEEL +1 -1
- {osism-0.20250219.0.dist-info → osism-0.20250314.0.dist-info}/entry_points.txt +1 -9
- osism-0.20250314.0.dist-info/pbr.json +1 -0
- osism/actions/check_configuration.py +0 -49
- osism/actions/deploy_configuration.py +0 -92
- osism/actions/diff_configuration.py +0 -59
- osism/actions/generate_configuration.py +0 -137
- osism-0.20250219.0.dist-info/AUTHORS +0 -1
- osism-0.20250219.0.dist-info/pbr.json +0 -1
- {osism-0.20250219.0.dist-info → osism-0.20250314.0.dist-info}/LICENSE +0 -0
- {osism-0.20250219.0.dist-info → osism-0.20250314.0.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.2
|
2
2
|
Name: osism
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.20250314.0
|
4
4
|
Summary: OSISM manager interface
|
5
5
|
Home-page: https://github.com/osism/python-osism
|
6
6
|
Author: OSISM GmbH
|
@@ -24,44 +24,44 @@ License-File: LICENSE
|
|
24
24
|
License-File: AUTHORS
|
25
25
|
Requires-Dist: ClusterShell==1.9.3
|
26
26
|
Requires-Dist: GitPython==3.1.44
|
27
|
-
Requires-Dist: Jinja2==3.1.
|
27
|
+
Requires-Dist: Jinja2==3.1.6
|
28
28
|
Requires-Dist: PyYAML==6.0.2
|
29
29
|
Requires-Dist: ara==1.7.2
|
30
30
|
Requires-Dist: celery[redis]==5.4.0
|
31
|
-
Requires-Dist: cliff==4.
|
32
|
-
Requires-Dist: deepdiff==8.
|
31
|
+
Requires-Dist: cliff==4.9.1
|
32
|
+
Requires-Dist: deepdiff==8.3.0
|
33
33
|
Requires-Dist: docker==7.1.0
|
34
34
|
Requires-Dist: dtrack-auditor==1.5.0
|
35
|
-
Requires-Dist: fastapi==0.115.
|
35
|
+
Requires-Dist: fastapi==0.115.11
|
36
36
|
Requires-Dist: flower==2.0.1
|
37
37
|
Requires-Dist: hiredis==3.1.0
|
38
38
|
Requires-Dist: jc==1.25.4
|
39
|
-
Requires-Dist: keystoneauth1==5.
|
40
|
-
Requires-Dist: kombu==5.
|
41
|
-
Requires-Dist: kubernetes==32.0.
|
39
|
+
Requires-Dist: keystoneauth1==5.10.0
|
40
|
+
Requires-Dist: kombu==5.5.0
|
41
|
+
Requires-Dist: kubernetes==32.0.1
|
42
42
|
Requires-Dist: loguru==0.7.3
|
43
43
|
Requires-Dist: netmiko==4.5.0
|
44
44
|
Requires-Dist: nornir-ansible==2023.12.28
|
45
45
|
Requires-Dist: nornir==3.5.0
|
46
|
-
Requires-Dist: openstacksdk==4.
|
46
|
+
Requires-Dist: openstacksdk==4.4.0
|
47
47
|
Requires-Dist: pottery==3.0.0
|
48
48
|
Requires-Dist: prompt-toolkit==3.0.50
|
49
49
|
Requires-Dist: pydantic==1.10.21
|
50
50
|
Requires-Dist: pynetbox==7.4.1
|
51
51
|
Requires-Dist: pytest-testinfra==10.1.1
|
52
52
|
Requires-Dist: python-dateutil==2.9.0.post0
|
53
|
-
Requires-Dist: setuptools==
|
54
|
-
Requires-Dist: sqlmodel==0.0.
|
55
|
-
Requires-Dist: sushy==5.
|
53
|
+
Requires-Dist: setuptools==76.0.0
|
54
|
+
Requires-Dist: sqlmodel==0.0.24
|
55
|
+
Requires-Dist: sushy==5.5.0
|
56
56
|
Requires-Dist: tabulate==0.9.0
|
57
57
|
Requires-Dist: transitions==0.9.2
|
58
58
|
Requires-Dist: uvicorn[standard]==0.34.0
|
59
59
|
Requires-Dist: watchdog==6.0.0
|
60
60
|
Provides-Extra: ansible
|
61
61
|
Requires-Dist: ansible-runner==2.4.0; extra == "ansible"
|
62
|
-
Requires-Dist: ansible-core==2.18.
|
62
|
+
Requires-Dist: ansible-core==2.18.3; extra == "ansible"
|
63
63
|
Provides-Extra: openstack-image-manager
|
64
|
-
Requires-Dist: openstack-image-manager==0.
|
64
|
+
Requires-Dist: openstack-image-manager==0.20250314.0; extra == "openstack-image-manager"
|
65
65
|
Dynamic: author
|
66
66
|
Dynamic: author-email
|
67
67
|
Dynamic: classifier
|
@@ -1,14 +1,10 @@
|
|
1
1
|
osism/__init__.py,sha256=1UiNTBus0V0f2AbZQzAtVtu6zkfCCrw0OTq--NwFAqY,341
|
2
2
|
osism/__main__.py,sha256=ILe4gu61xEISiBsxanqTQIdSkV-YhpZXTRlguCYyssk,141
|
3
|
-
osism/api.py,sha256=
|
3
|
+
osism/api.py,sha256=X3IVLWbKMtfozJ5sEx6sLEZ1rD4U9s3uNnLLwxiwDjs,4802
|
4
4
|
osism/main.py,sha256=Dt2-9sLXcS-Ny4DAz7hrha-KRc7zd7BFUTRdfs_X8z4,893
|
5
|
-
osism/settings.py,sha256=
|
5
|
+
osism/settings.py,sha256=m__DltxKQo5D-vDKKwY8RNBVs5bverYdJmtyVyln_6o,1049
|
6
6
|
osism/actions/__init__.py,sha256=bG7Ffen4LvQtgnYPFEpFccsWs81t4zqqeqn9ZeirH6E,38
|
7
|
-
osism/actions/
|
8
|
-
osism/actions/deploy_configuration.py,sha256=uHrW6J0908zloK3SnOcKq3m53H8KCihplU1IA10mZMA,2712
|
9
|
-
osism/actions/diff_configuration.py,sha256=sGoUPQWxINE_qqqBgePxOtEOXgtMFRM43TGJtGFFwhs,1513
|
10
|
-
osism/actions/generate_configuration.py,sha256=eAv1IfKYMw3466rStHB1HXHVksM0wn4CrHjZDfTgV40,4391
|
11
|
-
osism/actions/manage_device.py,sha256=VXrRRcu78i05QjmN3t3vdeF1OoMAE7oYUaSyK0aJOjo,37457
|
7
|
+
osism/actions/manage_device.py,sha256=joQwPnwEUw5V1ZRRbdrM0FjfNlG4vPNc0r8FBRTOJiA,3541
|
12
8
|
osism/actions/manage_interface.py,sha256=iDp7zY16XXtwdLk1sxa-TBAkpdPxmtbVeEvMZuP5h4s,472
|
13
9
|
osism/commands/__init__.py,sha256=Ag4wX_DCgXRdoLn6t069jqb3DdRylsX2nyYkiyCx4uk,456
|
14
10
|
osism/commands/apply.py,sha256=n3lLb1cS3GahQqRT0723di98hg47MjVzDzkAoeZX7qU,16780
|
@@ -20,7 +16,7 @@ osism/commands/container.py,sha256=Fku2GaCM3Idq_FxExUtNqjrEM0XYjpVvXmueSVO8S_c,1
|
|
20
16
|
osism/commands/get.py,sha256=ryytjtXWmlMV0NucP5tGkMZu0nIlC4xVtjRk4iMZ06c,8967
|
21
17
|
osism/commands/log.py,sha256=2IpYuosC7FZwwLvM8HmKSU1NRNIelVVYzqjjVMCrOJk,4072
|
22
18
|
osism/commands/manage.py,sha256=HGU1VPU7rBJ2oYfaAbg2IzjRjOYatVNRv1gUUDFgEqk,9690
|
23
|
-
osism/commands/netbox.py,sha256=
|
19
|
+
osism/commands/netbox.py,sha256=OJiNAdMObIt2ffc7C80eLRjwqZmD4lgidQ8I8VWtF8s,4900
|
24
20
|
osism/commands/noset.py,sha256=7zDFuFMyNpo7DUOKcNiYV8nodtdMOYFp5LDPcuJhlZ8,1481
|
25
21
|
osism/commands/reconciler.py,sha256=Ja_b86gX6-_Pr3DmrUUvskmEnnJpHQ-XJNQLycMJeyc,2818
|
26
22
|
osism/commands/server.py,sha256=zFXRdYoj4ZNDJNPSaGddMPEWxt8G2GyMomPOcCOaN3c,4137
|
@@ -40,22 +36,22 @@ osism/core/playbooks.py,sha256=M3T3ajV-8Lt-orsRO3jAoukhaoYFr4EZ2dzYXQjt1kg,728
|
|
40
36
|
osism/data/__init__.py,sha256=izXdh0J3vPLQI7kBhJI7ibJQzPqU_nlONP0L4Cf_k6A,1504
|
41
37
|
osism/plugins/__init__.py,sha256=bG7Ffen4LvQtgnYPFEpFccsWs81t4zqqeqn9ZeirH6E,38
|
42
38
|
osism/services/__init__.py,sha256=bG7Ffen4LvQtgnYPFEpFccsWs81t4zqqeqn9ZeirH6E,38
|
43
|
-
osism/services/listener.py,sha256=
|
44
|
-
osism/tasks/__init__.py,sha256=
|
39
|
+
osism/services/listener.py,sha256=JjCdwPG5U9b_xYDpGFQeiLPP4y00GM3Me6NW1tt6Jws,11275
|
40
|
+
osism/tasks/__init__.py,sha256=qZQGMeaaeUN9CUBqVXGEx2pvDZpDJbhudq0jl4-7GRU,9111
|
45
41
|
osism/tasks/ansible.py,sha256=0c5nY1M0jf_9Me8HMP2Je_Ibjii4rFm-5HW8tmE6aos,1681
|
46
42
|
osism/tasks/ceph.py,sha256=eIQkah3Kj4INtOkF9kTjHbXJ3_J2lg48EWJKfHc-UYw,615
|
47
43
|
osism/tasks/conductor.py,sha256=g9ulqWlGim0DjwQkVgW8Tl8MsXBGuukuQvM12CXbEmM,3892
|
48
44
|
osism/tasks/kolla.py,sha256=wJQpWn_01iWLkr7l7T7RNrQGfRgsgmYi4WQlTmNGvew,618
|
49
45
|
osism/tasks/kubernetes.py,sha256=VzXq_VrYU_CLm4cOruqnE3Kq2ydfO9glZ3p0bp3OYoc,625
|
50
|
-
osism/tasks/netbox.py,sha256=
|
46
|
+
osism/tasks/netbox.py,sha256=yR8z6VYkNXmNCsHzxP6KGmPtGW5mbpLks8XEw6TUwjk,4692
|
51
47
|
osism/tasks/openstack.py,sha256=i9dIVz9RPVC38gIhUPIE0oq8Wj2ppf9bHrHLTrsjaJ8,9098
|
52
48
|
osism/tasks/reconciler.py,sha256=RpepZtRgBgYTwmAkfuT9kIaxU1ITDb8SFalMoShdRNQ,3547
|
53
49
|
osism/utils/__init__.py,sha256=5yng8l5Jd6GhNO4FNi6iYH4569UuTYAynamANgZnm1E,1258
|
54
|
-
osism-0.
|
55
|
-
osism-0.
|
56
|
-
osism-0.
|
57
|
-
osism-0.
|
58
|
-
osism-0.
|
59
|
-
osism-0.
|
60
|
-
osism-0.
|
61
|
-
osism-0.
|
50
|
+
osism-0.20250314.0.dist-info/AUTHORS,sha256=DJIRsjyrFxKjFvmpUNDRDBS04nRiJ5B6FpKcDcfnoGM,36
|
51
|
+
osism-0.20250314.0.dist-info/LICENSE,sha256=tAkwu8-AdEyGxGoSvJ2gVmQdcicWw3j1ZZueVV74M-E,11357
|
52
|
+
osism-0.20250314.0.dist-info/METADATA,sha256=9Yv6LRSN9ZDCXQN5U4KpHrZZK7j7hW4NIJcP11nKO58,2950
|
53
|
+
osism-0.20250314.0.dist-info/WHEEL,sha256=52BFRY2Up02UkjOa29eZOS2VxUrpPORXg1pkohGGUS8,91
|
54
|
+
osism-0.20250314.0.dist-info/entry_points.txt,sha256=8yx03jRhfk45lMfGV8t4tZ2Xp95puuj8LEnx9Ogjefc,3050
|
55
|
+
osism-0.20250314.0.dist-info/pbr.json,sha256=Wlz72FgMvVrweUm0EjV2XpPxCiO9BCUCpb61UvKTyBc,47
|
56
|
+
osism-0.20250314.0.dist-info/top_level.txt,sha256=8L8dsI9hcaGHsdnR4k_LN9EM78EhwrXRFHyAryPXZtY,6
|
57
|
+
osism-0.20250314.0.dist-info/RECORD,,
|
@@ -36,19 +36,11 @@ manage flavors = osism.commands.manage:Flavors
|
|
36
36
|
manage image clusterapi = osism.commands.manage:ImageClusterapi
|
37
37
|
manage image octavia = osism.commands.manage:ImageOctavia
|
38
38
|
manage images = osism.commands.manage:Images
|
39
|
+
manage netbox = osism.commands.netbox:Manage
|
39
40
|
manage server list = osism.commands.server:ServerList
|
40
41
|
manage server migrate = osism.commands.server:ServerMigrate
|
41
42
|
manage volume list = osism.commands.volume:VolumeList
|
42
43
|
netbox = osism.commands.netbox:Run
|
43
|
-
netbox check = osism.commands.netbox:Check
|
44
|
-
netbox connect = osism.commands.netbox:Connect
|
45
|
-
netbox deploy = osism.commands.netbox:Deploy
|
46
|
-
netbox diff = osism.commands.netbox:Diff
|
47
|
-
netbox disable = osism.commands.netbox:Disable
|
48
|
-
netbox generate = osism.commands.netbox:Generate
|
49
|
-
netbox import = osism.commands.netbox:Import
|
50
|
-
netbox init = osism.commands.netbox:Init
|
51
|
-
netbox manage = osism.commands.netbox:Manage
|
52
44
|
netbox ping = osism.commands.netbox:Ping
|
53
45
|
netbox sync = osism.commands.netbox:Sync
|
54
46
|
netbox sync ironic = osism.commands.netbox:Ironic
|
@@ -0,0 +1 @@
|
|
1
|
+
{"git_version": "73a2ae0", "is_release": false}
|
@@ -1,49 +0,0 @@
|
|
1
|
-
# SPDX-License-Identifier: Apache-2.0
|
2
|
-
|
3
|
-
from loguru import logger
|
4
|
-
from pottery import Redlock
|
5
|
-
|
6
|
-
from osism import utils
|
7
|
-
|
8
|
-
|
9
|
-
def for_device(name, parameters={}):
|
10
|
-
device = utils.nb.dcim.devices.get(name=name)
|
11
|
-
|
12
|
-
if (
|
13
|
-
"device_type" not in device.custom_fields
|
14
|
-
or device.custom_fields["device_type"] != "switch"
|
15
|
-
):
|
16
|
-
return
|
17
|
-
|
18
|
-
if "Managed by OSISM" not in [str(x) for x in device.tags]:
|
19
|
-
return
|
20
|
-
|
21
|
-
if "deployment_enabled" in device.custom_fields and not bool(
|
22
|
-
device.custom_fields["deployment_enabled"]
|
23
|
-
):
|
24
|
-
return
|
25
|
-
|
26
|
-
if "deployment_type" not in device.custom_fields:
|
27
|
-
return
|
28
|
-
|
29
|
-
# Allow only one change per time
|
30
|
-
lock = Redlock(
|
31
|
-
key=f"lock_check_{name}", masters={utils.redis}, auto_release_time=120
|
32
|
-
)
|
33
|
-
lock.acquire()
|
34
|
-
|
35
|
-
logger.info(
|
36
|
-
f"Check configuration for device {device.name} with plugin {device.custom_fields['deployment_type']}"
|
37
|
-
)
|
38
|
-
|
39
|
-
deployment_type = device.custom_fields["deployment_type"]
|
40
|
-
logger.error(
|
41
|
-
f"Deployment type {deployment_type} for device {device.name} not supported"
|
42
|
-
)
|
43
|
-
last_configuration = None
|
44
|
-
|
45
|
-
if last_configuration:
|
46
|
-
for line in last_configuration.split("\n"):
|
47
|
-
logger.info(f"configuration - {device.name}: {line}")
|
48
|
-
|
49
|
-
lock.release()
|
@@ -1,92 +0,0 @@
|
|
1
|
-
# SPDX-License-Identifier: Apache-2.0
|
2
|
-
|
3
|
-
from loguru import logger
|
4
|
-
from pottery import Redlock
|
5
|
-
import git
|
6
|
-
import jinja2
|
7
|
-
|
8
|
-
from osism import utils
|
9
|
-
|
10
|
-
|
11
|
-
def for_device(name, parameters={}, mode="deploy"):
|
12
|
-
device = utils.nb.dcim.devices.get(name=name)
|
13
|
-
|
14
|
-
if (
|
15
|
-
"device_type" not in device.custom_fields
|
16
|
-
or device.custom_fields["device_type"] != "switch"
|
17
|
-
):
|
18
|
-
return
|
19
|
-
|
20
|
-
if "Managed by OSISM" not in [str(x) for x in device.tags]:
|
21
|
-
return
|
22
|
-
|
23
|
-
if "deployment_enabled" in device.custom_fields and not bool(
|
24
|
-
device.custom_fields["deployment_enabled"]
|
25
|
-
):
|
26
|
-
return
|
27
|
-
|
28
|
-
if "deployment_type" not in device.custom_fields:
|
29
|
-
return
|
30
|
-
|
31
|
-
# Allow only one change per time
|
32
|
-
lock = Redlock(
|
33
|
-
key=f"lock_deploy_{name}", masters={utils.redis}, auto_release_time=120
|
34
|
-
)
|
35
|
-
lock.acquire()
|
36
|
-
|
37
|
-
repo = git.Repo.init(path="/state")
|
38
|
-
|
39
|
-
first = False
|
40
|
-
|
41
|
-
if device.name in repo.tags:
|
42
|
-
last_commit = repo.commit(device.name)
|
43
|
-
current_commit = repo.head.commit
|
44
|
-
else:
|
45
|
-
first = True
|
46
|
-
last_commit = repo.head.commit
|
47
|
-
current_commit = repo.head.commit
|
48
|
-
|
49
|
-
if device.name in repo.tags and mode == "deploy":
|
50
|
-
repo.delete_tag(name)
|
51
|
-
|
52
|
-
if not first and last_commit == current_commit and mode == "deploy":
|
53
|
-
logger.info(f"No deployment for device {device.name} required")
|
54
|
-
else:
|
55
|
-
if not first:
|
56
|
-
try:
|
57
|
-
last_configuration = repo.git.show(
|
58
|
-
f"{last_commit.hexsha}:{device.name}.cfg.j2"
|
59
|
-
)
|
60
|
-
except git.exc.GitCommandError:
|
61
|
-
last_configuration = None
|
62
|
-
else:
|
63
|
-
last_configuration = None
|
64
|
-
|
65
|
-
try:
|
66
|
-
current_configuration = repo.git.show(
|
67
|
-
f"{current_commit.hexsha}:{device.name}.cfg.j2"
|
68
|
-
)
|
69
|
-
except git.exc.GitCommandError:
|
70
|
-
current_configuration = None
|
71
|
-
|
72
|
-
if not current_configuration:
|
73
|
-
logger.error(f"There is no prepared configuration for device {device.name}")
|
74
|
-
else:
|
75
|
-
t = jinja2.Environment(loader=jinja2.BaseLoader()).from_string(
|
76
|
-
current_configuration
|
77
|
-
)
|
78
|
-
rendered_current_configuration = t.render(**parameters)
|
79
|
-
|
80
|
-
logger.info(
|
81
|
-
f"{mode} configuration for device {device.name} with plugin {device.custom_fields['deployment_type']}"
|
82
|
-
)
|
83
|
-
|
84
|
-
deployment_type = device.custom_fields["deployment_type"]
|
85
|
-
logger.error(
|
86
|
-
f"Deployment type {deployment_type} for device {device.name} not supported"
|
87
|
-
)
|
88
|
-
|
89
|
-
if mode == "deploy":
|
90
|
-
repo.create_tag(device.name, current_commit)
|
91
|
-
|
92
|
-
lock.release()
|
@@ -1,59 +0,0 @@
|
|
1
|
-
# SPDX-License-Identifier: Apache-2.0
|
2
|
-
|
3
|
-
from loguru import logger
|
4
|
-
import git
|
5
|
-
from pottery import Redlock
|
6
|
-
|
7
|
-
from osism import utils
|
8
|
-
|
9
|
-
|
10
|
-
def for_device(name, parameters={}):
|
11
|
-
device = utils.nb.dcim.devices.get(name=name)
|
12
|
-
|
13
|
-
if (
|
14
|
-
"device_type" not in device.custom_fields
|
15
|
-
or device.custom_fields["device_type"] != "switch"
|
16
|
-
):
|
17
|
-
return
|
18
|
-
|
19
|
-
if "Managed by OSISM" not in [str(x) for x in device.tags]:
|
20
|
-
return
|
21
|
-
|
22
|
-
if "deployment_enabled" in device.custom_fields and not bool(
|
23
|
-
device.custom_fields["deployment_enabled"]
|
24
|
-
):
|
25
|
-
return
|
26
|
-
|
27
|
-
if "deployment_type" not in device.custom_fields:
|
28
|
-
return
|
29
|
-
|
30
|
-
# Allow only one change per time
|
31
|
-
lock = Redlock(
|
32
|
-
key=f"lock_diff_{name}", masters={utils.redis}, auto_release_time=120
|
33
|
-
)
|
34
|
-
lock.acquire()
|
35
|
-
|
36
|
-
logger.info(
|
37
|
-
f"Diff configuration for device {device.name} with plugin {device.custom_fields['deployment_type']}"
|
38
|
-
)
|
39
|
-
|
40
|
-
deployment_type = device.custom_fields["deployment_type"]
|
41
|
-
logger.error(
|
42
|
-
f"Deployment type {deployment_type} for device {device.name} not supported"
|
43
|
-
)
|
44
|
-
current_configuration = None
|
45
|
-
|
46
|
-
repo = git.Repo.init(path="/state")
|
47
|
-
|
48
|
-
try:
|
49
|
-
last_configuration = repo.git.show(
|
50
|
-
f"{repo.head.commit.hexsha}:{device.name}.cfg.j2"
|
51
|
-
)
|
52
|
-
except git.exc.GitCommandError:
|
53
|
-
last_configuration = None
|
54
|
-
|
55
|
-
logger.error(
|
56
|
-
f"Deployment type {deployment_type} for device {device.name} not supported"
|
57
|
-
)
|
58
|
-
|
59
|
-
lock.release()
|
@@ -1,137 +0,0 @@
|
|
1
|
-
# SPDX-License-Identifier: Apache-2.0
|
2
|
-
|
3
|
-
from datetime import datetime
|
4
|
-
import ipaddress
|
5
|
-
import os
|
6
|
-
|
7
|
-
from loguru import logger
|
8
|
-
import git
|
9
|
-
import gitdb
|
10
|
-
import jinja2
|
11
|
-
from pottery import Redlock
|
12
|
-
|
13
|
-
from osism.utils import first
|
14
|
-
from osism import utils
|
15
|
-
|
16
|
-
|
17
|
-
def vlans_as_string(untagged_vlan, tagged_vlans):
|
18
|
-
vlans = [str(x.vid) for x in tagged_vlans]
|
19
|
-
if untagged_vlan:
|
20
|
-
vlans = vlans + [str(untagged_vlan.vid)]
|
21
|
-
return ",".join(sorted(vlans))
|
22
|
-
|
23
|
-
|
24
|
-
def for_device(name, template=None):
|
25
|
-
device = utils.nb.dcim.devices.get(name=name)
|
26
|
-
|
27
|
-
if (
|
28
|
-
"device_type" not in device.custom_fields
|
29
|
-
or device.custom_fields["device_type"] != "switch"
|
30
|
-
):
|
31
|
-
return
|
32
|
-
|
33
|
-
if "Managed by OSISM" not in [str(x) for x in device.tags]:
|
34
|
-
return
|
35
|
-
|
36
|
-
logger.info(f"Generate configuration for device {device.name}")
|
37
|
-
|
38
|
-
if not template:
|
39
|
-
template = f"{device.name}.cfg.j2"
|
40
|
-
|
41
|
-
if not os.path.isfile(f"/netbox/templates/{template}"):
|
42
|
-
template = f"{device.device_type.manufacturer.name}.cfg.j2"
|
43
|
-
|
44
|
-
if not os.path.isfile(f"/netbox/templates/{template}"):
|
45
|
-
template = "default.cfg.j2"
|
46
|
-
|
47
|
-
vlans = utils.nb.ipam.vlans.filter(available_on_device=device.id)
|
48
|
-
interfaces = utils.nb.dcim.interfaces.filter(device=device)
|
49
|
-
|
50
|
-
interfaces_ethernet = []
|
51
|
-
interfaces_port_channels = []
|
52
|
-
interfaces_virtual = []
|
53
|
-
|
54
|
-
for interface in interfaces:
|
55
|
-
if str(interface.type) == "Link Aggregation Group (LAG)":
|
56
|
-
interfaces_port_channels.append(interface)
|
57
|
-
elif str(interface.type) == "Virtual":
|
58
|
-
interfaces_virtual.append(interface)
|
59
|
-
else:
|
60
|
-
interfaces_ethernet.append(interface)
|
61
|
-
|
62
|
-
# Port-Channel10 + Vlan4094 are always used as MLAG
|
63
|
-
try:
|
64
|
-
mlag = utils.nb.dcim.interfaces.get(device=device, name="Port-Channel10")
|
65
|
-
mlag_vlan = utils.nb.dcim.interfaces.get(device=device, name="Vlan4094")
|
66
|
-
mlag_address = utils.nb.ipam.ip_addresses.get(
|
67
|
-
device=device, interface="Vlan4094"
|
68
|
-
)
|
69
|
-
except: # noqa
|
70
|
-
mlag = None
|
71
|
-
mlag_vlan = None
|
72
|
-
mlag_address = None
|
73
|
-
|
74
|
-
# NOTE: only work with /30
|
75
|
-
try:
|
76
|
-
x = list(ipaddress.ip_interface(mlag_address.address).network.hosts())
|
77
|
-
x.remove(ipaddress.ip_interface(mlag_address.address).ip)
|
78
|
-
mlag_peer_address = x[0]
|
79
|
-
except: # noqa
|
80
|
-
mlag_peer_address = None
|
81
|
-
|
82
|
-
try:
|
83
|
-
mlag_domain_id = device.name.split("-")[1]
|
84
|
-
except: # noqa
|
85
|
-
mlag_domain_id = None
|
86
|
-
|
87
|
-
repo = git.Repo.init(path="/state")
|
88
|
-
repo.config_writer().set_value("user", "name", "Netbox Generator").release()
|
89
|
-
repo.config_writer().set_value(
|
90
|
-
"user", "email", "netbox-generator@reconciler.local"
|
91
|
-
).release()
|
92
|
-
|
93
|
-
data = {
|
94
|
-
"hostname": device.name,
|
95
|
-
"interfaces_ethernet": interfaces_ethernet,
|
96
|
-
"interfaces_virtual": interfaces_virtual,
|
97
|
-
"interfaces_port_channels": interfaces_port_channels,
|
98
|
-
"vlans": vlans,
|
99
|
-
"device": name,
|
100
|
-
"nb": utils.nb,
|
101
|
-
"first": first,
|
102
|
-
"vlans_as_string": vlans_as_string,
|
103
|
-
"mlag": mlag,
|
104
|
-
"mlag_vlan": mlag_vlan,
|
105
|
-
"mlag_peer_address": mlag_peer_address,
|
106
|
-
"mlag_domain_id": mlag_domain_id,
|
107
|
-
"timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
|
108
|
-
"device_type": device.device_type.model,
|
109
|
-
"device_manufacturer": device.device_type.manufacturer.name,
|
110
|
-
}
|
111
|
-
|
112
|
-
loader = jinja2.FileSystemLoader(searchpath="/netbox/templates/")
|
113
|
-
environment = jinja2.Environment(loader=loader)
|
114
|
-
template = environment.get_template(template)
|
115
|
-
result = template.render(data)
|
116
|
-
|
117
|
-
logger.info(f"Writing generated configuration to /state/{device.name}.cfg.j2")
|
118
|
-
with open(f"/state/{device.name}.cfg.j2", "w+") as fp:
|
119
|
-
fp.write(os.linesep.join([s for s in result.splitlines() if s]))
|
120
|
-
|
121
|
-
# Allow only one change per time
|
122
|
-
lock = Redlock(key="lock_repository", masters={utils.redis})
|
123
|
-
lock.acquire()
|
124
|
-
|
125
|
-
repo.git.add(f"/state/{device.name}.cfg.j2")
|
126
|
-
|
127
|
-
try:
|
128
|
-
if len(repo.index.diff("HEAD")) > 0:
|
129
|
-
logger.info(f"Committing changes in /state/{device.name}.cfg.j2")
|
130
|
-
repo.git.commit(message=f"Update {device.name}")
|
131
|
-
|
132
|
-
# Ref 'HEAD' did not resolve to an object
|
133
|
-
except gitdb.exc.BadName:
|
134
|
-
logger.info("Initial commit")
|
135
|
-
repo.git.commit(message="Initial commit")
|
136
|
-
|
137
|
-
lock.release()
|
@@ -1 +0,0 @@
|
|
1
|
-
Christian Berendt <berendt@osism.tech>
|
@@ -1 +0,0 @@
|
|
1
|
-
{"git_version": "6615081", "is_release": false}
|
File without changes
|
File without changes
|