osism 0.20250709.0__py3-none-any.whl → 0.20250823.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/openstack.py CHANGED
@@ -65,23 +65,43 @@ def baremetal_node_show(self, node_id_or_name, ignore_missing=False):
65
65
  @app.task(bind=True, name="osism.tasks.openstack.baremetal_node_list")
66
66
  def baremetal_node_list(self):
67
67
  conn = utils.get_openstack_connection()
68
- nodes = conn.baremetal.nodes()
69
- result = []
68
+ result = conn.baremetal.nodes()
69
+ return list(result)
70
70
 
71
- # Simulate the output of the OpenStack CLI with -f json and without --long
72
- for node in nodes:
73
- result.append(
74
- {
75
- "UUID": node.id,
76
- "Name": node.name,
77
- "Instance UUID": node.instance_id,
78
- "Power State": node.power_state,
79
- "Provisioning State": node.provision_state,
80
- "Maintenance": node.is_maintenance,
81
- }
82
- )
83
71
 
84
- return result
72
+ def get_baremetal_nodes():
73
+ """Get all baremetal nodes with their details.
74
+
75
+ This is a generalized function that can be used by both
76
+ CLI commands and API endpoints to retrieve baremetal node information.
77
+
78
+ Returns:
79
+ list: List of dictionaries containing node information
80
+ """
81
+ conn = utils.get_openstack_connection()
82
+ nodes = conn.baremetal.nodes(details=True)
83
+
84
+ # Convert generator to list and extract relevant fields
85
+ node_list = []
86
+ for node in nodes:
87
+ node_info = {
88
+ "uuid": node.get("uuid"),
89
+ "name": node.get("name"),
90
+ "power_state": node.get("power_state"),
91
+ "provision_state": node.get("provision_state"),
92
+ "maintenance": node.get("maintenance"),
93
+ "instance_uuid": node.get("instance_uuid"),
94
+ "driver": node.get("driver"),
95
+ "resource_class": node.get("resource_class"),
96
+ "properties": node.get("properties", {}),
97
+ "extra": node.get("extra", {}),
98
+ "last_error": node.get("last_error"),
99
+ "created_at": node.get("created_at"),
100
+ "updated_at": node.get("updated_at"),
101
+ }
102
+ node_list.append(node_info)
103
+
104
+ return node_list
85
105
 
86
106
 
87
107
  @app.task(bind=True, name="osism.tasks.openstack.baremetal_node_validate")
osism/utils/__init__.py CHANGED
@@ -73,7 +73,7 @@ try:
73
73
  )
74
74
  if (
75
75
  "NETBOX_TOKEN" not in secondary_nb_settings
76
- or not secondary_nb_settings["NETBOX_TOKEN"]
76
+ or not str(secondary_nb_settings["NETBOX_TOKEN"]).strip()
77
77
  ):
78
78
  raise ValueError(
79
79
  "All NETBOX_TOKEN values in the elements of setting NETBOX_SECONDARIES need to be valid NetBox tokens"
@@ -82,7 +82,7 @@ try:
82
82
  secondary_nb_list.append(
83
83
  get_netbox_connection(
84
84
  secondary_nb_settings["NETBOX_URL"],
85
- secondary_nb_settings["NETBOX_TOKEN"],
85
+ str(secondary_nb_settings["NETBOX_TOKEN"]),
86
86
  secondary_nb_settings.get("IGNORE_SSL_ERRORS", True),
87
87
  )
88
88
  )
@@ -109,8 +109,18 @@ def get_ansible_vault_password():
109
109
  f = Fernet(key)
110
110
 
111
111
  encrypted_ansible_vault_password = redis.get("ansible_vault_password")
112
+ if encrypted_ansible_vault_password is None:
113
+ raise ValueError("Ansible vault password is not set in Redis")
114
+
112
115
  ansible_vault_password = f.decrypt(encrypted_ansible_vault_password)
113
- return ansible_vault_password.decode("utf-8")
116
+ password = ansible_vault_password.decode("utf-8")
117
+
118
+ if not password or password.strip() == "":
119
+ raise ValueError(
120
+ "Ansible vault password is empty or contains only whitespace"
121
+ )
122
+
123
+ return password
114
124
  except Exception as exc:
115
125
  logger.error("Unable to get ansible vault password")
116
126
  raise exc
@@ -185,6 +195,29 @@ def finish_task_output(task_id, rc=None):
185
195
  redis.xadd(task_id, {"type": "action", "content": "quit"})
186
196
 
187
197
 
198
+ def revoke_task(task_id):
199
+ """
200
+ Revoke a running Celery task.
201
+
202
+ Args:
203
+ task_id (str): The ID of the task to revoke
204
+
205
+ Returns:
206
+ bool: True if revocation was successful, False otherwise
207
+ """
208
+ try:
209
+ from celery import Celery
210
+ from osism.tasks import Config
211
+
212
+ app = Celery("task")
213
+ app.config_from_object(Config)
214
+ app.control.revoke(task_id, terminate=True)
215
+ return True
216
+ except Exception as e:
217
+ logger.error(f"Failed to revoke task {task_id}: {e}")
218
+ return False
219
+
220
+
188
221
  def create_redlock(key, auto_release_time=3600):
189
222
  """
190
223
  Create a Redlock instance with output suppression during initialization.
osism/utils/ssh.py ADDED
@@ -0,0 +1,250 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+
3
+ import os
4
+ import subprocess
5
+ from typing import List, Optional
6
+ from loguru import logger
7
+
8
+ from osism import utils
9
+
10
+
11
+ def get_host_identifiers(hostname: str) -> List[str]:
12
+ """
13
+ Get all possible host identifiers for SSH known_hosts cleanup.
14
+
15
+ This includes the hostname itself and its resolved IP address
16
+ (both via DNS and Netbox fallback if available).
17
+
18
+ Args:
19
+ hostname: The hostname to get identifiers for
20
+
21
+ Returns:
22
+ List of unique host identifiers (hostname, IPs)
23
+ """
24
+ identifiers = [hostname]
25
+
26
+ # Try DNS resolution first
27
+ try:
28
+ import socket
29
+
30
+ ip_address = socket.gethostbyname(hostname)
31
+ if ip_address and ip_address not in identifiers:
32
+ identifiers.append(ip_address)
33
+ logger.debug(f"Resolved hostname {hostname} to {ip_address} via DNS")
34
+ except socket.gaierror as e:
35
+ logger.debug(f"DNS resolution failed for {hostname}: {e}")
36
+
37
+ # Try Netbox fallback if available
38
+ if utils.nb:
39
+ try:
40
+ device = utils.nb.dcim.devices.get(name=hostname)
41
+ if device and device.primary_ip4:
42
+ ip_address = str(device.primary_ip4.address).split("/")[0]
43
+ if ip_address and ip_address not in identifiers:
44
+ identifiers.append(ip_address)
45
+ logger.debug(
46
+ f"Found primary IPv4 for {hostname} in Netbox: {ip_address}"
47
+ )
48
+ except Exception as e:
49
+ logger.debug(f"Error querying Netbox for {hostname}: {e}")
50
+
51
+ return identifiers
52
+
53
+
54
+ def remove_known_hosts_entries(
55
+ hostname: str, known_hosts_path: str = "/share/known_hosts"
56
+ ) -> bool:
57
+ """
58
+ Remove SSH known_hosts entries for a given hostname and its IP addresses.
59
+
60
+ This function safely removes entries from the SSH known_hosts file for both
61
+ the hostname and any resolved IP addresses (DNS + Netbox fallback).
62
+
63
+ Args:
64
+ hostname: The hostname to remove entries for
65
+ known_hosts_path: Path to the SSH known_hosts file (default: /share/known_hosts)
66
+
67
+ Returns:
68
+ True if cleanup was successful, False otherwise
69
+ """
70
+ if not hostname or not hostname.strip():
71
+ logger.warning("Empty hostname provided for SSH known_hosts cleanup")
72
+ return False
73
+
74
+ if not os.path.exists(known_hosts_path):
75
+ logger.debug(f"SSH known_hosts file does not exist: {known_hosts_path}")
76
+ return True
77
+
78
+ # Assume ssh-keygen is available (it's a standard SSH tool)
79
+
80
+ # Get all possible host identifiers
81
+ try:
82
+ identifiers = get_host_identifiers(hostname)
83
+ if not identifiers:
84
+ logger.warning(f"No host identifiers found for {hostname}")
85
+ return False
86
+
87
+ logger.info(f"Cleaning SSH known_hosts entries for {hostname}: {identifiers}")
88
+ except Exception as e:
89
+ logger.error(f"Error getting host identifiers for {hostname}: {e}")
90
+ return False
91
+
92
+ success = True
93
+ entries_removed = 0
94
+
95
+ for identifier in identifiers:
96
+ if not identifier or not identifier.strip():
97
+ logger.debug("Skipping empty identifier")
98
+ continue
99
+
100
+ try:
101
+ # Use ssh-keygen to remove entries safely
102
+ # The -R option removes all keys for the specified host
103
+ result = subprocess.run(
104
+ ["ssh-keygen", "-R", identifier, "-f", known_hosts_path],
105
+ capture_output=True,
106
+ text=True,
107
+ timeout=30, # Increased timeout for safety
108
+ )
109
+
110
+ if result.returncode == 0:
111
+ # ssh-keygen returns 0 even if no entries were found
112
+ # Check stderr for messages about entries being updated
113
+ stderr_lower = result.stderr.lower()
114
+ if "updated" in stderr_lower or identifier in stderr_lower:
115
+ entries_removed += 1
116
+ logger.debug(f"Removed SSH known_hosts entries for {identifier}")
117
+ else:
118
+ logger.debug(f"No SSH known_hosts entries found for {identifier}")
119
+ else:
120
+ # Log stderr for debugging but don't fail entirely
121
+ logger.warning(
122
+ f"ssh-keygen returned non-zero exit code for {identifier}: {result.stderr.strip()}"
123
+ )
124
+
125
+ except subprocess.TimeoutExpired:
126
+ logger.error(
127
+ f"Timeout while removing SSH known_hosts entries for {identifier}"
128
+ )
129
+ success = False
130
+ except subprocess.CalledProcessError as e:
131
+ logger.error(
132
+ f"Error removing SSH known_hosts entries for {identifier}: {e}"
133
+ )
134
+ success = False
135
+ except Exception as e:
136
+ logger.error(
137
+ f"Unexpected error removing SSH known_hosts entries for {identifier}: {e}"
138
+ )
139
+ success = False
140
+
141
+ if entries_removed > 0:
142
+ logger.info(
143
+ f"Successfully cleaned {entries_removed} SSH known_hosts entries for {hostname}"
144
+ )
145
+ else:
146
+ logger.debug(f"No SSH known_hosts entries found to clean for {hostname}")
147
+
148
+ return success
149
+
150
+
151
+ def backup_known_hosts(
152
+ known_hosts_path: str = "/share/known_hosts",
153
+ ) -> Optional[str]:
154
+ """
155
+ Create a backup of the SSH known_hosts file before making changes.
156
+
157
+ Args:
158
+ known_hosts_path: Path to the SSH known_hosts file
159
+
160
+ Returns:
161
+ Path to the backup file if successful, None otherwise
162
+ """
163
+ if not known_hosts_path or not known_hosts_path.strip():
164
+ logger.warning("Empty known_hosts path provided for backup")
165
+ return None
166
+
167
+ if not os.path.exists(known_hosts_path):
168
+ logger.debug(
169
+ f"SSH known_hosts file does not exist, no backup needed: {known_hosts_path}"
170
+ )
171
+ return None
172
+
173
+ try:
174
+ # Check if file is readable
175
+ if not os.access(known_hosts_path, os.R_OK):
176
+ logger.warning(f"SSH known_hosts file is not readable: {known_hosts_path}")
177
+ return None
178
+
179
+ # Create backup with timestamp
180
+ import datetime
181
+
182
+ timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
183
+ backup_path = f"{known_hosts_path}.backup_{timestamp}"
184
+
185
+ # Ensure backup directory exists and is writable
186
+ backup_dir = os.path.dirname(backup_path)
187
+ if not os.path.exists(backup_dir):
188
+ logger.warning(f"Backup directory does not exist: {backup_dir}")
189
+ return None
190
+
191
+ if not os.access(backup_dir, os.W_OK):
192
+ logger.warning(f"Backup directory is not writable: {backup_dir}")
193
+ return None
194
+
195
+ # Copy the file
196
+ import shutil
197
+
198
+ shutil.copy2(known_hosts_path, backup_path)
199
+
200
+ # Verify backup was created successfully
201
+ if os.path.exists(backup_path) and os.path.getsize(backup_path) > 0:
202
+ logger.debug(f"Created SSH known_hosts backup: {backup_path}")
203
+ return backup_path
204
+ else:
205
+ logger.warning(f"Backup file was not created properly: {backup_path}")
206
+ return None
207
+
208
+ except PermissionError as e:
209
+ logger.warning(f"Permission denied creating SSH known_hosts backup: {e}")
210
+ return None
211
+ except OSError as e:
212
+ logger.warning(f"OS error creating SSH known_hosts backup: {e}")
213
+ return None
214
+ except Exception as e:
215
+ logger.warning(f"Unexpected error creating SSH known_hosts backup: {e}")
216
+ return None
217
+
218
+
219
+ def cleanup_ssh_known_hosts_for_node(hostname: str, create_backup: bool = True) -> bool:
220
+ """
221
+ High-level function to clean up SSH known_hosts entries for a node.
222
+
223
+ This is the main function that should be called from reset/undeploy commands.
224
+ It optionally creates a backup and then removes all SSH known_hosts entries
225
+ for the specified hostname and its IP addresses.
226
+
227
+ Args:
228
+ hostname: The hostname/node name to clean up entries for
229
+ create_backup: Whether to create a backup before cleanup (default: True)
230
+
231
+ Returns:
232
+ True if cleanup was successful, False otherwise
233
+ """
234
+ known_hosts_path = "/share/known_hosts"
235
+
236
+ try:
237
+ # Create backup if requested
238
+ if create_backup:
239
+ backup_path = backup_known_hosts(known_hosts_path)
240
+ if backup_path:
241
+ logger.debug(f"SSH known_hosts backup created: {backup_path}")
242
+
243
+ # Perform the cleanup
244
+ success = remove_known_hosts_entries(hostname, known_hosts_path)
245
+
246
+ return success
247
+
248
+ except Exception as e:
249
+ logger.error(f"Error during SSH known_hosts cleanup for {hostname}: {e}")
250
+ return False
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: osism
3
- Version: 0.20250709.0
3
+ Version: 0.20250823.0
4
4
  Summary: OSISM manager interface
5
5
  Home-page: https://github.com/osism/python-osism
6
6
  Author: OSISM GmbH
@@ -23,25 +23,25 @@ Description-Content-Type: text/markdown
23
23
  License-File: LICENSE
24
24
  License-File: AUTHORS
25
25
  Requires-Dist: ClusterShell==1.9.3
26
- Requires-Dist: GitPython==3.1.44
26
+ Requires-Dist: GitPython==3.1.45
27
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.5.3
31
- Requires-Dist: cliff==4.10.0
32
- Requires-Dist: deepdiff==8.5.0
31
+ Requires-Dist: cliff==4.11.0
32
+ Requires-Dist: deepdiff==8.6.0
33
33
  Requires-Dist: docker==7.1.0
34
34
  Requires-Dist: dtrack-auditor==1.5.0
35
- Requires-Dist: fastapi==0.116.0
35
+ Requires-Dist: fastapi==0.116.1
36
36
  Requires-Dist: flower==2.0.1
37
37
  Requires-Dist: hiredis==3.2.1
38
38
  Requires-Dist: jc==1.25.5
39
- Requires-Dist: keystoneauth1==5.11.1
39
+ Requires-Dist: keystoneauth1==5.12.0
40
40
  Requires-Dist: kombu==5.5.4
41
41
  Requires-Dist: kubernetes==33.1.0
42
42
  Requires-Dist: loguru==0.7.3
43
43
  Requires-Dist: nbcli==0.10.0.dev2
44
- Requires-Dist: openstacksdk==4.6.0
44
+ Requires-Dist: openstacksdk==4.7.0
45
45
  Requires-Dist: paramiko==3.5.1
46
46
  Requires-Dist: pottery==3.0.1
47
47
  Requires-Dist: prompt-toolkit==3.0.51
@@ -50,7 +50,7 @@ Requires-Dist: pytest-testinfra==10.2.2
50
50
  Requires-Dist: python-dateutil==2.9.0.post0
51
51
  Requires-Dist: setuptools==80.9.0
52
52
  Requires-Dist: sqlmodel==0.0.24
53
- Requires-Dist: sushy==5.6.0
53
+ Requires-Dist: sushy==5.7.1
54
54
  Requires-Dist: tabulate==0.9.0
55
55
  Requires-Dist: transitions==0.9.3
56
56
  Requires-Dist: uvicorn[standard]==0.35.0
@@ -58,7 +58,7 @@ Requires-Dist: validators==0.35.0
58
58
  Requires-Dist: watchdog==6.0.0
59
59
  Provides-Extra: ansible
60
60
  Requires-Dist: ansible-runner==2.4.1; extra == "ansible"
61
- Requires-Dist: ansible-core==2.18.6; extra == "ansible"
61
+ Requires-Dist: ansible-core==2.19.0; extra == "ansible"
62
62
  Provides-Extra: openstack-image-manager
63
63
  Requires-Dist: openstack-image-manager==0.20250508.0; extra == "openstack-image-manager"
64
64
  Dynamic: author
@@ -1,27 +1,27 @@
1
1
  osism/__init__.py,sha256=1UiNTBus0V0f2AbZQzAtVtu6zkfCCrw0OTq--NwFAqY,341
2
2
  osism/__main__.py,sha256=ILe4gu61xEISiBsxanqTQIdSkV-YhpZXTRlguCYyssk,141
3
- osism/api.py,sha256=7BKVedr3aK8QSRf4ZI1WpraYivibimx-SqVKVAzD6bw,11070
3
+ osism/api.py,sha256=hhRgBswe3Tem6eTMor54PttNhBhAts2AEDBsxQfqRyU,13363
4
4
  osism/main.py,sha256=Dt2-9sLXcS-Ny4DAz7hrha-KRc7zd7BFUTRdfs_X8z4,893
5
- osism/settings.py,sha256=IUbUo8kru8TeiMAnnil5oHwd8SqbkPCY401dVONMygo,1885
5
+ osism/settings.py,sha256=VZT1muZVYWM5Ov1eFRC7a4ZGYIdI2AFmudCm0wZ1C2Q,1898
6
6
  osism/commands/__init__.py,sha256=Ag4wX_DCgXRdoLn6t069jqb3DdRylsX2nyYkiyCx4uk,456
7
7
  osism/commands/apply.py,sha256=GWUccZAXlgkPYqylrCmdWcj8FCkDsPEipIIG937MeII,16833
8
- osism/commands/baremetal.py,sha256=yxCb0UwBfERinoGvlD9bvsGPEdDcHhq48Mn6u5b2aM8,12037
9
- osism/commands/compose.py,sha256=iqzG7mS9E1VWaLNN6yQowjOqiHn3BMdj-yfXb3Dc4Ok,1200
8
+ osism/commands/baremetal.py,sha256=TeXwg4lYfxel0YkWC3z8bv9qTsJQmsI2QD6u1K4vhIM,24821
9
+ osism/commands/compose.py,sha256=76HL9wzTJ7bFPhZk-uyfWq0n6Z74lOHn4RE0zzkHgYE,1241
10
10
  osism/commands/compute.py,sha256=cgqXWJa5wAvn-7e3FWCgX6hie_aK0yrKRkcNzjLXwDY,25799
11
11
  osism/commands/configuration.py,sha256=sPe8b0dVKFRbr30xoeVdAnHbGwCwgUh0xa_Vzv5pSQQ,954
12
- osism/commands/console.py,sha256=8BPz1hio5Wi6kONVAWFuSqkDRrMcLEYeFIY8dbtN6e4,3218
13
- osism/commands/container.py,sha256=Fku2GaCM3Idq_FxExUtNqjrEM0XYjpVvXmueSVO8S_c,1601
12
+ osism/commands/console.py,sha256=0BSDKewPGAwWAJwi_WrFZ_dRMbMQzbG6IS_0gVi88J8,6276
13
+ osism/commands/container.py,sha256=jHk5A0PXBzHGIm-1d5HQZI_POANAq7An1lZGRbqBvr0,1642
14
14
  osism/commands/get.py,sha256=ryytjtXWmlMV0NucP5tGkMZu0nIlC4xVtjRk4iMZ06c,8967
15
- osism/commands/log.py,sha256=2IpYuosC7FZwwLvM8HmKSU1NRNIelVVYzqjjVMCrOJk,4072
15
+ osism/commands/log.py,sha256=QnnTTNiAoa8oj4kDOcggh0QrRAD6onxcEpLXBy7CvDg,4113
16
16
  osism/commands/manage.py,sha256=FaO9dbYjNHYanS98-zC498bx26oU8E3loxCczH9mfKI,12751
17
- osism/commands/netbox.py,sha256=e65P0kWrjTLw2T9HZthxjDTIRa-KAHgSSJAlvVef7n4,7345
17
+ osism/commands/netbox.py,sha256=gqXet5jHIRKFtHkbd6pQ0071jHe4r5c7DFnZWkT_lNQ,8275
18
18
  osism/commands/noset.py,sha256=7zDFuFMyNpo7DUOKcNiYV8nodtdMOYFp5LDPcuJhlZ8,1481
19
19
  osism/commands/reconciler.py,sha256=ubQfX8j13s3NuMKnT0Lt6O-szf7Z1V02AfsMQFHmO74,2209
20
20
  osism/commands/redfish.py,sha256=oBfxd5UBX4ED8XulEuIYziIYQqTvUKpKfcdGyg_AoiI,8431
21
21
  osism/commands/server.py,sha256=avmoOv5rjOi-fN2A-27cPwOtiy2Q2j6UFtCh3QrfWAI,7512
22
22
  osism/commands/service.py,sha256=A1lgAlGeCJpbFFqF55DRWPcCirIgpU0dzjzVLZ0mz3k,2649
23
23
  osism/commands/set.py,sha256=xLBi2DzbVQo2jb3-cOIE9In5UB3vFxquQJkDN-EsfhM,1425
24
- osism/commands/sonic.py,sha256=siuYUIlLfNuCKe9BLZ_9Pj2FkzcUCxusBOyaFnwiIF0,35303
24
+ osism/commands/sonic.py,sha256=H_KyMVUgXhiCjZ3T1VW9IzM-8yiRjhgj-JzzvgY9mSE,43622
25
25
  osism/commands/status.py,sha256=X-Rcj-XuNPDBoxsGkf96NswwpmTognxz1V6E2NX2ZgY,1997
26
26
  osism/commands/sync.py,sha256=jOg-g8NmVOkXBI6rOuiOx2WgUJc1PplLAAAwc0VuIfw,1919
27
27
  osism/commands/task.py,sha256=mwJJ7a71Lw3o_FX7j3rR0-NbPdPwMDOjbOAiiXE4uGc,543
@@ -35,37 +35,38 @@ osism/data/enums.py,sha256=gItIjOK6xWuOZSkMxpMdYLRyt4ezyhzkqA7BGiah2o0,10030
35
35
  osism/data/playbooks.py,sha256=M3T3ajV-8Lt-orsRO3jAoukhaoYFr4EZ2dzYXQjt1kg,728
36
36
  osism/services/__init__.py,sha256=bG7Ffen4LvQtgnYPFEpFccsWs81t4zqqeqn9ZeirH6E,38
37
37
  osism/services/listener.py,sha256=Vf8LOZkHzlspm40BZ1az3o1O_ar34_i6C83p-D8KzzM,9783
38
- osism/tasks/__init__.py,sha256=XZhUQLamrS0ikRkYNCxv-H8KQ0I51Uda7fq6botVpXo,6998
38
+ osism/tasks/__init__.py,sha256=iAUs-ttUMw1nZElL631sT1ke29RvTjQjlhWPl_kGrEw,9003
39
39
  osism/tasks/ansible.py,sha256=-gUe6uZFhPLI3DGZHlpQlghuDKpp4Drn5IEctlV6Sv8,1300
40
40
  osism/tasks/ceph.py,sha256=eIQkah3Kj4INtOkF9kTjHbXJ3_J2lg48EWJKfHc-UYw,615
41
41
  osism/tasks/conductor.py,sha256=WBLsoPtr0iGUzRGERs0Xt7CMYrnHQVEwNV9qXBssI3s,274
42
42
  osism/tasks/kolla.py,sha256=wJQpWn_01iWLkr7l7T7RNrQGfRgsgmYi4WQlTmNGvew,618
43
43
  osism/tasks/kubernetes.py,sha256=VzXq_VrYU_CLm4cOruqnE3Kq2ydfO9glZ3p0bp3OYoc,625
44
44
  osism/tasks/netbox.py,sha256=QGQGz3s0V8WvPvhEJWwo0H24aLFaZrSl-voN-axzRwY,5846
45
- osism/tasks/openstack.py,sha256=g15tCll5vP1pC6ysxRCTZxplsdGmXbxaCH3k1Qdv5Xg,6367
45
+ osism/tasks/openstack.py,sha256=VeNfEcv4JHx_oJxpAb2QO2adlk--hlSqo_2iVQbOtpE,7142
46
46
  osism/tasks/reconciler.py,sha256=PnGWfvfmomzbgddvyCdxul-z5ZLXxWAmrQyRCN874-s,1958
47
- osism/tasks/conductor/__init__.py,sha256=HW8CXpZOQ6aNgLZ3Ck08YcfQfueoA0ce35Kolh0rWww,1903
48
- osism/tasks/conductor/config.py,sha256=tMI0dtEFSWxfueRZdvocpbEq0sIN_PnXG08CuATkPz4,4489
49
- osism/tasks/conductor/ironic.py,sha256=LyUm9xk1oqjarRona2UVodMO7clIt2sqtiW76elqEak,15352
50
- osism/tasks/conductor/netbox.py,sha256=5Nc7wrriDOtSuru1KDLt9QpA54vC7tXDPB2J0JP9GKo,11393
47
+ osism/tasks/conductor/__init__.py,sha256=eAiaM69sVbTTDam7gCLyjF7wBCt7rd__pRFu7VdY-f8,1930
48
+ osism/tasks/conductor/config.py,sha256=n1H9_8DY90p5E4mygzKyJUl8G3WdDuGHFTp-SrmZmgU,4543
49
+ osism/tasks/conductor/ironic.py,sha256=sxUHAzs8_Z-IaB5ZZ0ufObWiytBKiptPUWoIGWo2wcY,16440
50
+ osism/tasks/conductor/netbox.py,sha256=xPJn-tXLqTAgW3v6L9rQ__XGHhM7ErchnyfsLY6iH14,13381
51
51
  osism/tasks/conductor/redfish.py,sha256=hOOS-_l3Qmo_6vLsgjZmJwTxLTf029hhFRVkU0TMLL0,12723
52
- osism/tasks/conductor/utils.py,sha256=ZSbQumQr-uL-B9XOwbsscLIX7czJHu6Mq0t_poRpMsw,7769
52
+ osism/tasks/conductor/utils.py,sha256=-vHsyi0Adlk8qdoZkhM2kUwG7DqwwZZVE0JGK5Z92mI,8127
53
53
  osism/tasks/conductor/sonic/__init__.py,sha256=oxTTl_MGK4iWK9uNDRNlULtGrDGCQHrlJZ04weh_Lh8,777
54
54
  osism/tasks/conductor/sonic/bgp.py,sha256=PC6gGI5bCj2PCXcNGyMV9-EdlJWDsYaodzxigmYSZvw,3088
55
55
  osism/tasks/conductor/sonic/cache.py,sha256=Asv2k3nLJejuq7iB0a_LyK8dEmJzypP9v3OHkNY3GwI,3438
56
- osism/tasks/conductor/sonic/config_generator.py,sha256=_B001d6YdhLjAl61WGhlF2xyMXvcyJv0TQ16zuzJjB8,40117
57
- osism/tasks/conductor/sonic/connections.py,sha256=NvRjwJv3NF3ry5Xe9qHzk7pQbfDQHYx_j3ATRMUs7gA,14244
56
+ osism/tasks/conductor/sonic/config_generator.py,sha256=U9tFNdJsZIdk-lzbkodXiWmK4FJq0FplBKKKuP7R27o,53269
57
+ osism/tasks/conductor/sonic/connections.py,sha256=MU3u7HRG42dDlKL5GMruDVSvVl6AUXEf_WivfYdFURE,19297
58
58
  osism/tasks/conductor/sonic/constants.py,sha256=HjVFwmH-AN3np1qN97ahEAcwz2-4cHa-pA9pXWqWsqs,2219
59
59
  osism/tasks/conductor/sonic/device.py,sha256=ZYJA0bQ8waKWStzWUPxbcwNWa2Z_hMB3pqs8aA_nxXA,2458
60
60
  osism/tasks/conductor/sonic/exporter.py,sha256=25L1vbi84ZQD0xNHNTWk-anTz5QRkGJskCECBkeGQw4,8882
61
- osism/tasks/conductor/sonic/interface.py,sha256=318wOwXYSSMKTPP2WSZIps-JvIkCQ2gYdQs9ZYHXwwg,38957
61
+ osism/tasks/conductor/sonic/interface.py,sha256=M876LHdFqGxUfTizzDusdzvCkDI0vCgqte5uLmOXFaY,39472
62
62
  osism/tasks/conductor/sonic/sync.py,sha256=fpgsQVwq6Hb7eeDHhLkAqx5BkaK3Ce_m_WvmWEsJyOo,9182
63
- osism/utils/__init__.py,sha256=cMKOYH8mg9PXnIDoSume1KF3OpELhHWhKYL8ScY0_EY,6903
64
- osism-0.20250709.0.dist-info/licenses/AUTHORS,sha256=oWotd63qsnNR945QLJP9mEXaXNtCMaesfo8ZNuLjwpU,39
65
- osism-0.20250709.0.dist-info/licenses/LICENSE,sha256=tAkwu8-AdEyGxGoSvJ2gVmQdcicWw3j1ZZueVV74M-E,11357
66
- osism-0.20250709.0.dist-info/METADATA,sha256=yodBqt4lzfRfMB1-pdlKX7shsBBy67vdP4Zl8xfHa_c,2937
67
- osism-0.20250709.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
68
- osism-0.20250709.0.dist-info/entry_points.txt,sha256=NlvBIfH7JWQ5xhjcYQeCpQKpP_3RjXxJIW1XK8oYhmk,3802
69
- osism-0.20250709.0.dist-info/pbr.json,sha256=ux-nCNhP6rA-LJ8vLyJsdbbHawfvybH88tJFSPLDB6Q,47
70
- osism-0.20250709.0.dist-info/top_level.txt,sha256=8L8dsI9hcaGHsdnR4k_LN9EM78EhwrXRFHyAryPXZtY,6
71
- osism-0.20250709.0.dist-info/RECORD,,
63
+ osism/utils/__init__.py,sha256=370UHVU5BFy-1wDAxBFaRjSA-zR0KNadJPWQ6zcYRf0,7806
64
+ osism/utils/ssh.py,sha256=nxeEgwjJWvQCybKDp-NelMeWyODCYpaXFCBchAv4-bg,8691
65
+ osism-0.20250823.0.dist-info/licenses/AUTHORS,sha256=EKFIR9F27AvoEXp1cA6FkGbjEOFt4Rcbipr5RJc7jSs,64
66
+ osism-0.20250823.0.dist-info/licenses/LICENSE,sha256=tAkwu8-AdEyGxGoSvJ2gVmQdcicWw3j1ZZueVV74M-E,11357
67
+ osism-0.20250823.0.dist-info/METADATA,sha256=ZwWM7UZEXo9p5LSTB5v65qa2aEt3o7UOi7LNSrjkBXE,2937
68
+ osism-0.20250823.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
69
+ osism-0.20250823.0.dist-info/entry_points.txt,sha256=h9YS3gfPc5ueU9ZXtCc60e8p4NQEuvtIH_zE0cfVqy0,4439
70
+ osism-0.20250823.0.dist-info/pbr.json,sha256=t633u2SKCZHSfZL7F8jKzAb9107KiG9OydBqGXdZPNQ,47
71
+ osism-0.20250823.0.dist-info/top_level.txt,sha256=8L8dsI9hcaGHsdnR4k_LN9EM78EhwrXRFHyAryPXZtY,6
72
+ osism-0.20250823.0.dist-info/RECORD,,
@@ -3,6 +3,11 @@ osism = osism.main:main
3
3
 
4
4
  [osism.commands]
5
5
  apply = osism.commands.apply:Run
6
+ baremetal burnin = osism.commands.baremetal:BaremetalBurnIn
7
+ baremetal deploy = osism.commands.baremetal:BaremetalDeploy
8
+ baremetal list = osism.commands.baremetal:BaremetalList
9
+ baremetal ping = osism.commands.baremetal:BaremetalPing
10
+ baremetal undeploy = osism.commands.baremetal:BaremetalUndeploy
6
11
  compose = osism.commands.compose:Run
7
12
  configuration sync = osism.commands.configuration:Sync
8
13
  console = osism.commands.console:Run
@@ -26,8 +31,12 @@ log ansible = osism.commands.log:Ansible
26
31
  log container = osism.commands.log:Container
27
32
  log file = osism.commands.log:File
28
33
  log opensearch = osism.commands.log:Opensearch
34
+ manage baremetal burnin = osism.commands.baremetal:BaremetalBurnIn
29
35
  manage baremetal deploy = osism.commands.baremetal:BaremetalDeploy
30
36
  manage baremetal list = osism.commands.baremetal:BaremetalList
37
+ manage baremetal maintenance set = osism.commands.baremetal:BaremetalMaintenanceSet
38
+ manage baremetal maintenance unset = osism.commands.baremetal:BaremetalMaintenanceUnset
39
+ manage baremetal ping = osism.commands.baremetal:BaremetalPing
31
40
  manage baremetal undeploy = osism.commands.baremetal:BaremetalUndeploy
32
41
  manage compute disable = osism.commands.compute:ComputeDisable
33
42
  manage compute enable = osism.commands.compute:ComputeEnable
@@ -59,6 +68,7 @@ set maintenance = osism.commands.set:Maintenance
59
68
  set vault password = osism.commands.vault:SetPassword
60
69
  sonic backup = osism.commands.sonic:Backup
61
70
  sonic console = osism.commands.sonic:Console
71
+ sonic list = osism.commands.sonic:List
62
72
  sonic load = osism.commands.sonic:Load
63
73
  sonic reboot = osism.commands.sonic:Reboot
64
74
  sonic reload = osism.commands.sonic:Reload
@@ -0,0 +1 @@
1
+ renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
@@ -0,0 +1 @@
1
+ {"git_version": "eaafb18", "is_release": false}
@@ -1 +0,0 @@
1
- Christian Berendt <berendt@osism.tech>
@@ -1 +0,0 @@
1
- {"git_version": "ed8c436", "is_release": false}