osism 0.20250824.1__py3-none-any.whl → 0.20250827.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/commands/apply.py +4 -0
- osism/commands/configuration.py +4 -0
- osism/commands/lock.py +91 -0
- osism/commands/manage.py +132 -6
- osism/commands/netbox.py +12 -0
- osism/commands/noset.py +7 -0
- osism/commands/reconciler.py +3 -0
- osism/commands/redfish.py +4 -0
- osism/commands/service.py +4 -0
- osism/commands/set.py +7 -0
- osism/commands/sonic.py +3 -0
- osism/commands/sync.py +7 -0
- osism/commands/validate.py +3 -0
- osism/commands/worker.py +4 -0
- osism/data/__init__.py +33 -0
- osism/tasks/ansible.py +3 -0
- osism/tasks/ceph.py +4 -0
- osism/tasks/conductor/__init__.py +10 -0
- osism/tasks/kolla.py +4 -0
- osism/tasks/kubernetes.py +4 -0
- osism/tasks/netbox.py +12 -0
- osism/tasks/openstack.py +265 -38
- osism/tasks/reconciler.py +3 -0
- osism/utils/__init__.py +81 -0
- {osism-0.20250824.1.dist-info → osism-0.20250827.0.dist-info}/METADATA +5 -5
- {osism-0.20250824.1.dist-info → osism-0.20250827.0.dist-info}/RECORD +32 -31
- {osism-0.20250824.1.dist-info → osism-0.20250827.0.dist-info}/entry_points.txt +4 -0
- osism-0.20250827.0.dist-info/licenses/AUTHORS +1 -0
- osism-0.20250827.0.dist-info/pbr.json +1 -0
- osism-0.20250824.1.dist-info/licenses/AUTHORS +0 -1
- osism-0.20250824.1.dist-info/pbr.json +0 -1
- {osism-0.20250824.1.dist-info → osism-0.20250827.0.dist-info}/WHEEL +0 -0
- {osism-0.20250824.1.dist-info → osism-0.20250827.0.dist-info}/licenses/LICENSE +0 -0
- {osism-0.20250824.1.dist-info → osism-0.20250827.0.dist-info}/top_level.txt +0 -0
osism/tasks/netbox.py
CHANGED
@@ -17,6 +17,9 @@ def setup_periodic_tasks(sender, **kwargs):
|
|
17
17
|
|
18
18
|
@app.task(bind=True, name="osism.tasks.netbox.run")
|
19
19
|
def run(self, action, arguments):
|
20
|
+
# Check if tasks are locked before execution
|
21
|
+
utils.check_task_lock_and_exit()
|
22
|
+
|
20
23
|
pass
|
21
24
|
|
22
25
|
|
@@ -28,6 +31,8 @@ def run(self, action, arguments):
|
|
28
31
|
@app.task(bind=True, name="osism.tasks.netbox.set_maintenance")
|
29
32
|
def set_maintenance(self, device_name, state=True):
|
30
33
|
"""Set the maintenance state for a device in the NetBox."""
|
34
|
+
# Check if tasks are locked before execution
|
35
|
+
utils.check_task_lock_and_exit()
|
31
36
|
|
32
37
|
lock = utils.create_redlock(
|
33
38
|
key=f"lock_osism_tasks_netbox_set_maintenance_{device_name}",
|
@@ -56,6 +61,8 @@ def set_maintenance(self, device_name, state=True):
|
|
56
61
|
@app.task(bind=True, name="osism.tasks.netbox.set_provision_state")
|
57
62
|
def set_provision_state(self, device_name, state):
|
58
63
|
"""Set the provision state for a device in the NetBox."""
|
64
|
+
# Check if tasks are locked before execution
|
65
|
+
utils.check_task_lock_and_exit()
|
59
66
|
|
60
67
|
lock = utils.create_redlock(
|
61
68
|
key=f"lock_osism_tasks_netbox_set_provision_state_{device_name}",
|
@@ -85,6 +92,8 @@ def set_provision_state(self, device_name, state):
|
|
85
92
|
@app.task(bind=True, name="osism.tasks.netbox.set_power_state")
|
86
93
|
def set_power_state(self, device_name, state):
|
87
94
|
"""Set the provision state for a device in the NetBox."""
|
95
|
+
# Check if tasks are locked before execution
|
96
|
+
utils.check_task_lock_and_exit()
|
88
97
|
|
89
98
|
lock = utils.create_redlock(
|
90
99
|
key=f"lock_osism_tasks_netbox_set_provision_state_{device_name}",
|
@@ -156,6 +165,9 @@ def get_addresses_by_device_and_interface(self, device_name, interface_name):
|
|
156
165
|
|
157
166
|
@app.task(bind=True, name="osism.tasks.netbox.manage")
|
158
167
|
def manage(self, *arguments, publish=True, locking=False, auto_release_time=3600):
|
168
|
+
# Check if tasks are locked before execution
|
169
|
+
utils.check_task_lock_and_exit()
|
170
|
+
|
159
171
|
netbox_manager_env = {
|
160
172
|
"NETBOX_MANAGER_URL": str(settings.NETBOX_URL),
|
161
173
|
"NETBOX_MANAGER_TOKEN": str(settings.NETBOX_TOKEN),
|
osism/tasks/openstack.py
CHANGED
@@ -1,10 +1,15 @@
|
|
1
1
|
# SPDX-License-Identifier: Apache-2.0
|
2
2
|
|
3
3
|
from celery import Celery
|
4
|
+
import os
|
5
|
+
import shutil
|
4
6
|
import tempfile
|
7
|
+
import yaml
|
8
|
+
from loguru import logger
|
5
9
|
|
6
10
|
from osism import utils
|
7
11
|
from osism.tasks import Config, run_command
|
12
|
+
from osism.tasks.conductor.utils import get_vault
|
8
13
|
|
9
14
|
app = Celery("openstack")
|
10
15
|
app.config_from_object(Config)
|
@@ -157,6 +162,208 @@ def baremetal_port_delete(self, port_or_id):
|
|
157
162
|
return result
|
158
163
|
|
159
164
|
|
165
|
+
def get_cloud_password(cloud):
|
166
|
+
"""
|
167
|
+
Load and decrypt the OpenStack password for a specific cloud profile
|
168
|
+
from the Ansible Vault encrypted secrets.yml file.
|
169
|
+
|
170
|
+
Args:
|
171
|
+
cloud (str): The cloud profile name
|
172
|
+
|
173
|
+
Returns:
|
174
|
+
str: The decrypted password or None if not found/decryptable
|
175
|
+
"""
|
176
|
+
if not cloud:
|
177
|
+
logger.warning("No cloud parameter provided for password lookup")
|
178
|
+
return None
|
179
|
+
|
180
|
+
secrets_path = "/opt/configuration/environments/openstack/secrets.yml"
|
181
|
+
# Replace hyphens with underscores for password key (admin-system -> admin_system)
|
182
|
+
cloud_normalized = cloud.replace("-", "_")
|
183
|
+
password_key = f"os_password_{cloud_normalized}"
|
184
|
+
|
185
|
+
try:
|
186
|
+
# Check if secrets file exists
|
187
|
+
if not os.path.exists(secrets_path):
|
188
|
+
logger.warning(f"Secrets file not found: {secrets_path}")
|
189
|
+
return None
|
190
|
+
|
191
|
+
# Get vault instance for decryption
|
192
|
+
vault = get_vault()
|
193
|
+
|
194
|
+
# Load and decrypt the entire Ansible Vault encrypted file
|
195
|
+
with open(secrets_path, "rb") as f:
|
196
|
+
encrypted_data = f.read()
|
197
|
+
|
198
|
+
# Decrypt the entire file content
|
199
|
+
decrypted_data = vault.decrypt(encrypted_data).decode()
|
200
|
+
|
201
|
+
# Parse the decrypted YAML content safely
|
202
|
+
try:
|
203
|
+
decrypted_secrets = yaml.safe_load(decrypted_data)
|
204
|
+
except yaml.YAMLError as yaml_exc:
|
205
|
+
logger.error(
|
206
|
+
f"Failed to parse YAML content from decrypted secrets file: {yaml_exc}"
|
207
|
+
)
|
208
|
+
return None
|
209
|
+
|
210
|
+
if not decrypted_secrets or not isinstance(decrypted_secrets, dict):
|
211
|
+
logger.warning(
|
212
|
+
f"Empty or invalid secrets file after decryption: {secrets_path}"
|
213
|
+
)
|
214
|
+
return None
|
215
|
+
|
216
|
+
# Extract the password for the specified cloud - validate key format first
|
217
|
+
if not password_key.isidentifier() or not password_key.startswith(
|
218
|
+
"os_password_"
|
219
|
+
):
|
220
|
+
logger.error(f"Invalid password key format: '{password_key}'")
|
221
|
+
return None
|
222
|
+
|
223
|
+
password = decrypted_secrets.get(password_key)
|
224
|
+
|
225
|
+
if password is not None:
|
226
|
+
# Convert password to string and strip whitespace
|
227
|
+
password_str = str(password).strip()
|
228
|
+
if password_str:
|
229
|
+
logger.info(f"Successfully loaded password for cloud '{cloud}'")
|
230
|
+
return password_str
|
231
|
+
else:
|
232
|
+
logger.warning(
|
233
|
+
f"Password key '{password_key}' is empty after conversion"
|
234
|
+
)
|
235
|
+
return None
|
236
|
+
else:
|
237
|
+
logger.warning(f"Password key '{password_key}' not found in secrets file")
|
238
|
+
return None
|
239
|
+
|
240
|
+
except Exception as exc:
|
241
|
+
logger.error(f"Failed to load/decrypt password for cloud '{cloud}': {exc}")
|
242
|
+
return None
|
243
|
+
|
244
|
+
|
245
|
+
def setup_cloud_environment(cloud):
|
246
|
+
"""
|
247
|
+
Set up cloud configuration environment for OpenStack commands.
|
248
|
+
|
249
|
+
Creates secure.yml with cloud password and copies clouds.yaml to /tmp,
|
250
|
+
then changes working directory to /tmp.
|
251
|
+
|
252
|
+
Args:
|
253
|
+
cloud (str): The cloud profile name
|
254
|
+
|
255
|
+
Returns:
|
256
|
+
tuple: (temp_files_to_cleanup, original_cwd, success)
|
257
|
+
"""
|
258
|
+
temp_files_to_cleanup = []
|
259
|
+
original_cwd = os.getcwd()
|
260
|
+
|
261
|
+
if not cloud:
|
262
|
+
logger.warning("No cloud parameter provided, skipping cloud configuration")
|
263
|
+
return temp_files_to_cleanup, original_cwd, False
|
264
|
+
|
265
|
+
password = get_cloud_password(cloud)
|
266
|
+
if not password:
|
267
|
+
logger.warning(
|
268
|
+
f"Could not load password for cloud '{cloud}', skipping cloud configuration"
|
269
|
+
)
|
270
|
+
return temp_files_to_cleanup, original_cwd, False
|
271
|
+
|
272
|
+
try:
|
273
|
+
# Create secure.yml in /tmp
|
274
|
+
secure_yml_path = "/tmp/secure.yml"
|
275
|
+
secure_yml_content = {"clouds": {cloud: {"auth": {"password": password}}}}
|
276
|
+
|
277
|
+
with open(secure_yml_path, "w") as f:
|
278
|
+
yaml.dump(secure_yml_content, f)
|
279
|
+
temp_files_to_cleanup.append(secure_yml_path)
|
280
|
+
|
281
|
+
# Try both .yaml and .yml extensions
|
282
|
+
if os.path.exists("/etc/openstack/clouds.yaml"):
|
283
|
+
shutil.copy2("/etc/openstack/clouds.yaml", "/tmp/clouds.yaml")
|
284
|
+
temp_files_to_cleanup.append("/tmp/clouds.yaml")
|
285
|
+
elif os.path.exists("/etc/openstack/clouds.yml"):
|
286
|
+
shutil.copy2("/etc/openstack/clouds.yml", "/tmp/clouds.yml")
|
287
|
+
temp_files_to_cleanup.append("/tmp/clouds.yml")
|
288
|
+
else:
|
289
|
+
logger.warning("Could not find /etc/openstack/clouds.yaml or clouds.yml")
|
290
|
+
|
291
|
+
# Change working directory to /tmp
|
292
|
+
os.chdir("/tmp")
|
293
|
+
|
294
|
+
logger.debug(f"Successfully set up cloud environment for '{cloud}'")
|
295
|
+
return temp_files_to_cleanup, original_cwd, True
|
296
|
+
|
297
|
+
except Exception as exc:
|
298
|
+
logger.error(f"Failed to set up cloud environment for '{cloud}': {exc}")
|
299
|
+
return temp_files_to_cleanup, original_cwd, False
|
300
|
+
|
301
|
+
|
302
|
+
def cleanup_cloud_environment(temp_files_to_cleanup, original_cwd):
|
303
|
+
"""
|
304
|
+
Clean up temporary files and restore working directory.
|
305
|
+
|
306
|
+
Args:
|
307
|
+
temp_files_to_cleanup (list): List of temporary files to remove
|
308
|
+
original_cwd (str): Original working directory to restore
|
309
|
+
"""
|
310
|
+
# Restore working directory
|
311
|
+
try:
|
312
|
+
os.chdir(original_cwd)
|
313
|
+
except Exception as exc:
|
314
|
+
logger.warning(f"Could not restore original working directory: {exc}")
|
315
|
+
|
316
|
+
# Clean up temporary files
|
317
|
+
for temp_file in temp_files_to_cleanup:
|
318
|
+
try:
|
319
|
+
if os.path.exists(temp_file):
|
320
|
+
os.remove(temp_file)
|
321
|
+
logger.debug(f"Cleaned up temporary file: {temp_file}")
|
322
|
+
except Exception as exc:
|
323
|
+
logger.warning(f"Could not remove temporary file {temp_file}: {exc}")
|
324
|
+
|
325
|
+
|
326
|
+
def run_openstack_command_with_cloud(
|
327
|
+
request_id,
|
328
|
+
command,
|
329
|
+
cloud,
|
330
|
+
arguments,
|
331
|
+
publish=True,
|
332
|
+
locking=False,
|
333
|
+
auto_release_time=3600,
|
334
|
+
):
|
335
|
+
"""
|
336
|
+
Execute an OpenStack command with cloud configuration setup.
|
337
|
+
|
338
|
+
Args:
|
339
|
+
request_id: Celery request ID
|
340
|
+
command (str): Command to execute
|
341
|
+
cloud (str): Cloud profile name
|
342
|
+
arguments (list): Command arguments
|
343
|
+
**kwargs: Additional arguments for run_command
|
344
|
+
|
345
|
+
Returns:
|
346
|
+
int: Command return code
|
347
|
+
"""
|
348
|
+
temp_files_to_cleanup, original_cwd, cloud_setup_success = setup_cloud_environment(
|
349
|
+
cloud
|
350
|
+
)
|
351
|
+
|
352
|
+
try:
|
353
|
+
return run_command(
|
354
|
+
request_id,
|
355
|
+
command,
|
356
|
+
{},
|
357
|
+
*arguments,
|
358
|
+
publish=publish,
|
359
|
+
locking=locking,
|
360
|
+
auto_release_time=auto_release_time,
|
361
|
+
ignore_env=True,
|
362
|
+
)
|
363
|
+
finally:
|
364
|
+
cleanup_cloud_environment(temp_files_to_cleanup, original_cwd)
|
365
|
+
|
366
|
+
|
160
367
|
@app.task(bind=True, name="osism.tasks.openstack.image_manager")
|
161
368
|
def image_manager(
|
162
369
|
self,
|
@@ -165,62 +372,82 @@ def image_manager(
|
|
165
372
|
publish=True,
|
166
373
|
locking=False,
|
167
374
|
auto_release_time=3600,
|
168
|
-
|
375
|
+
cloud=None,
|
169
376
|
):
|
377
|
+
# Check if tasks are locked before execution
|
378
|
+
utils.check_task_lock_and_exit()
|
379
|
+
|
170
380
|
command = "/usr/local/bin/openstack-image-manager"
|
381
|
+
|
171
382
|
if configs:
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
sanitized_args
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
383
|
+
# For configs case, we need to handle image directory setup and cloud configuration
|
384
|
+
temp_files_to_cleanup, original_cwd, cloud_setup_success = (
|
385
|
+
setup_cloud_environment(cloud)
|
386
|
+
)
|
387
|
+
|
388
|
+
try:
|
389
|
+
with tempfile.TemporaryDirectory() as temp_dir:
|
390
|
+
for config in configs:
|
391
|
+
with tempfile.NamedTemporaryFile(
|
392
|
+
mode="w+", suffix=".yml", dir=temp_dir, delete=False
|
393
|
+
) as temp_file:
|
394
|
+
temp_file.write(config)
|
395
|
+
|
396
|
+
sanitized_args = [
|
397
|
+
arg for arg in arguments if not arg.startswith("--images=")
|
398
|
+
]
|
399
|
+
|
400
|
+
try:
|
401
|
+
images_index = sanitized_args.index("--images")
|
402
|
+
sanitized_args.pop(images_index)
|
403
|
+
sanitized_args.pop(images_index)
|
404
|
+
except ValueError:
|
405
|
+
pass
|
406
|
+
sanitized_args.extend(["--images", temp_dir])
|
407
|
+
|
408
|
+
return run_command(
|
409
|
+
self.request.id,
|
410
|
+
command,
|
411
|
+
{},
|
412
|
+
*sanitized_args,
|
413
|
+
publish=publish,
|
414
|
+
locking=locking,
|
415
|
+
auto_release_time=auto_release_time,
|
416
|
+
ignore_env=True,
|
417
|
+
)
|
418
|
+
finally:
|
419
|
+
cleanup_cloud_environment(temp_files_to_cleanup, original_cwd)
|
201
420
|
else:
|
202
|
-
|
421
|
+
# Simple case - use the generalized helper
|
422
|
+
return run_openstack_command_with_cloud(
|
203
423
|
self.request.id,
|
204
424
|
command,
|
205
|
-
|
206
|
-
|
425
|
+
cloud,
|
426
|
+
arguments,
|
207
427
|
publish=publish,
|
208
428
|
locking=locking,
|
209
429
|
auto_release_time=auto_release_time,
|
210
|
-
ignore_env=ignore_env,
|
211
430
|
)
|
212
431
|
|
213
432
|
|
214
433
|
@app.task(bind=True, name="osism.tasks.openstack.flavor_manager")
|
215
434
|
def flavor_manager(
|
216
|
-
self,
|
435
|
+
self,
|
436
|
+
*arguments,
|
437
|
+
publish=True,
|
438
|
+
locking=False,
|
439
|
+
auto_release_time=3600,
|
440
|
+
cloud=None,
|
217
441
|
):
|
442
|
+
# Check if tasks are locked before execution
|
443
|
+
utils.check_task_lock_and_exit()
|
444
|
+
|
218
445
|
command = "/usr/local/bin/openstack-flavor-manager"
|
219
|
-
return
|
446
|
+
return run_openstack_command_with_cloud(
|
220
447
|
self.request.id,
|
221
448
|
command,
|
222
|
-
|
223
|
-
|
449
|
+
cloud,
|
450
|
+
arguments,
|
224
451
|
publish=publish,
|
225
452
|
locking=locking,
|
226
453
|
auto_release_time=auto_release_time,
|
osism/tasks/reconciler.py
CHANGED
@@ -27,6 +27,9 @@ def setup_periodic_tasks(sender, **kwargs):
|
|
27
27
|
|
28
28
|
@app.task(bind=True, name="osism.tasks.reconciler.run")
|
29
29
|
def run(self, publish=True, flush_cache=False):
|
30
|
+
# Check if tasks are locked before execution
|
31
|
+
utils.check_task_lock_and_exit()
|
32
|
+
|
30
33
|
lock = utils.create_redlock(
|
31
34
|
key="lock_osism_tasks_reconciler_run",
|
32
35
|
auto_release_time=60,
|
osism/utils/__init__.py
CHANGED
@@ -242,3 +242,84 @@ def create_redlock(key, auto_release_time=3600):
|
|
242
242
|
masters={redis},
|
243
243
|
auto_release_time=auto_release_time,
|
244
244
|
)
|
245
|
+
|
246
|
+
|
247
|
+
def set_task_lock(user=None, reason=None):
|
248
|
+
"""
|
249
|
+
Set task lock to prevent new tasks from starting.
|
250
|
+
|
251
|
+
Args:
|
252
|
+
user (str): User who set the lock (optional)
|
253
|
+
reason (str): Reason for the lock (optional)
|
254
|
+
|
255
|
+
Returns:
|
256
|
+
bool: True if lock was set successfully
|
257
|
+
"""
|
258
|
+
try:
|
259
|
+
import json
|
260
|
+
from datetime import datetime
|
261
|
+
|
262
|
+
lock_data = {
|
263
|
+
"locked": True,
|
264
|
+
"timestamp": datetime.now().isoformat(),
|
265
|
+
"user": user or "dragon",
|
266
|
+
"reason": reason,
|
267
|
+
}
|
268
|
+
|
269
|
+
redis.set("osism:task_lock", json.dumps(lock_data))
|
270
|
+
return True
|
271
|
+
except Exception as e:
|
272
|
+
logger.error(f"Failed to set task lock: {e}")
|
273
|
+
return False
|
274
|
+
|
275
|
+
|
276
|
+
def remove_task_lock():
|
277
|
+
"""
|
278
|
+
Remove task lock to allow new tasks to start.
|
279
|
+
|
280
|
+
Returns:
|
281
|
+
bool: True if lock was removed successfully
|
282
|
+
"""
|
283
|
+
try:
|
284
|
+
redis.delete("osism:task_lock")
|
285
|
+
return True
|
286
|
+
except Exception as e:
|
287
|
+
logger.error(f"Failed to remove task lock: {e}")
|
288
|
+
return False
|
289
|
+
|
290
|
+
|
291
|
+
def is_task_locked():
|
292
|
+
"""
|
293
|
+
Check if tasks are currently locked.
|
294
|
+
|
295
|
+
Returns:
|
296
|
+
dict: Lock status information or None if not locked
|
297
|
+
"""
|
298
|
+
try:
|
299
|
+
import json
|
300
|
+
|
301
|
+
lock_data = redis.get("osism:task_lock")
|
302
|
+
if lock_data:
|
303
|
+
return json.loads(lock_data.decode("utf-8"))
|
304
|
+
return None
|
305
|
+
except Exception as e:
|
306
|
+
logger.error(f"Failed to check task lock status: {e}")
|
307
|
+
return None
|
308
|
+
|
309
|
+
|
310
|
+
def check_task_lock_and_exit():
|
311
|
+
"""
|
312
|
+
Check if tasks are locked and exit with error message if they are.
|
313
|
+
Used by commands that should not run when tasks are locked.
|
314
|
+
"""
|
315
|
+
lock_info = is_task_locked()
|
316
|
+
if lock_info and lock_info.get("locked"):
|
317
|
+
user = lock_info.get("user", "unknown")
|
318
|
+
timestamp = lock_info.get("timestamp", "unknown")
|
319
|
+
reason = lock_info.get("reason")
|
320
|
+
|
321
|
+
logger.error(f"Tasks are currently locked by {user} at {timestamp}")
|
322
|
+
if reason:
|
323
|
+
logger.error(f"Reason: {reason}")
|
324
|
+
logger.error("Use 'osism unlock' to remove the lock")
|
325
|
+
exit(1)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: osism
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.20250827.0
|
4
4
|
Summary: OSISM manager interface
|
5
5
|
Home-page: https://github.com/osism/python-osism
|
6
6
|
Author: OSISM GmbH
|
@@ -26,7 +26,7 @@ Requires-Dist: ClusterShell==1.9.3
|
|
26
26
|
Requires-Dist: GitPython==3.1.45
|
27
27
|
Requires-Dist: Jinja2==3.1.6
|
28
28
|
Requires-Dist: PyYAML==6.0.2
|
29
|
-
Requires-Dist: ara==1.7.
|
29
|
+
Requires-Dist: ara==1.7.3
|
30
30
|
Requires-Dist: celery[redis]==5.5.3
|
31
31
|
Requires-Dist: cliff==4.11.0
|
32
32
|
Requires-Dist: deepdiff==8.6.0
|
@@ -44,7 +44,7 @@ Requires-Dist: nbcli==0.10.0.dev2
|
|
44
44
|
Requires-Dist: openstacksdk==4.7.0
|
45
45
|
Requires-Dist: paramiko==3.5.1
|
46
46
|
Requires-Dist: pottery==3.0.1
|
47
|
-
Requires-Dist: prompt-toolkit==3.0.
|
47
|
+
Requires-Dist: prompt-toolkit==3.0.52
|
48
48
|
Requires-Dist: pynetbox==7.5.0
|
49
49
|
Requires-Dist: pytest-testinfra==10.2.2
|
50
50
|
Requires-Dist: python-dateutil==2.9.0.post0
|
@@ -59,9 +59,9 @@ Requires-Dist: watchdog==6.0.0
|
|
59
59
|
Requires-Dist: websockets==15.0.1
|
60
60
|
Provides-Extra: ansible
|
61
61
|
Requires-Dist: ansible-runner==2.4.1; extra == "ansible"
|
62
|
-
Requires-Dist: ansible-core==2.19.
|
62
|
+
Requires-Dist: ansible-core==2.19.1; extra == "ansible"
|
63
63
|
Provides-Extra: openstack-image-manager
|
64
|
-
Requires-Dist: openstack-image-manager==0.
|
64
|
+
Requires-Dist: openstack-image-manager==0.20250827.0; extra == "openstack-image-manager"
|
65
65
|
Dynamic: author
|
66
66
|
Dynamic: author-email
|
67
67
|
Dynamic: classifier
|
@@ -4,33 +4,34 @@ osism/api.py,sha256=wVPLhPPdBcFx6vss5pX1Y2JxbaNSMh_Bqo4AB529QWI,16945
|
|
4
4
|
osism/main.py,sha256=Dt2-9sLXcS-Ny4DAz7hrha-KRc7zd7BFUTRdfs_X8z4,893
|
5
5
|
osism/settings.py,sha256=VZT1muZVYWM5Ov1eFRC7a4ZGYIdI2AFmudCm0wZ1C2Q,1898
|
6
6
|
osism/commands/__init__.py,sha256=Ag4wX_DCgXRdoLn6t069jqb3DdRylsX2nyYkiyCx4uk,456
|
7
|
-
osism/commands/apply.py,sha256=
|
7
|
+
osism/commands/apply.py,sha256=OtZ4zoSM5uAXc5-GIq7WN8Uwv6idR7Eb8xLw5JS6u38,16953
|
8
8
|
osism/commands/baremetal.py,sha256=TeXwg4lYfxel0YkWC3z8bv9qTsJQmsI2QD6u1K4vhIM,24821
|
9
9
|
osism/commands/compose.py,sha256=76HL9wzTJ7bFPhZk-uyfWq0n6Z74lOHn4RE0zzkHgYE,1241
|
10
10
|
osism/commands/compute.py,sha256=cgqXWJa5wAvn-7e3FWCgX6hie_aK0yrKRkcNzjLXwDY,25799
|
11
|
-
osism/commands/configuration.py,sha256=
|
11
|
+
osism/commands/configuration.py,sha256=XJ8RYSSoHmU_WO4sTS1UEutZwfFrMGTqzHtmndBOwok,1074
|
12
12
|
osism/commands/console.py,sha256=0BSDKewPGAwWAJwi_WrFZ_dRMbMQzbG6IS_0gVi88J8,6276
|
13
13
|
osism/commands/container.py,sha256=jHk5A0PXBzHGIm-1d5HQZI_POANAq7An1lZGRbqBvr0,1642
|
14
14
|
osism/commands/get.py,sha256=ryytjtXWmlMV0NucP5tGkMZu0nIlC4xVtjRk4iMZ06c,8967
|
15
|
+
osism/commands/lock.py,sha256=MrZ5Ku6xJkic8Nlnv285V89EAgi0NQ8HZioU8urpWXA,3220
|
15
16
|
osism/commands/log.py,sha256=QnnTTNiAoa8oj4kDOcggh0QrRAD6onxcEpLXBy7CvDg,4113
|
16
|
-
osism/commands/manage.py,sha256=
|
17
|
-
osism/commands/netbox.py,sha256=
|
18
|
-
osism/commands/noset.py,sha256=
|
19
|
-
osism/commands/reconciler.py,sha256=
|
20
|
-
osism/commands/redfish.py,sha256=
|
17
|
+
osism/commands/manage.py,sha256=nQTsV-0D9_JLR7v53Wa7G0DcOmmfntZ557W4mcQzNw0,17095
|
18
|
+
osism/commands/netbox.py,sha256=dxljfrQ07qHdUgWWRiAxzihlRmXI2JeWWPicuuKTRww,8659
|
19
|
+
osism/commands/noset.py,sha256=0_5-LruRIbmzKP8UfV6r25DaYf0sWC958GZAl5nj04g,1697
|
20
|
+
osism/commands/reconciler.py,sha256=2svFOFEQtPd2z14_lMd0yGrKLgGJ9dh0bCnyCHhl7ms,2305
|
21
|
+
osism/commands/redfish.py,sha256=dcGMF7r4MnKrU95Iy-LFTpHZS2RGQ4kiYN2L1qBvUgg,8551
|
21
22
|
osism/commands/server.py,sha256=avmoOv5rjOi-fN2A-27cPwOtiy2Q2j6UFtCh3QrfWAI,7512
|
22
|
-
osism/commands/service.py,sha256=
|
23
|
-
osism/commands/set.py,sha256=
|
24
|
-
osism/commands/sonic.py,sha256=
|
23
|
+
osism/commands/service.py,sha256=aWcWoTKFWB7IU10IRRaFN0Oo-Hy0MbaEWjXASV744As,2769
|
24
|
+
osism/commands/set.py,sha256=Qbq46_jWkL9ilMtRadtjDYayd9W2XaAQlodfRy2hEiw,1641
|
25
|
+
osism/commands/sonic.py,sha256=_-pxkgddxFrEJ-6QqSSxv2_fDA5x9U4lt8esGWDa0Ds,43718
|
25
26
|
osism/commands/status.py,sha256=X-Rcj-XuNPDBoxsGkf96NswwpmTognxz1V6E2NX2ZgY,1997
|
26
|
-
osism/commands/sync.py,sha256=
|
27
|
+
osism/commands/sync.py,sha256=C7jVtm33VhC9Mmxi1St1k3Cfgl0gFul3BSEseIv_se8,2135
|
27
28
|
osism/commands/task.py,sha256=mwJJ7a71Lw3o_FX7j3rR0-NbPdPwMDOjbOAiiXE4uGc,543
|
28
|
-
osism/commands/validate.py,sha256=
|
29
|
+
osism/commands/validate.py,sha256=xZ0XRvxel9L9-C6qDUy1SMfwSo8bL-5eTnKGPg5ZuDA,3358
|
29
30
|
osism/commands/vault.py,sha256=llaqNN8UH8t8cCu2KmdaURvprA4zeG6izCen_W7ulPs,2029
|
30
31
|
osism/commands/volume.py,sha256=l6oAk__dFM8KKdLTWOvuSiI7tLh9wAPZp8hwmYF-NX0,6595
|
31
32
|
osism/commands/wait.py,sha256=2Ncx63M0AFq4fq40VZVClf1LS-WHetD8iC_mG2dY_Cw,5275
|
32
|
-
osism/commands/worker.py,sha256=
|
33
|
-
osism/data/__init__.py,sha256=
|
33
|
+
osism/commands/worker.py,sha256=S8EBBVHSP6qQ4nek5fPclxdeHtjY4AFQF43YK0Kyly4,1777
|
34
|
+
osism/data/__init__.py,sha256=7nhKIh5lATHCVO34En60dmM9WXclucRO59ylMp_1gks,2232
|
34
35
|
osism/data/enums.py,sha256=gItIjOK6xWuOZSkMxpMdYLRyt4ezyhzkqA7BGiah2o0,10030
|
35
36
|
osism/data/playbooks.py,sha256=M3T3ajV-8Lt-orsRO3jAoukhaoYFr4EZ2dzYXQjt1kg,728
|
36
37
|
osism/services/__init__.py,sha256=bG7Ffen4LvQtgnYPFEpFccsWs81t4zqqeqn9ZeirH6E,38
|
@@ -38,15 +39,15 @@ osism/services/event_bridge.py,sha256=roV90o9UgTnwoVbXnPR3muBk04IriVYCO_fewZ46Mq
|
|
38
39
|
osism/services/listener.py,sha256=O8Xq5fEEVoNFIgFPE7GqfVqx6C4QkdWhUPUGzODFnws,14211
|
39
40
|
osism/services/websocket_manager.py,sha256=F147kWOg8PAvbVG4aVYQVtK4mFMfPVtHxxYJXaqiAjg,11051
|
40
41
|
osism/tasks/__init__.py,sha256=iAUs-ttUMw1nZElL631sT1ke29RvTjQjlhWPl_kGrEw,9003
|
41
|
-
osism/tasks/ansible.py,sha256
|
42
|
-
osism/tasks/ceph.py,sha256=
|
42
|
+
osism/tasks/ansible.py,sha256=wAeFqyY8EavySpOIBSgWwK3HcGXWPZCIVOaSss5irCM,1387
|
43
|
+
osism/tasks/ceph.py,sha256=Zo-92rzbJ9NDH9dbKi_JPWwekO3cYTdbmwAGSwr5l0w,726
|
43
44
|
osism/tasks/conductor.py,sha256=WBLsoPtr0iGUzRGERs0Xt7CMYrnHQVEwNV9qXBssI3s,274
|
44
|
-
osism/tasks/kolla.py,sha256=
|
45
|
-
osism/tasks/kubernetes.py,sha256=
|
46
|
-
osism/tasks/netbox.py,sha256=
|
47
|
-
osism/tasks/openstack.py,sha256=
|
48
|
-
osism/tasks/reconciler.py,sha256=
|
49
|
-
osism/tasks/conductor/__init__.py,sha256=
|
45
|
+
osism/tasks/kolla.py,sha256=1p0SZBTYpUvIg09czwUmnMh6LIBhleB6O1WSX1mkmJo,729
|
46
|
+
osism/tasks/kubernetes.py,sha256=hrzzDPM0Vx0_KWNxQwsQG54y1v0s2goFYJIMriX0Gh4,736
|
47
|
+
osism/tasks/netbox.py,sha256=FjEGQUZDzAVqA9cc3eQqaPv5-hPj3iI9lEc9SkuDO7M,6278
|
48
|
+
osism/tasks/openstack.py,sha256=c5PyVlSzn69Xw-nFgUf1cX3a3E_STSCNrIectiDzqPI,14871
|
49
|
+
osism/tasks/reconciler.py,sha256=vlPdOr7nbqggfVMSNez-JHZmKw8L7YmqKQnLF7TOXuQ,2045
|
50
|
+
osism/tasks/conductor/__init__.py,sha256=pS0jJqmSRIY0fHd3982KSuvCwI1gDzfj5iSFxaSMTyM,2215
|
50
51
|
osism/tasks/conductor/config.py,sha256=n1H9_8DY90p5E4mygzKyJUl8G3WdDuGHFTp-SrmZmgU,4543
|
51
52
|
osism/tasks/conductor/ironic.py,sha256=sxUHAzs8_Z-IaB5ZZ0ufObWiytBKiptPUWoIGWo2wcY,16440
|
52
53
|
osism/tasks/conductor/netbox.py,sha256=xPJn-tXLqTAgW3v6L9rQ__XGHhM7ErchnyfsLY6iH14,13381
|
@@ -62,13 +63,13 @@ osism/tasks/conductor/sonic/device.py,sha256=ZYJA0bQ8waKWStzWUPxbcwNWa2Z_hMB3pqs
|
|
62
63
|
osism/tasks/conductor/sonic/exporter.py,sha256=25L1vbi84ZQD0xNHNTWk-anTz5QRkGJskCECBkeGQw4,8882
|
63
64
|
osism/tasks/conductor/sonic/interface.py,sha256=M876LHdFqGxUfTizzDusdzvCkDI0vCgqte5uLmOXFaY,39472
|
64
65
|
osism/tasks/conductor/sonic/sync.py,sha256=fpgsQVwq6Hb7eeDHhLkAqx5BkaK3Ce_m_WvmWEsJyOo,9182
|
65
|
-
osism/utils/__init__.py,sha256=
|
66
|
+
osism/utils/__init__.py,sha256=IEr0sR1HKg-QI_u84fs4gMldC6-EPSxvMBh2zMGu5dU,9939
|
66
67
|
osism/utils/ssh.py,sha256=nxeEgwjJWvQCybKDp-NelMeWyODCYpaXFCBchAv4-bg,8691
|
67
|
-
osism-0.
|
68
|
-
osism-0.
|
69
|
-
osism-0.
|
70
|
-
osism-0.
|
71
|
-
osism-0.
|
72
|
-
osism-0.
|
73
|
-
osism-0.
|
74
|
-
osism-0.
|
68
|
+
osism-0.20250827.0.dist-info/licenses/AUTHORS,sha256=EKFIR9F27AvoEXp1cA6FkGbjEOFt4Rcbipr5RJc7jSs,64
|
69
|
+
osism-0.20250827.0.dist-info/licenses/LICENSE,sha256=tAkwu8-AdEyGxGoSvJ2gVmQdcicWw3j1ZZueVV74M-E,11357
|
70
|
+
osism-0.20250827.0.dist-info/METADATA,sha256=db-Wl6Z-yJlLgkOrnSul0rhX7AsSUBS4IjbGZylytO0,2971
|
71
|
+
osism-0.20250827.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
72
|
+
osism-0.20250827.0.dist-info/entry_points.txt,sha256=W45YQ7MJ7BCAPZXl3F6d2FSi6An0moZQbzLn_BwGnRE,4618
|
73
|
+
osism-0.20250827.0.dist-info/pbr.json,sha256=RMUc1kb18-_rQuHlqeVqOjLNYTKhFnuNFJHUGDb-3DQ,47
|
74
|
+
osism-0.20250827.0.dist-info/top_level.txt,sha256=8L8dsI9hcaGHsdnR4k_LN9EM78EhwrXRFHyAryPXZtY,6
|
75
|
+
osism-0.20250827.0.dist-info/RECORD,,
|
@@ -27,6 +27,8 @@ get status = osism.commands.status:Run
|
|
27
27
|
get tasks = osism.commands.get:Tasks
|
28
28
|
get versions manager = osism.commands.get:VersionsManager
|
29
29
|
get versions netbox = osism.commands.netbox:Versions
|
30
|
+
lock = osism.commands.lock:Lock
|
31
|
+
lock status = osism.commands.lock:LockStatus
|
30
32
|
log ansible = osism.commands.log:Ansible
|
31
33
|
log container = osism.commands.log:Container
|
32
34
|
log file = osism.commands.log:File
|
@@ -49,6 +51,7 @@ manage compute stop = osism.commands.compute:ComputeStop
|
|
49
51
|
manage dnsmasq = osism.commands.manage:Dnsmasq
|
50
52
|
manage flavors = osism.commands.manage:Flavors
|
51
53
|
manage image clusterapi = osism.commands.manage:ImageClusterapi
|
54
|
+
manage image gardenlinux = osism.commands.manage:ImageGardenlinux
|
52
55
|
manage image octavia = osism.commands.manage:ImageOctavia
|
53
56
|
manage images = osism.commands.manage:Images
|
54
57
|
manage netbox = osism.commands.netbox:Manage
|
@@ -85,6 +88,7 @@ sync netbox = osism.commands.netbox:Sync
|
|
85
88
|
sync sonic = osism.commands.sync:Sonic
|
86
89
|
task list = osism.commands.get:Tasks
|
87
90
|
task revoke = osism.commands.task:Revoke
|
91
|
+
unlock = osism.commands.lock:Unlock
|
88
92
|
validate = osism.commands.validate:Run
|
89
93
|
vault password set = osism.commands.vault:SetPassword
|
90
94
|
vault password unset = osism.commands.vault:UnsetPassword
|
@@ -0,0 +1 @@
|
|
1
|
+
renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
|
@@ -0,0 +1 @@
|
|
1
|
+
{"git_version": "bbad13f", "is_release": false}
|
@@ -1 +0,0 @@
|
|
1
|
-
Christian Berendt <berendt@osism.tech>
|
@@ -1 +0,0 @@
|
|
1
|
-
{"git_version": "2d93840", "is_release": false}
|
File without changes
|
File without changes
|
File without changes
|