osism 0.20250312.0__py3-none-any.whl → 0.20250326.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/commands/manage.py +117 -55
- osism/commands/netbox.py +45 -343
- osism/services/listener.py +0 -40
- osism/settings.py +0 -3
- osism/tasks/__init__.py +44 -14
- osism/tasks/ansible.py +0 -15
- osism/tasks/netbox.py +22 -98
- osism/tasks/openstack.py +64 -15
- osism/tasks/reconciler.py +0 -16
- {osism-0.20250312.0.dist-info → osism-0.20250326.0.dist-info}/METADATA +12 -11
- {osism-0.20250312.0.dist-info → osism-0.20250326.0.dist-info}/RECORD +18 -22
- {osism-0.20250312.0.dist-info → osism-0.20250326.0.dist-info}/WHEEL +1 -1
- {osism-0.20250312.0.dist-info → osism-0.20250326.0.dist-info}/entry_points.txt +1 -10
- osism-0.20250326.0.dist-info/licenses/AUTHORS +1 -0
- osism-0.20250326.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.20250312.0.dist-info/AUTHORS +0 -1
- osism-0.20250312.0.dist-info/pbr.json +0 -1
- {osism-0.20250312.0.dist-info → osism-0.20250326.0.dist-info/licenses}/LICENSE +0 -0
- {osism-0.20250312.0.dist-info → osism-0.20250326.0.dist-info}/top_level.txt +0 -0
osism/commands/netbox.py
CHANGED
@@ -1,40 +1,17 @@
|
|
1
1
|
# SPDX-License-Identifier: Apache-2.0
|
2
2
|
|
3
|
-
import argparse
|
4
|
-
from glob import glob
|
5
|
-
from os.path import basename
|
6
|
-
|
7
3
|
from cliff.command import Command
|
8
4
|
from loguru import logger
|
9
5
|
from redis import Redis
|
10
|
-
from tabulate import tabulate
|
11
6
|
|
12
7
|
from osism import settings
|
13
|
-
from osism.tasks import conductor, netbox, reconciler,
|
8
|
+
from osism.tasks import conductor, netbox, reconciler, openstack, handle_task
|
14
9
|
|
15
10
|
|
16
11
|
redis = Redis(host=settings.REDIS_HOST, port=settings.REDIS_PORT, db=settings.REDIS_DB)
|
17
12
|
redis.ping()
|
18
13
|
|
19
14
|
|
20
|
-
class Run(Command):
|
21
|
-
def get_parser(self, prog_name):
|
22
|
-
parser = super(Run, self).get_parser(prog_name)
|
23
|
-
parser.add_argument(
|
24
|
-
"arguments", nargs=argparse.REMAINDER, help="Other arguments for Ansible"
|
25
|
-
)
|
26
|
-
parser.add_argument(
|
27
|
-
"--no-wait",
|
28
|
-
default=False,
|
29
|
-
help="Do not wait until the role has been applied",
|
30
|
-
action="store_true",
|
31
|
-
)
|
32
|
-
return parser
|
33
|
-
|
34
|
-
def take_action(self, parsed_args):
|
35
|
-
pass
|
36
|
-
|
37
|
-
|
38
15
|
class Ironic(Command):
|
39
16
|
def get_parser(self, prog_name):
|
40
17
|
parser = super(Ironic, self).get_parser(prog_name)
|
@@ -77,368 +54,93 @@ class Sync(Command):
|
|
77
54
|
task.wait(timeout=None, interval=0.5)
|
78
55
|
|
79
56
|
|
80
|
-
class Init(Command):
|
81
|
-
def get_parser(self, prog_name):
|
82
|
-
parser = super(Init, self).get_parser(prog_name)
|
83
|
-
parser.add_argument(
|
84
|
-
"arguments", nargs=argparse.REMAINDER, help="Other arguments for Ansible"
|
85
|
-
)
|
86
|
-
parser.add_argument(
|
87
|
-
"--no-wait",
|
88
|
-
default=False,
|
89
|
-
help="Do not wait until the role has been applied",
|
90
|
-
action="store_true",
|
91
|
-
)
|
92
|
-
parser.add_argument(
|
93
|
-
"--format",
|
94
|
-
default="log",
|
95
|
-
help="Output type",
|
96
|
-
const="log",
|
97
|
-
nargs="?",
|
98
|
-
choices=["script", "log"],
|
99
|
-
),
|
100
|
-
return parser
|
101
|
-
|
102
|
-
def take_action(self, parsed_args):
|
103
|
-
arguments = parsed_args.arguments
|
104
|
-
format = parsed_args.format
|
105
|
-
wait = not parsed_args.no_wait
|
106
|
-
|
107
|
-
task = ansible.run.delay("netbox-local", "init", arguments)
|
108
|
-
rc = 0
|
109
|
-
|
110
|
-
if wait:
|
111
|
-
logger.info(f"Task {task.task_id} was prepared for execution.")
|
112
|
-
logger.info(
|
113
|
-
f"It takes a moment until task {task.task_id} has been started and output is visible here."
|
114
|
-
)
|
115
|
-
rc = handle_task(task, wait, format, 300)
|
116
|
-
else:
|
117
|
-
logger.info(
|
118
|
-
f"Task {task.task_id} is running in background. No more output. Check ARA for logs."
|
119
|
-
)
|
120
|
-
|
121
|
-
return rc
|
122
|
-
|
123
|
-
|
124
|
-
class Import(Command):
|
125
|
-
def get_parser(self, prog_name):
|
126
|
-
parser = super(Import, self).get_parser(prog_name)
|
127
|
-
parser.add_argument(
|
128
|
-
"--vendors",
|
129
|
-
help="Vendors from which all available device types are to be imported",
|
130
|
-
required=False,
|
131
|
-
)
|
132
|
-
parser.add_argument(
|
133
|
-
"--library",
|
134
|
-
default=False,
|
135
|
-
help="Do import device types from the device type library",
|
136
|
-
action="store_true",
|
137
|
-
)
|
138
|
-
parser.add_argument(
|
139
|
-
"--no-wait",
|
140
|
-
default=False,
|
141
|
-
help="Do not wait until the role has been applied",
|
142
|
-
action="store_true",
|
143
|
-
)
|
144
|
-
return parser
|
145
|
-
|
146
|
-
def take_action(self, parsed_args):
|
147
|
-
vendors = parsed_args.vendors
|
148
|
-
wait = not parsed_args.no_wait
|
149
|
-
|
150
|
-
task = netbox.import_device_types.delay(vendors, parsed_args.library)
|
151
|
-
|
152
|
-
if wait:
|
153
|
-
logger.info(f"Task {task.task_id} is running. Wait. No more output.")
|
154
|
-
task.wait(timeout=None, interval=0.5)
|
155
|
-
|
156
|
-
|
157
57
|
class Manage(Command):
|
158
58
|
def get_parser(self, prog_name):
|
159
59
|
parser = super(Manage, self).get_parser(prog_name)
|
160
|
-
parser.add_argument(
|
161
|
-
"--type",
|
162
|
-
type=str,
|
163
|
-
help="Type of the resource to manage",
|
164
|
-
required=False,
|
165
|
-
default="rack",
|
166
|
-
)
|
167
|
-
parser.add_argument(
|
168
|
-
"name", nargs="?", type=str, help="Name of the resource to manage"
|
169
|
-
)
|
170
|
-
parser.add_argument(
|
171
|
-
"arguments", nargs=argparse.REMAINDER, help="Other arguments for Ansible"
|
172
|
-
)
|
173
60
|
parser.add_argument(
|
174
61
|
"--no-wait",
|
175
62
|
default=False,
|
176
|
-
help="Do not wait until the
|
63
|
+
help="Do not wait until the management of the netbox has been completed",
|
177
64
|
action="store_true",
|
178
65
|
)
|
179
66
|
parser.add_argument(
|
180
|
-
"--
|
181
|
-
default="log",
|
182
|
-
help="Output type",
|
183
|
-
const="log",
|
184
|
-
nargs="?",
|
185
|
-
choices=["script", "log"],
|
186
|
-
),
|
187
|
-
return parser
|
188
|
-
|
189
|
-
def take_action(self, parsed_args):
|
190
|
-
arguments = parsed_args.arguments
|
191
|
-
format = parsed_args.format
|
192
|
-
name = parsed_args.name
|
193
|
-
type_of_resource = parsed_args.type
|
194
|
-
wait = not parsed_args.no_wait
|
195
|
-
|
196
|
-
rc = 0
|
197
|
-
if not name:
|
198
|
-
logger.info("No name of an object to be managed was given")
|
199
|
-
table = []
|
200
|
-
for playbook_type in ["rack"]:
|
201
|
-
playbooks = glob(
|
202
|
-
f"/opt/configuration/netbox/playbooks/{playbook_type}-*.yml"
|
203
|
-
)
|
204
|
-
for playbook in playbooks:
|
205
|
-
name = basename(playbook)[len(playbook_type) + 1 : -4] # noqa E203
|
206
|
-
table.append([playbook_type, name])
|
207
|
-
|
208
|
-
print(tabulate(table, headers=["Type", "Name"], tablefmt="psql"))
|
209
|
-
else:
|
210
|
-
task = ansible.run.delay(
|
211
|
-
"netbox-local", f"{type_of_resource}-{name}", arguments
|
212
|
-
)
|
213
|
-
|
214
|
-
if wait:
|
215
|
-
logger.info(f"Task {task.task_id} was prepared for execution.")
|
216
|
-
logger.info(
|
217
|
-
f"It takes a moment until task {task.task_id} has been started and output is visible here."
|
218
|
-
)
|
219
|
-
rc = handle_task(task, wait, format, 300)
|
220
|
-
else:
|
221
|
-
logger.info(
|
222
|
-
f"Task {task.task_id} is running in background. No more output. Check ARA for logs."
|
223
|
-
)
|
224
|
-
|
225
|
-
return rc
|
226
|
-
|
227
|
-
|
228
|
-
class Connect(Command):
|
229
|
-
def get_parser(self, prog_name):
|
230
|
-
parser = super(Connect, self).get_parser(prog_name)
|
231
|
-
parser.add_argument(
|
232
|
-
"name",
|
233
|
-
nargs="?",
|
234
|
-
type=str,
|
235
|
-
help="Name of the resource (a collection or a device) to connect",
|
236
|
-
)
|
237
|
-
parser.add_argument(
|
238
|
-
"--collection",
|
239
|
-
type=str,
|
240
|
-
help="Name of the collection to connect",
|
241
|
-
required=False,
|
242
|
-
),
|
243
|
-
parser.add_argument(
|
244
|
-
"--device", type=str, help="Name of the device to connect", required=False
|
245
|
-
)
|
246
|
-
parser.add_argument(
|
247
|
-
"--enforce",
|
67
|
+
"--no-netbox-wait",
|
248
68
|
default=False,
|
249
|
-
help="
|
69
|
+
help="Do not wait for the netbox API to be ready",
|
250
70
|
action="store_true",
|
251
71
|
)
|
252
72
|
parser.add_argument(
|
253
|
-
"--
|
254
|
-
)
|
255
|
-
parser.add_argument(
|
256
|
-
"--type",
|
73
|
+
"--parallel",
|
257
74
|
type=str,
|
258
|
-
default=
|
259
|
-
help="
|
260
|
-
required=False,
|
75
|
+
default=None,
|
76
|
+
help="Process up to n files in parallel",
|
261
77
|
)
|
262
|
-
return parser
|
263
|
-
|
264
|
-
def take_action(self, parsed_args):
|
265
|
-
name = parsed_args.name
|
266
|
-
collection = parsed_args.device
|
267
|
-
device = parsed_args.device
|
268
|
-
state = parsed_args.state
|
269
|
-
type_of_resource = parsed_args.type
|
270
|
-
enforce = parsed_args.enforce
|
271
|
-
|
272
|
-
task = None
|
273
|
-
|
274
|
-
if name:
|
275
|
-
if type_of_resource == "collection":
|
276
|
-
task = netbox.data.delay(name, "", state)
|
277
|
-
elif type_of_resource == "device":
|
278
|
-
task = netbox.data.delay("", name, state)
|
279
|
-
else:
|
280
|
-
task = netbox.data.delay(collection, device, state)
|
281
|
-
name = f"{collection}-{device}"
|
282
|
-
|
283
|
-
task.wait(timeout=None, interval=0.5)
|
284
|
-
data = task.get()
|
285
|
-
|
286
|
-
for device in data:
|
287
|
-
t = netbox.connect.delay(device, state, data, enforce)
|
288
|
-
logger.info(
|
289
|
-
f"Task {t.task_id} for device {device} is running in background"
|
290
|
-
)
|
291
|
-
logger.info(
|
292
|
-
"Tasks are running in background. No more output. Check Flower for logs."
|
293
|
-
)
|
294
|
-
|
295
|
-
|
296
|
-
class Disable(Command):
|
297
|
-
def get_parser(self, prog_name):
|
298
|
-
parser = super(Disable, self).get_parser(prog_name)
|
299
78
|
parser.add_argument(
|
300
|
-
"
|
301
|
-
nargs=1,
|
79
|
+
"--limit",
|
302
80
|
type=str,
|
303
|
-
|
81
|
+
default=None,
|
82
|
+
help="Limit files by prefix",
|
304
83
|
)
|
305
84
|
parser.add_argument(
|
306
|
-
"--
|
85
|
+
"--skipdtl",
|
307
86
|
default=False,
|
308
|
-
help="
|
87
|
+
help="Skip devicetype library",
|
309
88
|
action="store_true",
|
310
89
|
)
|
311
|
-
return parser
|
312
|
-
|
313
|
-
def take_action(self, parsed_args):
|
314
|
-
name = parsed_args.name[0]
|
315
|
-
wait = not parsed_args.no_wait
|
316
|
-
|
317
|
-
task = netbox.disable.delay(name)
|
318
|
-
|
319
|
-
if wait:
|
320
|
-
logger.info(f"Task {task.task_id} is running. Wait. No more output.")
|
321
|
-
task.wait(timeout=None, interval=0.5)
|
322
|
-
|
323
|
-
|
324
|
-
class Generate(Command):
|
325
|
-
def get_parser(self, prog_name):
|
326
|
-
parser = super(Generate, self).get_parser(prog_name)
|
327
|
-
parser.add_argument(
|
328
|
-
"name",
|
329
|
-
nargs=1,
|
330
|
-
type=str,
|
331
|
-
help="Name of the device for which the configuration is to be generated.",
|
332
|
-
)
|
333
90
|
parser.add_argument(
|
334
|
-
"--
|
91
|
+
"--skipmtl",
|
335
92
|
default=False,
|
336
|
-
help="
|
93
|
+
help="Skip moduletype library",
|
337
94
|
action="store_true",
|
338
95
|
)
|
339
96
|
parser.add_argument(
|
340
|
-
"--
|
341
|
-
)
|
342
|
-
return parser
|
343
|
-
|
344
|
-
def take_action(self, parsed_args):
|
345
|
-
name = parsed_args.name[0]
|
346
|
-
template = parsed_args.template
|
347
|
-
wait = not parsed_args.no_wait
|
348
|
-
|
349
|
-
task = netbox.generate.delay(name, template)
|
350
|
-
|
351
|
-
if wait:
|
352
|
-
logger.info(f"Task {task.task_id} is running. Wait. No more output.")
|
353
|
-
task.wait(timeout=None, interval=0.5)
|
354
|
-
|
355
|
-
|
356
|
-
class Deploy(Command):
|
357
|
-
def get_parser(self, prog_name):
|
358
|
-
parser = super(Deploy, self).get_parser(prog_name)
|
359
|
-
parser.add_argument(
|
360
|
-
"name",
|
361
|
-
nargs=1,
|
362
|
-
type=str,
|
363
|
-
help="Name of the device for which the configuration is to be deployed",
|
364
|
-
)
|
365
|
-
parser.add_argument(
|
366
|
-
"arguments", nargs=argparse.REMAINDER, help="Other arguments for Ansible"
|
367
|
-
)
|
368
|
-
parser.add_argument(
|
369
|
-
"--no-wait",
|
97
|
+
"--skipres",
|
370
98
|
default=False,
|
371
|
-
help="
|
99
|
+
help="Skip resources",
|
372
100
|
action="store_true",
|
373
101
|
)
|
374
102
|
return parser
|
375
103
|
|
376
104
|
def take_action(self, parsed_args):
|
377
|
-
name = parsed_args.name[0]
|
378
|
-
# arguments = parsed_args.arguments
|
379
105
|
wait = not parsed_args.no_wait
|
106
|
+
arguments = []
|
380
107
|
|
381
|
-
|
108
|
+
if parsed_args.no_netbox_wait:
|
109
|
+
arguments.append("--no-wait")
|
110
|
+
else:
|
111
|
+
arguments.append("--wait")
|
382
112
|
|
383
|
-
if
|
384
|
-
|
385
|
-
|
113
|
+
if parsed_args.parallel:
|
114
|
+
arguments.append("--parallel")
|
115
|
+
arguments.append(parsed_args.parallel)
|
386
116
|
|
117
|
+
if parsed_args.limit:
|
118
|
+
arguments.append("--limit")
|
119
|
+
arguments.append(parsed_args.limit)
|
387
120
|
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
"name",
|
393
|
-
nargs=1,
|
394
|
-
type=str,
|
395
|
-
help="Name of the device for which the configuration is to be checked",
|
396
|
-
)
|
397
|
-
parser.add_argument(
|
398
|
-
"--no-wait",
|
399
|
-
default=False,
|
400
|
-
help="Do not wait until the changes have been made",
|
401
|
-
action="store_true",
|
402
|
-
)
|
403
|
-
return parser
|
121
|
+
if parsed_args.skipdtl:
|
122
|
+
arguments.append("--skipdtl")
|
123
|
+
else:
|
124
|
+
arguments.append("--no-skipdtl")
|
404
125
|
|
405
|
-
|
406
|
-
|
407
|
-
|
126
|
+
if parsed_args.skipmtl:
|
127
|
+
arguments.append("--skipmtl")
|
128
|
+
else:
|
129
|
+
arguments.append("--no-skipmtl")
|
408
130
|
|
409
|
-
|
131
|
+
if parsed_args.skipres:
|
132
|
+
arguments.append("--skipres")
|
133
|
+
else:
|
134
|
+
arguments.append("--no-skipres")
|
410
135
|
|
136
|
+
task_signature = netbox.manage.si(*arguments)
|
137
|
+
task = task_signature.apply_async()
|
411
138
|
if wait:
|
412
|
-
logger.info(
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
class Diff(Command):
|
417
|
-
def get_parser(self, prog_name):
|
418
|
-
parser = super(Diff, self).get_parser(prog_name)
|
419
|
-
parser.add_argument(
|
420
|
-
"name",
|
421
|
-
nargs=1,
|
422
|
-
type=str,
|
423
|
-
help="Name of the device for which the configuration is to be diffed",
|
424
|
-
)
|
425
|
-
parser.add_argument(
|
426
|
-
"--no-wait",
|
427
|
-
default=False,
|
428
|
-
help="Do not wait until the changes have been made",
|
429
|
-
action="store_true",
|
430
|
-
)
|
431
|
-
return parser
|
432
|
-
|
433
|
-
def take_action(self, parsed_args):
|
434
|
-
name = parsed_args.name[0]
|
435
|
-
wait = not parsed_args.no_wait
|
436
|
-
|
437
|
-
task = netbox.diff.delay(name)
|
139
|
+
logger.info(
|
140
|
+
f"It takes a moment until task {task.task_id} (netbox-manager) has been started and output is visible here."
|
141
|
+
)
|
438
142
|
|
439
|
-
|
440
|
-
logger.info(f"Task {task.task_id} is running. Wait. No more output.")
|
441
|
-
task.wait(timeout=None, interval=0.5)
|
143
|
+
return handle_task(task, wait, format="script", timeout=3600)
|
442
144
|
|
443
145
|
|
444
146
|
class Ping(Command):
|
osism/services/listener.py
CHANGED
@@ -40,7 +40,6 @@ class BaremetalEvents:
|
|
40
40
|
},
|
41
41
|
"maintenance_set": {"end": self.node_maintenance_set_end},
|
42
42
|
"provision_set": {
|
43
|
-
"start": self.node_provision_set_start,
|
44
43
|
"end": self.node_provision_set_end,
|
45
44
|
"success": self.node_provision_set_success,
|
46
45
|
},
|
@@ -97,28 +96,6 @@ class BaremetalEvents:
|
|
97
96
|
)
|
98
97
|
netbox.set_maintenance.delay(name, object_data["maintenance"])
|
99
98
|
|
100
|
-
def node_provision_set_start(self, payload: dict[Any, Any]) -> None:
|
101
|
-
object_data = self.get_object_data(payload)
|
102
|
-
name = object_data["name"]
|
103
|
-
logger.info(
|
104
|
-
f"baremetal.node.provision_set.start ## {name} ## {object_data['provision_state']}"
|
105
|
-
)
|
106
|
-
|
107
|
-
if object_data["event"] == "inspect":
|
108
|
-
# system should be in state a
|
109
|
-
netbox.connect.delay(name, "a")
|
110
|
-
|
111
|
-
if object_data["provision_state"] == "cleaning":
|
112
|
-
# system should be in state b
|
113
|
-
netbox.connect.delay(name, "b")
|
114
|
-
|
115
|
-
if object_data["provision_state"] == "available":
|
116
|
-
# system should be in state c
|
117
|
-
netbox.connect.delay(name, "c")
|
118
|
-
|
119
|
-
if object_data["target_provision_state"] == "active":
|
120
|
-
pass
|
121
|
-
|
122
99
|
def node_provision_set_success(self, payload: dict[Any, Any]) -> None:
|
123
100
|
# A provision status was successfully set, update it in the netbox
|
124
101
|
object_data = self.get_object_data(payload)
|
@@ -128,10 +105,6 @@ class BaremetalEvents:
|
|
128
105
|
)
|
129
106
|
netbox.set_state.delay(name, object_data["provision_state"], "provision")
|
130
107
|
|
131
|
-
if object_data["provision_state"] == "manageable":
|
132
|
-
# system should be in state c
|
133
|
-
netbox.connect.delay(name, "c")
|
134
|
-
|
135
108
|
def node_provision_set_end(self, payload: dict[Any, Any]) -> None:
|
136
109
|
object_data = self.get_object_data(payload)
|
137
110
|
name = object_data["name"]
|
@@ -147,16 +120,6 @@ class BaremetalEvents:
|
|
147
120
|
netbox.set_state.delay(name, "introspected", "introspection")
|
148
121
|
openstack.baremetal_set_node_provision_state.delay(name, "provide")
|
149
122
|
|
150
|
-
elif object_data["previous_provision_state"] == "wait call-back":
|
151
|
-
pass
|
152
|
-
|
153
|
-
elif (
|
154
|
-
object_data["previous_provision_state"] == "cleaning"
|
155
|
-
and object_data["provision_state"] == "available"
|
156
|
-
): # noqa
|
157
|
-
# system should be in state c
|
158
|
-
netbox.connect.delay(name, "c")
|
159
|
-
|
160
123
|
def port_create_end(self, payload: dict[Any, Any]) -> None:
|
161
124
|
object_data = self.get_object_data(payload)
|
162
125
|
name = object_data["name"]
|
@@ -206,9 +169,6 @@ class BaremetalEvents:
|
|
206
169
|
netbox.set_state.delay(name, None, "introspection")
|
207
170
|
netbox.set_state.delay(name, None, "deployment")
|
208
171
|
|
209
|
-
# system should be in state a
|
210
|
-
netbox.connect.delay(name, "a")
|
211
|
-
|
212
172
|
# remove internal flavor
|
213
173
|
openstack.baremetal_delete_internal_flavor.delay(name)
|
214
174
|
|
osism/settings.py
CHANGED
@@ -27,9 +27,6 @@ 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(
|
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/ansible.py
CHANGED
@@ -1,25 +1,10 @@
|
|
1
1
|
# SPDX-License-Identifier: Apache-2.0
|
2
2
|
|
3
|
-
import functools
|
4
|
-
from threading import RLock
|
5
|
-
|
6
3
|
from celery import Celery
|
7
|
-
import kombu.utils
|
8
4
|
|
9
5
|
from osism import settings
|
10
6
|
from osism.tasks import Config, run_ansible_in_environment
|
11
7
|
|
12
|
-
# https://github.com/celery/kombu/issues/1804
|
13
|
-
if not getattr(kombu.utils.cached_property, "lock", None):
|
14
|
-
setattr(
|
15
|
-
kombu.utils.cached_property,
|
16
|
-
"lock",
|
17
|
-
functools.cached_property(lambda _: RLock()),
|
18
|
-
)
|
19
|
-
# Must call __set_name__ here since this cached property is not defined in the context of a class
|
20
|
-
# Refer to https://docs.python.org/3/reference/datamodel.html#object.__set_name__
|
21
|
-
kombu.utils.cached_property.lock.__set_name__(kombu.utils.cached_property, "lock")
|
22
|
-
|
23
8
|
app = Celery("ansible")
|
24
9
|
app.config_from_object(Config)
|
25
10
|
|