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.
@@ -2,14 +2,18 @@
2
2
 
3
3
  import os
4
4
  import time
5
+ from collections.abc import Callable
6
+ from typing import Any
5
7
 
6
8
  from kombu import Connection, Exchange, Queue
7
9
  from kombu.mixins import ConsumerMixin
8
10
  from loguru import logger
9
11
  import json
12
+ import requests
10
13
 
11
14
  from osism import utils
12
15
  from osism.tasks import netbox, openstack
16
+ from osism import settings
13
17
 
14
18
  EXCHANGE_NAME = "ironic"
15
19
  ROUTING_KEY = "ironic_versioned_notifications.info"
@@ -17,168 +21,254 @@ QUEUE_NAME = "osism-listener-ironic"
17
21
  BROKER_URI = os.getenv("BROKER_URI")
18
22
 
19
23
 
20
- class NotificationsDump(ConsumerMixin):
21
- def __init__(self, connection):
22
- self.connection = connection
23
- return
24
-
25
- def get_consumers(self, consumer, channel):
26
- exchange = Exchange(EXCHANGE_NAME, type="topic", durable=False)
27
- queue = Queue(
28
- QUEUE_NAME,
29
- exchange,
30
- routing_key=ROUTING_KEY,
31
- durable=False,
32
- auto_delete=True,
33
- no_ack=True,
34
- )
35
- return [consumer(queue, callbacks=[self.on_message])]
24
+ class BaremetalEvents:
25
+ # References:
26
+ #
27
+ # * https://docs.openstack.org/ironic/latest/admin/notifications.html#available-notifications
28
+ # * https://docs.openstack.org/ironic/latest/user/states.html
29
+ # * https://docs.openstack.org/ironic/latest/_images/states.svg
30
+
31
+ def __init__(self) -> None:
32
+ self._handler: dict[
33
+ str, dict[str, dict[str, dict[str, Callable[[dict[Any, Any]], None]]]]
34
+ ] = {
35
+ "baremetal": {
36
+ "node": {
37
+ "power_set": {"end": self.node_power_set_end},
38
+ "power_state_corrected": {
39
+ "success": self.node_power_state_corrected_success
40
+ },
41
+ "maintenance_set": {"end": self.node_maintenance_set_end},
42
+ "provision_set": {
43
+ "end": self.node_provision_set_end,
44
+ "success": self.node_provision_set_success,
45
+ },
46
+ "delete": {"end": self.node_delete_end},
47
+ "create": {"end": self.node_create_end},
48
+ },
49
+ "port": {
50
+ "create": {"end": self.port_create_end},
51
+ "update": {"end": self.port_update_end},
52
+ },
53
+ }
54
+ }
55
+
56
+ def get_object_data(self, payload: dict[Any, Any]) -> Any:
57
+ return payload["ironic_object.data"]
58
+
59
+ def get_handler(self, event_type: str) -> Callable[[dict[Any, Any]], None]:
60
+ event_type_keys = event_type.split(".")
61
+ try:
62
+ handler = self._handler[event_type_keys[0]][event_type_keys[1]][
63
+ event_type_keys[2]
64
+ ][event_type_keys[3]]
65
+ except KeyError:
36
66
 
37
- def on_message(self, body, message):
38
- data = json.loads(body["oslo.message"])
39
- # logger.info(data)
67
+ def default_handler(payload: dict[Any, Any]) -> None:
68
+ object_data = self.get_object_data(payload)
69
+ name = object_data["name"]
70
+ logger.info(event_type + f" ## {name}")
40
71
 
41
- event_type = data["event_type"]
42
- payload = data["payload"]
43
- object_data = payload["ironic_object.data"]
72
+ handler = default_handler
73
+ return handler
44
74
 
75
+ def node_power_set_end(self, payload: dict[Any, Any]) -> None:
76
+ object_data = self.get_object_data(payload)
45
77
  name = object_data["name"]
78
+ logger.info(
79
+ f"baremetal.node.power_set.end ## {name} ## {object_data['power_state']}"
80
+ )
81
+ netbox.set_state.delay(name, object_data["power_state"], "power")
46
82
 
47
- # References:
48
- #
49
- # * https://docs.openstack.org/ironic/latest/admin/notifications.html#available-notifications
50
- # * https://docs.openstack.org/ironic/latest/user/states.html
51
- # * https://docs.openstack.org/ironic/latest/_images/states.svg
83
+ def node_power_state_corrected_success(self, payload: dict[Any, Any]) -> None:
84
+ object_data = self.get_object_data(payload)
85
+ name = object_data["name"]
86
+ logger.info(
87
+ f"baremetal.node.power_state_corrected.success ## {name} ## {object_data['power_state']}"
88
+ )
89
+ netbox.set_state.delay(name, object_data["power_state"], "power")
52
90
 
53
- if event_type == "baremetal.node.power_set.end":
54
- logger.info(
55
- f"baremetal.node.power_set.end ## {name} ## {object_data['power_state']}"
56
- )
57
- netbox.set_state.delay(name, object_data["power_state"], "power")
91
+ def node_maintenance_set_end(self, payload: dict[Any, Any]) -> None:
92
+ object_data = self.get_object_data(payload)
93
+ name = object_data["name"]
94
+ logger.info(
95
+ f"baremetal.node.maintenance_set.end ## {name} ## {object_data['maintenance']}"
96
+ )
97
+ netbox.set_maintenance.delay(name, object_data["maintenance"])
58
98
 
59
- elif event_type == "baremetal.node.power_state_corrected.success":
60
- logger.info(
61
- f"baremetal.node.power_state_corrected.success ## {name} ## {object_data['power_state']}"
62
- )
63
- netbox.set_state.delay(name, object_data["power_state"], "power")
99
+ def node_provision_set_success(self, payload: dict[Any, Any]) -> None:
100
+ # A provision status was successfully set, update it in the netbox
101
+ object_data = self.get_object_data(payload)
102
+ name = object_data["name"]
103
+ logger.info(
104
+ f"baremetal.node.provision_set.success ## {name} ## {object_data['provision_state']}"
105
+ )
106
+ netbox.set_state.delay(name, object_data["provision_state"], "provision")
64
107
 
65
- elif event_type == "baremetal.node.maintenance_set.end":
66
- logger.info(
67
- f"baremetal.node.maintenance_set.end ## {name} ## {object_data['maintenance']}"
68
- )
69
- netbox.set_maintenance.delay(name, object_data["maintenance"])
108
+ def node_provision_set_end(self, payload: dict[Any, Any]) -> None:
109
+ object_data = self.get_object_data(payload)
110
+ name = object_data["name"]
111
+ logger.info(
112
+ f"baremetal.node.provision_set.end ## {name} ## {object_data['provision_state']}"
113
+ )
114
+ netbox.set_state.delay(name, object_data["provision_state"], "provision")
70
115
 
71
- elif event_type == "baremetal.node.provision_set.start":
72
- logger.info(
73
- f"baremetal.node.provision_set.start ## {name} ## {object_data['provision_state']}"
74
- )
116
+ if (
117
+ object_data["previous_provision_state"] == "inspect wait"
118
+ and object_data["event"] == "done"
119
+ ):
120
+ netbox.set_state.delay(name, "introspected", "introspection")
121
+ openstack.baremetal_set_node_provision_state.delay(name, "provide")
75
122
 
76
- if object_data["event"] == "inspect":
77
- # system should be in state a
78
- netbox.connect.delay(name, "a")
123
+ def port_create_end(self, payload: dict[Any, Any]) -> None:
124
+ object_data = self.get_object_data(payload)
125
+ name = object_data["name"]
126
+ logger.info(f"baremetal.port.create.end ## {object_data['uuid']}")
79
127
 
80
- if object_data["provision_state"] == "cleaning":
81
- # system should be in state b
82
- netbox.connect.delay(name, "b")
128
+ mac_address = object_data["address"]
129
+ interface_a = utils.nb.dcim.interfaces.get(mac_address=mac_address)
130
+ device_a = interface_a.device
83
131
 
84
- if object_data["provision_state"] == "available":
85
- # system should be in state c
86
- netbox.connect.delay(name, "c")
132
+ task = openstack.baremetal_get_network_interface_name.delay(
133
+ device_a.name, mac_address
134
+ )
135
+ task.wait(timeout=None, interval=0.5)
136
+ network_interface_name = task.get()
87
137
 
88
- if object_data["target_provision_state"] == "active":
89
- pass
138
+ netbox.update_network_interface_name.delay(
139
+ object_data["address"], network_interface_name
140
+ )
90
141
 
91
- # A provision status was successfully set, update it in the netbox
92
- elif event_type == "baremetal.node.provision_set.success":
93
- logger.info(
94
- f"baremetal.node.provision_set.success ## {name} ## {object_data['provision_state']}"
95
- )
96
- netbox.set_state.delay(name, object_data["provision_state"], "provision")
142
+ def port_update_end(self, payload: dict[Any, Any]) -> None:
143
+ object_data = self.get_object_data(payload)
144
+ name = object_data["name"]
145
+ logger.info(f"baremetal.port.update.end ## {object_data['uuid']}")
97
146
 
98
- if object_data["provision_state"] == "manageable":
99
- # system should be in state c
100
- netbox.connect.delay(name, "c")
147
+ mac_address = object_data["address"]
148
+ interface_a = utils.nb.dcim.interfaces.get(mac_address=mac_address)
149
+ device_a = interface_a.device
101
150
 
102
- elif event_type == "baremetal.node.provision_set.end":
103
- logger.info(
104
- f"baremetal.node.provision_set.end ## {name} ## {object_data['provision_state']}"
105
- )
106
- netbox.set_state.delay(name, object_data["provision_state"], "provision")
107
-
108
- if (
109
- object_data["previous_provision_state"] == "inspect wait"
110
- and object_data["event"] == "done"
111
- ):
112
- netbox.set_state.delay(name, "introspected", "introspection")
113
- openstack.baremetal_set_node_provision_state.delay(name, "provide")
114
-
115
- elif object_data["previous_provision_state"] == "wait call-back":
116
- pass
117
-
118
- elif (
119
- object_data["previous_provision_state"] == "cleaning"
120
- and object_data["provision_state"] == "available"
121
- ): # noqa
122
- # system should be in state c
123
- netbox.connect.delay(name, "c")
124
-
125
- elif event_type == "baremetal.port.create.end":
126
- logger.info(f"baremetal.port.create.end ## {object_data['uuid']}")
127
-
128
- mac_address = object_data["address"]
129
- interface_a = utils.nb.dcim.interfaces.get(mac_address=mac_address)
130
- device_a = interface_a.device
131
-
132
- task = openstack.baremetal_get_network_interface_name.delay(
133
- device_a.name, mac_address
134
- )
135
- task.wait(timeout=None, interval=0.5)
136
- network_interface_name = task.get()
151
+ task = openstack.baremetal_get_network_interface_name.delay(
152
+ device_a.name, mac_address
153
+ )
154
+ task.wait(timeout=None, interval=0.5)
155
+ network_interface_name = task.get()
137
156
 
138
- netbox.update_network_interface_name.delay(
139
- object_data["address"], network_interface_name
140
- )
157
+ netbox.update_network_interface_name.delay(
158
+ object_data["address"], network_interface_name
159
+ )
141
160
 
142
- elif event_type == "baremetal.port.update.end":
143
- logger.info(f"baremetal.port.update.end ## {object_data['uuid']}")
161
+ def node_delete_end(self, payload: dict[Any, Any]) -> None:
162
+ object_data = self.get_object_data(payload)
163
+ name = object_data["name"]
164
+ logger.info(f"baremetal.node.delete.end ## {name}")
144
165
 
145
- mac_address = object_data["address"]
146
- interface_a = utils.nb.dcim.interfaces.get(mac_address=mac_address)
147
- device_a = interface_a.device
166
+ netbox.set_state.delay(name, "unregistered", "ironic")
167
+ netbox.set_state.delay(name, None, "provision")
168
+ netbox.set_state.delay(name, None, "power")
169
+ netbox.set_state.delay(name, None, "introspection")
170
+ netbox.set_state.delay(name, None, "deployment")
148
171
 
149
- task = openstack.baremetal_get_network_interface_name.delay(
150
- device_a.name, mac_address
151
- )
152
- task.wait(timeout=None, interval=0.5)
153
- network_interface_name = task.get()
172
+ # remove internal flavor
173
+ openstack.baremetal_delete_internal_flavor.delay(name)
154
174
 
155
- netbox.update_network_interface_name.delay(
156
- object_data["address"], network_interface_name
157
- )
175
+ def node_create_end(self, payload: dict[Any, Any]) -> None:
176
+ object_data = self.get_object_data(payload)
177
+ name = object_data["name"]
178
+ logger.info(f"baremetal.node.create.end ## {name}")
179
+ netbox.set_state.delay(name, "registered", "ironic")
158
180
 
159
- elif event_type == "baremetal.node.delete.end":
160
- logger.info(f"baremetal.node.delete.end ## {name}")
161
181
 
162
- netbox.set_state.delay(name, "unregistered", "ironic")
163
- netbox.set_state.delay(name, None, "provision")
164
- netbox.set_state.delay(name, None, "power")
165
- netbox.set_state.delay(name, None, "introspection")
166
- netbox.set_state.delay(name, None, "deployment")
182
+ class NotificationsDump(ConsumerMixin):
183
+ def __init__(self, connection):
184
+ self.connection = connection
185
+ self.baremetal_events = BaremetalEvents()
186
+ self.osism_api_session: None | requests.Session = None
187
+ self.osism_baremetal_api_url: None | str = None
188
+ if settings.OSISM_API_URL:
189
+ logger.info("Setting up OSISM API")
190
+ self.osism_api_session = requests.Session()
191
+ self.osism_baremetal_api_url = (
192
+ settings.OSISM_API_URL.rstrip("/") + "/notifications/baremetal"
193
+ )
194
+ return
167
195
 
168
- # system should be in state a
169
- netbox.connect.delay(name, "a")
196
+ def get_consumers(self, consumer, channel):
197
+ exchange = Exchange(EXCHANGE_NAME, type="topic", durable=False)
198
+ queue = Queue(
199
+ QUEUE_NAME,
200
+ exchange,
201
+ routing_key=ROUTING_KEY,
202
+ durable=False,
203
+ auto_delete=True,
204
+ no_ack=True,
205
+ )
206
+ return [consumer(queue, callbacks=[self.on_message])]
170
207
 
171
- # remove internal flavor
172
- openstack.baremetal_delete_internal_flavor.delay(name)
208
+ def on_message(self, body, message):
209
+ data = json.loads(body["oslo.message"])
210
+ # logger.info(data)
173
211
 
174
- elif event_type == "baremetal.node.create.end":
175
- logger.info(f"baremetal.node.create.end ## {name}")
176
- netbox.set_state.delay(name, "registered", "ironic")
212
+ if self.osism_api_session:
213
+ tries = 1
214
+ max_tries = 3
215
+ while tries <= max_tries:
216
+ logger.info(
217
+ f"Trying to deliver notification to {self.osism_baremetal_api_url} (Try: {tries}/{max_tries})\n"
218
+ )
219
+ try:
220
+ response = self.osism_api_session.post(
221
+ self.osism_baremetal_api_url,
222
+ timeout=5,
223
+ json=dict(
224
+ priority=data["priority"],
225
+ event_type=data["event_type"],
226
+ timestamp=data["timestamp"],
227
+ publisher_id=data["publisher_id"],
228
+ message_id=data["message_id"],
229
+ payload=data["payload"],
230
+ ),
231
+ )
232
+ if response.status_code == 204:
233
+ logger.info(
234
+ f"Successfully delivered notification to {self.osism_baremetal_api_url} (Try: {tries}/{max_tries})"
235
+ )
236
+ break
237
+ else:
238
+ response.raise_for_status()
239
+ except requests.ConnectionError:
240
+ logger.error(f"Error connecting to {self.osism_baremetal_api_url}")
241
+ except requests.Timeout:
242
+ logger.error(
243
+ f"Timeout reached while connecting to {self.osism_baremetal_api_url}"
244
+ )
245
+ except requests.HTTPError as e:
246
+ logger.error(
247
+ f"Received HTTP status code {e.response.status_code} while connecting to {self.osism_baremetal_api_url}"
248
+ )
249
+ if e.response.status_code <= 500:
250
+ logger.error(
251
+ f"Received HTTP status code {e.response.status_code} indicates a client side error, giving up early"
252
+ )
253
+ break
254
+
255
+ logger.error(
256
+ f"Failed to deliver notification to {self.osism_baremetal_api_url} ({tries}/{max_tries})"
257
+ )
258
+ tries += 1
259
+ if tries > max_tries:
260
+ logger.error(
261
+ f"Giving up delivering notification to {self.osism_baremetal_api_url} with data:\n"
262
+ + json.dumps(data)
263
+ )
264
+ else:
265
+ time.sleep(pow(3, tries - 1))
177
266
 
178
267
  else:
179
- logger.info(f"{event_type} ## {name}")
268
+ handler = self.baremetal_events.get_handler(data["event_type"])
269
+ handler(data["payload"])
180
270
 
181
- logger.info(object_data)
271
+ logger.info(self.baremetal_events.get_object_data(data["payload"]))
182
272
 
183
273
 
184
274
  def main():
osism/settings.py CHANGED
@@ -27,11 +27,10 @@ NETBOX_URL = os.getenv("NETBOX_API")
27
27
  NETBOX_TOKEN = os.getenv("NETBOX_TOKEN", read_secret("NETBOX_TOKEN"))
28
28
  IGNORE_SSL_ERRORS = os.getenv("IGNORE_SSL_ERRORS", "True") == "True"
29
29
 
30
- BASE_PATH = os.getenv("BASE_PATH", "/devicetype-library/device-types/")
31
- VENDORS = os.getenv("VENDORS", "").split()
32
-
33
30
  # 43200 seconds = 12 hours
34
31
  GATHER_FACTS_SCHEDULE = float(os.getenv("GATHER_FACTS_SCHEDULE", "43200.0"))
35
32
  INVENTORY_RECONCILER_SCHEDULE = float(
36
33
  os.getenv("INVENTORY_RECONCILER_SCHEDULE", "600.0")
37
34
  )
35
+
36
+ OSISM_API_URL = os.getenv("OSISM_API_URL", None)
osism/tasks/__init__.py CHANGED
@@ -160,20 +160,6 @@ def run_ansible_in_environment(
160
160
  env=env,
161
161
  )
162
162
 
163
- # execute local netbox playbooks
164
- elif worker == "osism-ansible" and environment == "netbox-local":
165
- if locking:
166
- lock.acquire()
167
-
168
- command = f"/run-{environment}.sh {role} {joined_arguments}"
169
- logger.info(f"RUN {command}")
170
- p = subprocess.Popen(
171
- command,
172
- stdout=subprocess.PIPE,
173
- stderr=subprocess.STDOUT,
174
- shell=True,
175
- )
176
-
177
163
  # execute all other roles
178
164
  else:
179
165
  if locking:
@@ -207,6 +193,50 @@ def run_ansible_in_environment(
207
193
  return result
208
194
 
209
195
 
196
+ def run_command(
197
+ request_id,
198
+ command,
199
+ env,
200
+ *arguments,
201
+ publish=True,
202
+ locking=False,
203
+ auto_release_time=3600,
204
+ ):
205
+ result = ""
206
+ command_env = os.environ.copy()
207
+ command_env.update(env)
208
+
209
+ if locking:
210
+ lock = Redlock(
211
+ key=f"lock-{command}",
212
+ masters={redis},
213
+ auto_release_time=auto_release_time,
214
+ )
215
+
216
+ p = subprocess.Popen(
217
+ [command] + list(arguments),
218
+ env=command_env,
219
+ stdout=subprocess.PIPE,
220
+ stderr=subprocess.STDOUT,
221
+ )
222
+ while p.poll() is None:
223
+ line = p.stdout.readline().decode("utf-8")
224
+ if publish:
225
+ redis.xadd(request_id, {"type": "stdout", "content": line})
226
+ result += line
227
+
228
+ rc = p.wait(timeout=60)
229
+
230
+ if publish:
231
+ redis.xadd(request_id, {"type": "rc", "content": rc})
232
+ redis.xadd(request_id, {"type": "action", "content": "quit"})
233
+
234
+ if locking:
235
+ lock.release()
236
+
237
+ return result
238
+
239
+
210
240
  def handle_task(t, wait=True, format="log", timeout=3600):
211
241
  global redis
212
242
 
osism/tasks/netbox.py CHANGED
@@ -1,8 +1,5 @@
1
1
  # SPDX-License-Identifier: Apache-2.0
2
2
 
3
- import os
4
- import subprocess
5
-
6
3
  from celery import Celery
7
4
  from celery.signals import worker_process_init
8
5
  import json
@@ -10,15 +7,8 @@ import pynetbox
10
7
  from redis import Redis
11
8
 
12
9
  from osism import settings
13
- from osism.actions import (
14
- check_configuration,
15
- deploy_configuration,
16
- diff_configuration,
17
- generate_configuration,
18
- manage_device,
19
- manage_interface,
20
- )
21
- from osism.tasks import Config, openstack
10
+ from osism.actions import manage_device, manage_interface
11
+ from osism.tasks import Config, openstack, run_command
22
12
 
23
13
  app = Celery("netbox")
24
14
  app.config_from_object(Config)
@@ -73,35 +63,6 @@ def update_network_interface_name(self, mac_address, network_interface_name):
73
63
  manage_interface.update_network_interface_name(mac_address, network_interface_name)
74
64
 
75
65
 
76
- @app.task(bind=True, name="osism.tasks.netbox.import_device_types")
77
- def import_device_types(self, vendors, library=False):
78
- global redis
79
-
80
- if library:
81
- env = {**os.environ, "BASE_PATH": "/devicetype-library/device-types/"}
82
- else:
83
- env = {**os.environ, "BASE_PATH": "/netbox/device-types/"}
84
-
85
- if vendors:
86
- p = subprocess.Popen(
87
- f"python3 /import/main.py --vendors {vendors}",
88
- shell=True,
89
- stdout=subprocess.PIPE,
90
- stderr=subprocess.STDOUT,
91
- env=env,
92
- )
93
- else:
94
- p = subprocess.Popen(
95
- "python3 /import/main.py",
96
- shell=True,
97
- stdout=subprocess.PIPE,
98
- stderr=subprocess.STDOUT,
99
- env=env,
100
- )
101
-
102
- p.communicate()
103
-
104
-
105
66
  @app.task(bind=True, name="osism.tasks.netbox.synchronize_device_state")
106
67
  def synchronize_device_state(self, data):
107
68
  """Synchronize the state of Ironic with Netbox"""
@@ -123,23 +84,6 @@ def states(self, data):
123
84
  return result
124
85
 
125
86
 
126
- @app.task(bind=True, name="osism.tasks.netbox.transitions")
127
- def transitions(self, data):
128
- result = manage_device.get_transitions(data.keys())
129
- return result
130
-
131
-
132
- @app.task(bind=True, name="osism.tasks.netbox.data")
133
- def data(self, collection, device, state):
134
- result = manage_device.load_data_from_filesystem(collection, device, state)
135
- return result
136
-
137
-
138
- @app.task(bind=True, name="osism.tasks.netbox.connect")
139
- def connect(self, device=None, state=None, data={}, enforce=False):
140
- manage_device.run(device, state, data, enforce)
141
-
142
-
143
87
  @app.task(bind=True, name="osism.tasks.netbox.set_state")
144
88
  def set_state(self, device=None, state=None, state_type=None):
145
89
  manage_device.set_state(device, state, state_type)
@@ -150,47 +94,7 @@ def set_maintenance(self, device=None, state=None):
150
94
  manage_device.set_maintenance(device, state)
151
95
 
152
96
 
153
- @app.task(bind=True, name="osism.tasks.netbox.disable")
154
- def disable(self, name):
155
- global nb
156
-
157
- for interface in nb.dcim.interfaces.filter(device=name):
158
- if str(interface.type) in ["Virtual"]:
159
- continue
160
-
161
- if "Port-Channel" in interface.name:
162
- continue
163
-
164
- if not interface.connected_endpoint and interface.enabled:
165
- interface.enabled = False
166
- interface.save()
167
-
168
- # FIXME: only enable devices that are not disabled by configuration
169
- if interface.connected_endpoint and not interface.enabled:
170
- interface.enabled = True
171
- interface.save()
172
-
173
-
174
- @app.task(bind=True, name="osism.tasks.netbox.generate")
175
- def generate(self, name, template=None):
176
- generate_configuration.for_device(name, template)
177
-
178
-
179
- @app.task(bind=True, name="osism.tasks.netbox.deploy")
180
- def deploy(self, name):
181
- deploy_configuration.for_device(name)
182
-
183
-
184
- @app.task(bind=True, name="osism.tasks.netbox.check")
185
- def check(self, name):
186
- check_configuration.for_device(name)
187
-
188
-
189
97
  @app.task(bind=True, name="osism.tasks.netbox.diff")
190
- def diff(self, name):
191
- diff_configuration.for_device(name)
192
-
193
-
194
98
  @app.task(bind=True, name="osism.tasks.netbox.get_devices_not_yet_registered_in_ironic")
195
99
  def get_devices_not_yet_registered_in_ironic(
196
100
  self, status="active", tags=["managed-by-ironic"], ironic_enabled=True
@@ -238,6 +142,26 @@ def get_devices_that_should_have_an_allocation_in_ironic(self):
238
142
  return result
239
143
 
240
144
 
145
+ @app.task(bind=True, name="osism.tasks.netbox.manage")
146
+ def manage(self, *arguments, publish=True, locking=False, auto_release_time=3600):
147
+ netbox_manager_env = {
148
+ "NETBOX_MANAGER_URL": str(settings.NETBOX_URL),
149
+ "NETBOX_MANAGER_TOKEN": str(settings.NETBOX_TOKEN),
150
+ "NETBOX_MANAGER_IGNORE_SSL_ERRORS": str(settings.IGNORE_SSL_ERRORS),
151
+ "NETBOX_MANAGER_VERBOSE": "true",
152
+ }
153
+
154
+ return run_command(
155
+ self.request.id,
156
+ "/usr/local/bin/netbox-manager",
157
+ netbox_manager_env,
158
+ *arguments,
159
+ publish=publish,
160
+ locking=locking,
161
+ auto_release_time=auto_release_time
162
+ )
163
+
164
+
241
165
  @app.task(bind=True, name="osism.tasks.netbox.ping")
242
166
  def ping(self):
243
167
  global nb
@@ -0,0 +1 @@
1
+ janhorstmann <horstmann@osism.tech>