osism 0.20250919.0__py3-none-any.whl → 0.20251004.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/tasks/__init__.py +143 -2
- osism/tasks/kubernetes.py +1 -1
- {osism-0.20250919.0.dist-info → osism-0.20251004.0.dist-info}/METADATA +5 -5
- {osism-0.20250919.0.dist-info → osism-0.20251004.0.dist-info}/RECORD +10 -10
- osism-0.20251004.0.dist-info/licenses/AUTHORS +1 -0
- osism-0.20251004.0.dist-info/pbr.json +1 -0
- osism-0.20250919.0.dist-info/licenses/AUTHORS +0 -1
- osism-0.20250919.0.dist-info/pbr.json +0 -1
- {osism-0.20250919.0.dist-info → osism-0.20251004.0.dist-info}/WHEEL +0 -0
- {osism-0.20250919.0.dist-info → osism-0.20251004.0.dist-info}/entry_points.txt +0 -0
- {osism-0.20250919.0.dist-info → osism-0.20251004.0.dist-info}/licenses/LICENSE +0 -0
- {osism-0.20250919.0.dist-info → osism-0.20251004.0.dist-info}/top_level.txt +0 -0
osism/tasks/__init__.py
CHANGED
@@ -1,13 +1,21 @@
|
|
1
1
|
# SPDX-License-Identifier: Apache-2.0
|
2
2
|
|
3
|
+
import fcntl
|
4
|
+
import json
|
3
5
|
import os
|
4
6
|
import re
|
5
7
|
import subprocess
|
8
|
+
import yaml
|
9
|
+
from datetime import datetime, timezone
|
10
|
+
from pathlib import Path
|
6
11
|
|
7
12
|
from loguru import logger
|
8
13
|
|
9
14
|
from osism import utils
|
10
15
|
|
16
|
+
# Regex pattern for extracting hosts from Ansible output
|
17
|
+
HOST_PATTERN = re.compile(r"^(ok|changed|failed|skipping|unreachable):\s+\[([^\]]+)\]")
|
18
|
+
|
11
19
|
|
12
20
|
class Config:
|
13
21
|
broker_connection_retry_on_startup = True
|
@@ -30,6 +38,109 @@ class Config:
|
|
30
38
|
}
|
31
39
|
|
32
40
|
|
41
|
+
def get_container_version(worker):
|
42
|
+
"""Read container version from YAML version file.
|
43
|
+
|
44
|
+
Args:
|
45
|
+
worker: The runtime container name (osism-ansible, kolla-ansible, ceph-ansible, osism-kubernetes)
|
46
|
+
|
47
|
+
Returns:
|
48
|
+
str: The container version, "latest" if empty, or "unknown" if not found
|
49
|
+
|
50
|
+
Examples:
|
51
|
+
>>> get_container_version("osism-ansible")
|
52
|
+
"7.0.5a"
|
53
|
+
>>> get_container_version("kolla-ansible")
|
54
|
+
"18.1.0"
|
55
|
+
>>> get_container_version("osism-kubernetes")
|
56
|
+
"1.29.0"
|
57
|
+
|
58
|
+
Note:
|
59
|
+
If the version parameter in the YAML file is an empty string (""),
|
60
|
+
the function returns "latest" as the default value.
|
61
|
+
"""
|
62
|
+
version_file = Path(f"/interface/versions/{worker}.yml")
|
63
|
+
|
64
|
+
try:
|
65
|
+
if not version_file.exists():
|
66
|
+
logger.debug(f"Version file not found: {version_file}")
|
67
|
+
return "unknown"
|
68
|
+
|
69
|
+
with open(version_file, "r") as f:
|
70
|
+
version_data = yaml.safe_load(f)
|
71
|
+
|
72
|
+
# Convert worker name to version parameter name
|
73
|
+
# osism-ansible -> osism_ansible_version
|
74
|
+
# kolla-ansible -> kolla_ansible_version
|
75
|
+
# ceph-ansible -> ceph_ansible_version
|
76
|
+
version_key = f"{worker.replace('-', '_')}_version"
|
77
|
+
|
78
|
+
version = version_data.get(version_key, "unknown")
|
79
|
+
|
80
|
+
# If version is empty string, use "latest" as default
|
81
|
+
if version == "":
|
82
|
+
version = "latest"
|
83
|
+
logger.debug(f"Version parameter empty for {worker}, using 'latest'")
|
84
|
+
|
85
|
+
logger.debug(f"Read version {version} for {worker} from {version_file}")
|
86
|
+
return version
|
87
|
+
|
88
|
+
except Exception as e:
|
89
|
+
logger.warning(f"Failed to read version from {version_file}: {e}")
|
90
|
+
return "unknown"
|
91
|
+
|
92
|
+
|
93
|
+
def log_play_execution(
|
94
|
+
request_id, worker, environment, role, hosts=None, arguments=None, result="started"
|
95
|
+
):
|
96
|
+
"""Log Ansible play execution to central tracking file.
|
97
|
+
|
98
|
+
Args:
|
99
|
+
request_id: The Celery task request ID for correlation
|
100
|
+
worker: The runtime container (osism-ansible, kolla-ansible, ceph-ansible, osism-kubernetes)
|
101
|
+
environment: The environment parameter
|
102
|
+
role: The playbook/role that was executed
|
103
|
+
hosts: List of hosts the play was executed against (default: empty list)
|
104
|
+
arguments: Command-line arguments passed to ansible-playbook (default: None)
|
105
|
+
result: Execution result - "started", "success", or "failure"
|
106
|
+
"""
|
107
|
+
log_file = Path("/share/ansible-execution-history.json")
|
108
|
+
|
109
|
+
# Get runtime version from YAML version file
|
110
|
+
runtime_version = get_container_version(worker)
|
111
|
+
|
112
|
+
# Use provided hosts or empty list
|
113
|
+
if hosts is None:
|
114
|
+
hosts = []
|
115
|
+
|
116
|
+
execution_record = {
|
117
|
+
"timestamp": datetime.now(timezone.utc).isoformat().replace("+00:00", "Z"),
|
118
|
+
"request_id": request_id,
|
119
|
+
"worker": worker,
|
120
|
+
"worker_version": runtime_version,
|
121
|
+
"environment": environment,
|
122
|
+
"role": role,
|
123
|
+
"hosts": hosts,
|
124
|
+
"arguments": arguments if arguments else "",
|
125
|
+
"result": result,
|
126
|
+
}
|
127
|
+
|
128
|
+
try:
|
129
|
+
# Create directory if it doesn't exist
|
130
|
+
log_file.parent.mkdir(parents=True, exist_ok=True)
|
131
|
+
|
132
|
+
# Append with file locking for thread safety
|
133
|
+
with open(log_file, "a") as f:
|
134
|
+
fcntl.flock(f.fileno(), fcntl.LOCK_EX)
|
135
|
+
try:
|
136
|
+
f.write(json.dumps(execution_record) + "\n")
|
137
|
+
finally:
|
138
|
+
fcntl.flock(f.fileno(), fcntl.LOCK_UN)
|
139
|
+
except Exception as e:
|
140
|
+
# Log warning but don't fail the execution
|
141
|
+
logger.warning(f"Failed to log play execution to {log_file}: {e}")
|
142
|
+
|
143
|
+
|
33
144
|
def run_ansible_in_environment(
|
34
145
|
request_id,
|
35
146
|
worker,
|
@@ -41,6 +152,7 @@ def run_ansible_in_environment(
|
|
41
152
|
auto_release_time=3600,
|
42
153
|
):
|
43
154
|
result = ""
|
155
|
+
extracted_hosts = set() # Local set for host deduplication
|
44
156
|
|
45
157
|
if type(arguments) == list:
|
46
158
|
joined_arguments = " ".join(arguments)
|
@@ -73,6 +185,17 @@ def run_ansible_in_environment(
|
|
73
185
|
if ansible_vault_password:
|
74
186
|
env["VAULT"] = "/ansible-vault.py"
|
75
187
|
|
188
|
+
# Log play execution start
|
189
|
+
log_play_execution(
|
190
|
+
request_id=request_id,
|
191
|
+
worker=worker,
|
192
|
+
environment=environment,
|
193
|
+
role=role,
|
194
|
+
hosts=None, # Hosts will be empty at start, filled at completion
|
195
|
+
arguments=joined_arguments,
|
196
|
+
result="started",
|
197
|
+
)
|
198
|
+
|
76
199
|
# NOTE: Consider arguments in the future
|
77
200
|
if locking:
|
78
201
|
lock = utils.create_redlock(
|
@@ -110,8 +233,8 @@ def run_ansible_in_environment(
|
|
110
233
|
env=env,
|
111
234
|
)
|
112
235
|
|
113
|
-
# execute roles from kubernetes
|
114
|
-
elif worker == "kubernetes":
|
236
|
+
# execute roles from osism-kubernetes
|
237
|
+
elif worker == "osism-kubernetes":
|
115
238
|
if locking:
|
116
239
|
lock.acquire()
|
117
240
|
|
@@ -157,12 +280,30 @@ def run_ansible_in_environment(
|
|
157
280
|
|
158
281
|
while p.poll() is None:
|
159
282
|
line = p.stdout.readline().decode("utf-8")
|
283
|
+
|
284
|
+
# Extract hosts from Ansible output
|
285
|
+
match = HOST_PATTERN.match(line.strip())
|
286
|
+
if match:
|
287
|
+
hostname = match.group(2)
|
288
|
+
extracted_hosts.add(hostname) # Local set (automatic deduplication)
|
289
|
+
|
160
290
|
if publish:
|
161
291
|
utils.push_task_output(request_id, line)
|
162
292
|
result += line
|
163
293
|
|
164
294
|
rc = p.wait(timeout=60)
|
165
295
|
|
296
|
+
# Log play execution result
|
297
|
+
log_play_execution(
|
298
|
+
request_id=request_id,
|
299
|
+
worker=worker,
|
300
|
+
environment=environment,
|
301
|
+
role=role,
|
302
|
+
hosts=sorted(list(extracted_hosts)), # Direct pass of extracted hosts
|
303
|
+
arguments=joined_arguments,
|
304
|
+
result="success" if rc == 0 else "failure",
|
305
|
+
)
|
306
|
+
|
166
307
|
if publish:
|
167
308
|
utils.finish_task_output(request_id, rc=rc)
|
168
309
|
|
osism/tasks/kubernetes.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: osism
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.20251004.0
|
4
4
|
Summary: OSISM manager interface
|
5
5
|
Home-page: https://github.com/osism/python-osism
|
6
6
|
Author: OSISM GmbH
|
@@ -25,14 +25,14 @@ License-File: AUTHORS
|
|
25
25
|
Requires-Dist: ClusterShell==1.9.3
|
26
26
|
Requires-Dist: GitPython==3.1.45
|
27
27
|
Requires-Dist: Jinja2==3.1.6
|
28
|
-
Requires-Dist: PyYAML==6.0.
|
28
|
+
Requires-Dist: PyYAML==6.0.3
|
29
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.1
|
33
33
|
Requires-Dist: docker==7.1.0
|
34
34
|
Requires-Dist: dtrack-auditor==1.5.0
|
35
|
-
Requires-Dist: fastapi==0.
|
35
|
+
Requires-Dist: fastapi==0.118.0
|
36
36
|
Requires-Dist: flower==2.0.1
|
37
37
|
Requires-Dist: hiredis==3.2.1
|
38
38
|
Requires-Dist: jc==1.25.5
|
@@ -42,7 +42,7 @@ Requires-Dist: kubernetes==33.1.0
|
|
42
42
|
Requires-Dist: loguru==0.7.3
|
43
43
|
Requires-Dist: nbcli==0.10.0.dev2
|
44
44
|
Requires-Dist: openstacksdk==4.7.1
|
45
|
-
Requires-Dist: paramiko==
|
45
|
+
Requires-Dist: paramiko==4.0.0
|
46
46
|
Requires-Dist: pottery==3.0.1
|
47
47
|
Requires-Dist: prompt-toolkit==3.0.52
|
48
48
|
Requires-Dist: pynetbox==7.5.0
|
@@ -53,7 +53,7 @@ Requires-Dist: sqlmodel==0.0.25
|
|
53
53
|
Requires-Dist: sushy==5.7.1
|
54
54
|
Requires-Dist: tabulate==0.9.0
|
55
55
|
Requires-Dist: transitions==0.9.3
|
56
|
-
Requires-Dist: uvicorn[standard]==0.
|
56
|
+
Requires-Dist: uvicorn[standard]==0.37.0
|
57
57
|
Requires-Dist: validators==0.35.0
|
58
58
|
Requires-Dist: watchdog==6.0.0
|
59
59
|
Requires-Dist: websockets==15.0.1
|
@@ -38,12 +38,12 @@ osism/services/__init__.py,sha256=bG7Ffen4LvQtgnYPFEpFccsWs81t4zqqeqn9ZeirH6E,38
|
|
38
38
|
osism/services/event_bridge.py,sha256=roV90o9UgTnwoVbXnPR3muBk04IriVYCO_fewZ46Mq8,12016
|
39
39
|
osism/services/listener.py,sha256=O8Xq5fEEVoNFIgFPE7GqfVqx6C4QkdWhUPUGzODFnws,14211
|
40
40
|
osism/services/websocket_manager.py,sha256=F147kWOg8PAvbVG4aVYQVtK4mFMfPVtHxxYJXaqiAjg,11051
|
41
|
-
osism/tasks/__init__.py,sha256=
|
41
|
+
osism/tasks/__init__.py,sha256=l_a7IfYm_NUn6XOokfJBYjTuMZGyvGHcvDUOMWSeYGo,13814
|
42
42
|
osism/tasks/ansible.py,sha256=wAeFqyY8EavySpOIBSgWwK3HcGXWPZCIVOaSss5irCM,1387
|
43
43
|
osism/tasks/ceph.py,sha256=Zo-92rzbJ9NDH9dbKi_JPWwekO3cYTdbmwAGSwr5l0w,726
|
44
44
|
osism/tasks/conductor.py,sha256=WBLsoPtr0iGUzRGERs0Xt7CMYrnHQVEwNV9qXBssI3s,274
|
45
45
|
osism/tasks/kolla.py,sha256=1p0SZBTYpUvIg09czwUmnMh6LIBhleB6O1WSX1mkmJo,729
|
46
|
-
osism/tasks/kubernetes.py,sha256=
|
46
|
+
osism/tasks/kubernetes.py,sha256=LyFKjtByQryNl67ZgKjnr-csEODDqYf3LvjURf_qhK0,742
|
47
47
|
osism/tasks/netbox.py,sha256=FjEGQUZDzAVqA9cc3eQqaPv5-hPj3iI9lEc9SkuDO7M,6278
|
48
48
|
osism/tasks/openstack.py,sha256=c5PyVlSzn69Xw-nFgUf1cX3a3E_STSCNrIectiDzqPI,14871
|
49
49
|
osism/tasks/reconciler.py,sha256=vlPdOr7nbqggfVMSNez-JHZmKw8L7YmqKQnLF7TOXuQ,2045
|
@@ -65,11 +65,11 @@ osism/tasks/conductor/sonic/interface.py,sha256=M876LHdFqGxUfTizzDusdzvCkDI0vCgq
|
|
65
65
|
osism/tasks/conductor/sonic/sync.py,sha256=fpgsQVwq6Hb7eeDHhLkAqx5BkaK3Ce_m_WvmWEsJyOo,9182
|
66
66
|
osism/utils/__init__.py,sha256=IEr0sR1HKg-QI_u84fs4gMldC6-EPSxvMBh2zMGu5dU,9939
|
67
67
|
osism/utils/ssh.py,sha256=nxeEgwjJWvQCybKDp-NelMeWyODCYpaXFCBchAv4-bg,8691
|
68
|
-
osism-0.
|
69
|
-
osism-0.
|
70
|
-
osism-0.
|
71
|
-
osism-0.
|
72
|
-
osism-0.
|
73
|
-
osism-0.
|
74
|
-
osism-0.
|
75
|
-
osism-0.
|
68
|
+
osism-0.20251004.0.dist-info/licenses/AUTHORS,sha256=oWotd63qsnNR945QLJP9mEXaXNtCMaesfo8ZNuLjwpU,39
|
69
|
+
osism-0.20251004.0.dist-info/licenses/LICENSE,sha256=tAkwu8-AdEyGxGoSvJ2gVmQdcicWw3j1ZZueVV74M-E,11357
|
70
|
+
osism-0.20251004.0.dist-info/METADATA,sha256=AyzRodVxbpGRzpJZM9nl7_8BBf-iAjb25mOWR8sl3UM,2971
|
71
|
+
osism-0.20251004.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
72
|
+
osism-0.20251004.0.dist-info/entry_points.txt,sha256=W45YQ7MJ7BCAPZXl3F6d2FSi6An0moZQbzLn_BwGnRE,4618
|
73
|
+
osism-0.20251004.0.dist-info/pbr.json,sha256=O4D8iZGKdlEwIsuOJIdJnESPh6JYeG__nO6RBvorNPU,47
|
74
|
+
osism-0.20251004.0.dist-info/top_level.txt,sha256=8L8dsI9hcaGHsdnR4k_LN9EM78EhwrXRFHyAryPXZtY,6
|
75
|
+
osism-0.20251004.0.dist-info/RECORD,,
|
@@ -0,0 +1 @@
|
|
1
|
+
Christian Berendt <berendt@osism.tech>
|
@@ -0,0 +1 @@
|
|
1
|
+
{"git_version": "e546bf8", "is_release": false}
|
@@ -1 +0,0 @@
|
|
1
|
-
janhorstmann <horstmann@osism.tech>
|
@@ -1 +0,0 @@
|
|
1
|
-
{"git_version": "6f46bd9", "is_release": false}
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|