osism 0.20250605.0__py3-none-any.whl → 0.20250621.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.
Files changed (36) hide show
  1. osism/commands/baremetal.py +71 -10
  2. osism/commands/manage.py +25 -1
  3. osism/commands/netbox.py +22 -5
  4. osism/commands/reconciler.py +6 -28
  5. osism/commands/sync.py +48 -1
  6. osism/commands/validate.py +7 -30
  7. osism/commands/wait.py +8 -31
  8. osism/services/listener.py +1 -1
  9. osism/settings.py +13 -2
  10. osism/tasks/__init__.py +8 -40
  11. osism/tasks/conductor/__init__.py +8 -1
  12. osism/tasks/conductor/ironic.py +90 -66
  13. osism/tasks/conductor/netbox.py +267 -6
  14. osism/tasks/conductor/sonic/__init__.py +26 -0
  15. osism/tasks/conductor/sonic/bgp.py +87 -0
  16. osism/tasks/conductor/sonic/cache.py +114 -0
  17. osism/tasks/conductor/sonic/config_generator.py +908 -0
  18. osism/tasks/conductor/sonic/connections.py +389 -0
  19. osism/tasks/conductor/sonic/constants.py +79 -0
  20. osism/tasks/conductor/sonic/device.py +82 -0
  21. osism/tasks/conductor/sonic/exporter.py +226 -0
  22. osism/tasks/conductor/sonic/interface.py +789 -0
  23. osism/tasks/conductor/sonic/sync.py +190 -0
  24. osism/tasks/conductor.py +2 -0
  25. osism/tasks/netbox.py +6 -4
  26. osism/tasks/reconciler.py +4 -5
  27. osism/utils/__init__.py +51 -4
  28. {osism-0.20250605.0.dist-info → osism-0.20250621.0.dist-info}/METADATA +4 -4
  29. {osism-0.20250605.0.dist-info → osism-0.20250621.0.dist-info}/RECORD +35 -25
  30. {osism-0.20250605.0.dist-info → osism-0.20250621.0.dist-info}/entry_points.txt +5 -0
  31. osism-0.20250621.0.dist-info/pbr.json +1 -0
  32. osism-0.20250605.0.dist-info/pbr.json +0 -1
  33. {osism-0.20250605.0.dist-info → osism-0.20250621.0.dist-info}/WHEEL +0 -0
  34. {osism-0.20250605.0.dist-info → osism-0.20250621.0.dist-info}/licenses/AUTHORS +0 -0
  35. {osism-0.20250605.0.dist-info → osism-0.20250621.0.dist-info}/licenses/LICENSE +0 -0
  36. {osism-0.20250605.0.dist-info → osism-0.20250621.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,190 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+
3
+ """Main SONiC synchronization function."""
4
+
5
+ from loguru import logger
6
+
7
+ from osism import utils
8
+ from osism.tasks.conductor.netbox import get_nb_device_query_list_sonic
9
+ from .bgp import calculate_minimum_as_for_group
10
+ from .connections import find_interconnected_devices
11
+ from .config_generator import generate_sonic_config, clear_all_caches
12
+ from .constants import DEFAULT_SONIC_ROLES, SUPPORTED_HWSKUS
13
+ from .exporter import save_config_to_netbox, export_config_to_file
14
+ from .cache import clear_interface_cache, get_interface_cache_stats
15
+
16
+
17
+ def sync_sonic(device_name=None, task_id=None, show_diff=True):
18
+ """Sync SONiC configurations for eligible devices.
19
+
20
+ Args:
21
+ device_name (str, optional): Name of specific device to sync. If None, sync all eligible devices.
22
+ task_id (str, optional): Task ID for output logging.
23
+ show_diff (bool, optional): Whether to show diffs when changes are detected. Defaults to True.
24
+
25
+ Returns:
26
+ dict: Dictionary with device names as keys and their SONiC configs as values
27
+ """
28
+ if device_name:
29
+ logger.info(f"Preparing SONIC configuration for device: {device_name}")
30
+ else:
31
+ logger.info("Preparing SONIC configuration files")
32
+
33
+ # Clear all caches at start of sync
34
+ clear_interface_cache()
35
+ clear_all_caches()
36
+ logger.debug("Initialized all caches for sync_sonic task")
37
+
38
+ # Dictionary to store configurations for all devices
39
+ device_configs = {}
40
+
41
+ logger.debug(f"Supported HWSKUs: {', '.join(SUPPORTED_HWSKUS)}")
42
+
43
+ devices = []
44
+
45
+ if device_name:
46
+ # When specific device is requested, fetch it directly
47
+ try:
48
+ device = utils.nb.dcim.devices.get(name=device_name)
49
+ if device:
50
+ # Check if device role matches allowed roles
51
+ if device.role and device.role.slug in DEFAULT_SONIC_ROLES:
52
+ devices.append(device)
53
+ logger.debug(
54
+ f"Found device: {device.name} with role: {device.role.slug}"
55
+ )
56
+ else:
57
+ logger.warning(
58
+ f"Device {device_name} has role '{device.role.slug if device.role else 'None'}' "
59
+ f"which is not in allowed SONiC roles: {', '.join(DEFAULT_SONIC_ROLES)}"
60
+ )
61
+ return device_configs
62
+ else:
63
+ logger.error(f"Device {device_name} not found in NetBox")
64
+ return device_configs
65
+ except Exception as e:
66
+ logger.error(f"Error fetching device {device_name}: {e}")
67
+ return device_configs
68
+ else:
69
+ # Get device query list from NETBOX_FILTER_CONDUCTOR_SONIC
70
+ nb_device_query_list = get_nb_device_query_list_sonic()
71
+
72
+ for nb_device_query in nb_device_query_list:
73
+ # Query devices with the NETBOX_FILTER_CONDUCTOR_SONIC criteria
74
+ for device in utils.nb.dcim.devices.filter(**nb_device_query):
75
+ # Check if device role matches allowed roles
76
+ if device.role and device.role.slug in DEFAULT_SONIC_ROLES:
77
+ devices.append(device)
78
+ logger.debug(
79
+ f"Found device: {device.name} with role: {device.role.slug}"
80
+ )
81
+
82
+ logger.info(f"Found {len(devices)} devices matching criteria")
83
+
84
+ # Find interconnected spine/superspine groups for special AS calculation
85
+ spine_groups = find_interconnected_devices(devices, ["spine", "superspine"])
86
+ logger.info(f"Found {len(spine_groups)} interconnected spine/superspine groups")
87
+
88
+ # Create mapping from device ID to its assigned AS number
89
+ device_as_mapping = {}
90
+
91
+ # Calculate AS numbers for spine/superspine groups
92
+ for group in spine_groups:
93
+ min_as = calculate_minimum_as_for_group(group)
94
+ if min_as:
95
+ for device in group:
96
+ device_as_mapping[device.id] = min_as
97
+ logger.debug(
98
+ f"Assigned AS {min_as} to {len(group)} devices in spine/superspine group"
99
+ )
100
+
101
+ # Generate SONIC configuration for each device
102
+ for device in devices:
103
+ # Get HWSKU from sonic_parameters custom field, default to None
104
+ hwsku = None
105
+ if (
106
+ hasattr(device, "custom_fields")
107
+ and "sonic_parameters" in device.custom_fields
108
+ and device.custom_fields["sonic_parameters"]
109
+ and "hwsku" in device.custom_fields["sonic_parameters"]
110
+ ):
111
+ hwsku = device.custom_fields["sonic_parameters"]["hwsku"]
112
+
113
+ # Skip devices without HWSKU
114
+ if not hwsku:
115
+ logger.debug(f"Skipping device {device.name}: no HWSKU configured")
116
+ continue
117
+
118
+ logger.debug(f"Processing device: {device.name} with HWSKU: {hwsku}")
119
+
120
+ # Output current device being processed if task_id is available
121
+ if task_id:
122
+ utils.push_task_output(task_id, f"Processing device: {device.name}\n")
123
+
124
+ # Validate that HWSKU is supported
125
+ if hwsku not in SUPPORTED_HWSKUS:
126
+ logger.warning(
127
+ f"Device {device.name} has unsupported HWSKU: {hwsku}. Supported HWSKUs: {', '.join(SUPPORTED_HWSKUS)}"
128
+ )
129
+ continue
130
+
131
+ # Generate SONIC configuration based on device HWSKU
132
+ sonic_config = generate_sonic_config(device, hwsku, device_as_mapping)
133
+
134
+ # Store configuration in the dictionary
135
+ device_configs[device.name] = sonic_config
136
+
137
+ # Save the generated configuration to NetBox config context (only if changed)
138
+ if show_diff:
139
+ netbox_changed, diff_output = save_config_to_netbox(
140
+ device, sonic_config, return_diff=True
141
+ )
142
+
143
+ # Output diff to task if available and there are changes
144
+ if task_id and netbox_changed and diff_output:
145
+ utils.push_task_output(task_id, f"\n{'='*60}\n")
146
+ utils.push_task_output(
147
+ task_id, f"Configuration diff for {device.name}:\n"
148
+ )
149
+ utils.push_task_output(task_id, f"{'='*60}\n")
150
+ utils.push_task_output(task_id, f"{diff_output}\n")
151
+ utils.push_task_output(task_id, f"{'='*60}\n\n")
152
+ elif task_id and netbox_changed and not diff_output:
153
+ # First-time configuration (no diff available)
154
+ utils.push_task_output(
155
+ task_id, f"First-time configuration created for {device.name}\n"
156
+ )
157
+ else:
158
+ netbox_changed = save_config_to_netbox(device, sonic_config)
159
+
160
+ # Export the generated configuration to local file (only if changed)
161
+ file_changed = export_config_to_file(device, sonic_config)
162
+
163
+ if netbox_changed or file_changed:
164
+ logger.info(f"Configuration updated for device {device.name}")
165
+ else:
166
+ logger.info(f"No configuration changes for device {device.name}")
167
+
168
+ logger.info(
169
+ f"Generated SONiC config for device {device.name} with {len(sonic_config['PORT'])} ports"
170
+ )
171
+
172
+ logger.info(f"Generated SONiC configurations for {len(device_configs)} devices")
173
+
174
+ # Log cache statistics and cleanup
175
+ cache_stats = get_interface_cache_stats()
176
+ if cache_stats:
177
+ logger.debug(
178
+ f"Interface cache stats: {cache_stats['cached_devices']} devices, {cache_stats['total_interfaces']} interfaces"
179
+ )
180
+
181
+ clear_interface_cache()
182
+ clear_all_caches()
183
+ logger.debug("Cleared all caches after sync_sonic task completion")
184
+
185
+ # Finish task output if task_id is available
186
+ if task_id:
187
+ utils.finish_task_output(task_id, rc=0)
188
+
189
+ # Return the dictionary with all device configurations
190
+ return device_configs
osism/tasks/conductor.py CHANGED
@@ -5,6 +5,7 @@ from osism.tasks.conductor import (
5
5
  get_ironic_parameters,
6
6
  sync_netbox,
7
7
  sync_ironic,
8
+ sync_sonic,
8
9
  )
9
10
 
10
11
  __all__ = [
@@ -12,4 +13,5 @@ __all__ = [
12
13
  "get_ironic_parameters",
13
14
  "sync_netbox",
14
15
  "sync_ironic",
16
+ "sync_sonic",
15
17
  ]
osism/tasks/netbox.py CHANGED
@@ -21,12 +21,14 @@ def run(self, action, arguments):
21
21
  pass
22
22
 
23
23
 
24
- # NOTE: While `get_*` tasks only operate on the netbox configured in NETBOX_URL, `set_*` tasks additionally operate on all netbox instances listed in NETBOX_SECONDARIES
24
+ # NOTE: While `get_*` tasks only operate on the NetBox configured in NETBOX_URL,
25
+ # `set_*` tasks additionally operate on all NetBox instances listed in
26
+ # NETBOX_SECONDARIES
25
27
 
26
28
 
27
29
  @app.task(bind=True, name="osism.tasks.netbox.set_maintenance")
28
30
  def set_maintenance(self, device_name, state=True):
29
- """Set the maintenance state for a device in the Netbox."""
31
+ """Set the maintenance state for a device in the NetBox."""
30
32
 
31
33
  lock = Redlock(
32
34
  key=f"lock_osism_tasks_netbox_set_maintenance_{device_name}",
@@ -55,7 +57,7 @@ def set_maintenance(self, device_name, state=True):
55
57
 
56
58
  @app.task(bind=True, name="osism.tasks.netbox.set_provision_state")
57
59
  def set_provision_state(self, device_name, state):
58
- """Set the provision state for a device in the Netbox."""
60
+ """Set the provision state for a device in the NetBox."""
59
61
 
60
62
  lock = Redlock(
61
63
  key=f"lock_osism_tasks_netbox_set_provision_state_{device_name}",
@@ -85,7 +87,7 @@ def set_provision_state(self, device_name, state):
85
87
 
86
88
  @app.task(bind=True, name="osism.tasks.netbox.set_power_state")
87
89
  def set_power_state(self, device_name, state):
88
- """Set the provision state for a device in the Netbox."""
90
+ """Set the provision state for a device in the NetBox."""
89
91
 
90
92
  lock = Redlock(
91
93
  key=f"lock_osism_tasks_netbox_set_provision_state_{device_name}",
osism/tasks/reconciler.py CHANGED
@@ -40,15 +40,14 @@ def run(self, publish=True):
40
40
  "/run.sh", shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT
41
41
  )
42
42
 
43
- for line in io.TextIOWrapper(p.stdout, encoding="utf-8"):
44
- if publish:
45
- utils.redis.xadd(self.request.id, {"type": "stdout", "content": line})
43
+ if publish:
44
+ for line in io.TextIOWrapper(p.stdout, encoding="utf-8"):
45
+ utils.push_task_output(self.request.id, line)
46
46
 
47
47
  rc = p.wait(timeout=60)
48
48
 
49
49
  if publish:
50
- utils.redis.xadd(self.request.id, {"type": "rc", "content": rc})
51
- utils.redis.xadd(self.request.id, {"type": "action", "content": "quit"})
50
+ utils.finish_task_output(self.request.id, rc=rc)
52
51
 
53
52
  lock.release()
54
53
 
osism/utils/__init__.py CHANGED
@@ -1,5 +1,7 @@
1
1
  # SPDX-License-Identifier: Apache-2.0
2
2
 
3
+ import time
4
+ import os
3
5
  from cryptography.fernet import Fernet
4
6
  import keystoneauth1
5
7
  from loguru import logger
@@ -48,12 +50,12 @@ try:
48
50
  secondary_nb_list = []
49
51
  if type(secondary_nb_settings_list) is not list:
50
52
  raise TypeError(
51
- f"Setting NETBOX_SECONDARIES needs to be an array of mappings containing supported netbox API configuration: {supported_secondary_nb_keys}"
53
+ f"Setting NETBOX_SECONDARIES needs to be an array of mappings containing supported NetBox API configuration: {supported_secondary_nb_keys}"
52
54
  )
53
55
  for secondary_nb_settings in secondary_nb_settings_list:
54
56
  if type(secondary_nb_settings) is not dict:
55
57
  raise TypeError(
56
- f"Elements in setting NETBOX_SECONDARIES need to be mappings containing supported netbox API configuration: {supported_secondary_nb_keys}"
58
+ f"Elements in setting NETBOX_SECONDARIES need to be mappings containing supported NetBox API configuration: {supported_secondary_nb_keys}"
57
59
  )
58
60
  for key in list(secondary_nb_settings.keys()):
59
61
  if key not in supported_secondary_nb_keys:
@@ -65,14 +67,14 @@ try:
65
67
  or not secondary_nb_settings["NETBOX_URL"]
66
68
  ):
67
69
  raise ValueError(
68
- "All NETBOX_URL values in the elements of setting NETBOX_SECONDARIES need to be valid netbox URLs"
70
+ "All NETBOX_URL values in the elements of setting NETBOX_SECONDARIES need to be valid NetBox URLs"
69
71
  )
70
72
  if (
71
73
  "NETBOX_TOKEN" not in secondary_nb_settings
72
74
  or not secondary_nb_settings["NETBOX_TOKEN"]
73
75
  ):
74
76
  raise ValueError(
75
- "All NETBOX_TOKEN values in the elements of setting NETBOX_SECONDARIES need to be valid netbox tokens"
77
+ "All NETBOX_TOKEN values in the elements of setting NETBOX_SECONDARIES need to be valid NetBox tokens"
76
78
  )
77
79
 
78
80
  secondary_nb_list.append(
@@ -134,3 +136,48 @@ def first(iterable, condition=lambda x: True):
134
136
  """
135
137
 
136
138
  return next(x for x in iterable if condition(x))
139
+
140
+
141
+ def fetch_task_output(
142
+ task_id, timeout=os.environ.get("OSISM_TASK_TIMEOUT", 300), enable_play_recap=False
143
+ ):
144
+ rc = 0
145
+ stoptime = time.time() + timeout
146
+ last_id = 0
147
+ while time.time() < stoptime:
148
+ data = redis.xread({str(task_id): last_id}, count=1, block=(timeout * 1000))
149
+ if data:
150
+ stoptime = time.time() + timeout
151
+ messages = data[0]
152
+ for message_id, message in messages[1]:
153
+ last_id = message_id.decode()
154
+ message_type = message[b"type"].decode()
155
+ message_content = message[b"content"].decode()
156
+
157
+ logger.debug(f"Processing message {last_id} of type {message_type}")
158
+ redis.xdel(str(task_id), last_id)
159
+
160
+ if message_type == "stdout":
161
+ print(message_content, end="")
162
+ if enable_play_recap and "PLAY RECAP" in message_content:
163
+ logger.info(
164
+ "Play has been completed. There may now be a delay until "
165
+ "all logs have been written."
166
+ )
167
+ logger.info("Please wait and do not abort execution.")
168
+ elif message_type == "rc":
169
+ rc = int(message_content)
170
+ elif message_type == "action" and message_content == "quit":
171
+ redis.close()
172
+ return rc
173
+ raise TimeoutError
174
+
175
+
176
+ def push_task_output(task_id, line):
177
+ redis.xadd(task_id, {"type": "stdout", "content": line})
178
+
179
+
180
+ def finish_task_output(task_id, rc=None):
181
+ if rc:
182
+ redis.xadd(task_id, {"type": "rc", "content": rc})
183
+ redis.xadd(task_id, {"type": "action", "content": "quit"})
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: osism
3
- Version: 0.20250605.0
3
+ Version: 0.20250621.0
4
4
  Summary: OSISM manager interface
5
5
  Home-page: https://github.com/osism/python-osism
6
6
  Author: OSISM GmbH
@@ -32,13 +32,13 @@ Requires-Dist: cliff==4.10.0
32
32
  Requires-Dist: deepdiff==8.5.0
33
33
  Requires-Dist: docker==7.1.0
34
34
  Requires-Dist: dtrack-auditor==1.5.0
35
- Requires-Dist: fastapi==0.115.12
35
+ Requires-Dist: fastapi==0.115.13
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.0
39
+ Requires-Dist: keystoneauth1==5.11.1
40
40
  Requires-Dist: kombu==5.5.4
41
- Requires-Dist: kubernetes==32.0.1
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
44
  Requires-Dist: netmiko==4.5.0
@@ -2,11 +2,11 @@ osism/__init__.py,sha256=1UiNTBus0V0f2AbZQzAtVtu6zkfCCrw0OTq--NwFAqY,341
2
2
  osism/__main__.py,sha256=ILe4gu61xEISiBsxanqTQIdSkV-YhpZXTRlguCYyssk,141
3
3
  osism/api.py,sha256=t3HebSzk6fyY7bLJD9P95oEL1qWYXzpX6Yk1o_nVkMo,4356
4
4
  osism/main.py,sha256=Dt2-9sLXcS-Ny4DAz7hrha-KRc7zd7BFUTRdfs_X8z4,893
5
- osism/settings.py,sha256=mkvbxVQ64ZD7Ypk-bRePHn0gZ5j6Lcu2a578eLU0gQs,1309
5
+ osism/settings.py,sha256=bebPBT6Hd1-KhJfwZdFR-s8eMwV4B1IFr-WrQBkOrWw,1786
6
6
  osism/actions/__init__.py,sha256=bG7Ffen4LvQtgnYPFEpFccsWs81t4zqqeqn9ZeirH6E,38
7
7
  osism/commands/__init__.py,sha256=Ag4wX_DCgXRdoLn6t069jqb3DdRylsX2nyYkiyCx4uk,456
8
8
  osism/commands/apply.py,sha256=q645f4qxmOAaUjVD7npzM2aNuOqfptVAkCLfE6x5IV8,16833
9
- osism/commands/baremetal.py,sha256=PHXV-OV5M2sezvlidFwRF78OuO1-forXAJ9LYUBBVPk,7965
9
+ osism/commands/baremetal.py,sha256=w1LyZDms-DtULsF_76JsauOYHc2tcvoMRP6F9dYby9E,10688
10
10
  osism/commands/compose.py,sha256=iqzG7mS9E1VWaLNN6yQowjOqiHn3BMdj-yfXb3Dc4Ok,1200
11
11
  osism/commands/compute.py,sha256=cgqXWJa5wAvn-7e3FWCgX6hie_aK0yrKRkcNzjLXwDY,25799
12
12
  osism/commands/configuration.py,sha256=sPe8b0dVKFRbr30xoeVdAnHbGwCwgUh0xa_Vzv5pSQQ,954
@@ -14,20 +14,20 @@ osism/commands/console.py,sha256=8BPz1hio5Wi6kONVAWFuSqkDRrMcLEYeFIY8dbtN6e4,321
14
14
  osism/commands/container.py,sha256=Fku2GaCM3Idq_FxExUtNqjrEM0XYjpVvXmueSVO8S_c,1601
15
15
  osism/commands/get.py,sha256=ryytjtXWmlMV0NucP5tGkMZu0nIlC4xVtjRk4iMZ06c,8967
16
16
  osism/commands/log.py,sha256=2IpYuosC7FZwwLvM8HmKSU1NRNIelVVYzqjjVMCrOJk,4072
17
- osism/commands/manage.py,sha256=WxUZEhylZj2IhydAe3BAr3S5ED6opG243skfSq5q41s,11971
18
- osism/commands/netbox.py,sha256=PagHlAwEyzKzhrqi4nikkD8sjnVqAzzbDt8PVkl2j9k,6651
17
+ osism/commands/manage.py,sha256=FaO9dbYjNHYanS98-zC498bx26oU8E3loxCczH9mfKI,12751
18
+ osism/commands/netbox.py,sha256=e65P0kWrjTLw2T9HZthxjDTIRa-KAHgSSJAlvVef7n4,7345
19
19
  osism/commands/noset.py,sha256=7zDFuFMyNpo7DUOKcNiYV8nodtdMOYFp5LDPcuJhlZ8,1481
20
- osism/commands/reconciler.py,sha256=Tp4aMlKzumEdcSsJCX76ud1iLXvuJjAmdyqs7uHBCcE,2929
20
+ osism/commands/reconciler.py,sha256=jy07Qbl219e-WCtWbtV9zh49qHHCjDMm6oVTJM61k1A,1958
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
24
  osism/commands/status.py,sha256=X-Rcj-XuNPDBoxsGkf96NswwpmTognxz1V6E2NX2ZgY,1997
25
- osism/commands/sync.py,sha256=Vf9k7uVQTIu-8kK1u7Gjs3et3RRBEkmnNikot_PFJIE,484
25
+ osism/commands/sync.py,sha256=jOg-g8NmVOkXBI6rOuiOx2WgUJc1PplLAAAwc0VuIfw,1919
26
26
  osism/commands/task.py,sha256=mwJJ7a71Lw3o_FX7j3rR0-NbPdPwMDOjbOAiiXE4uGc,543
27
- osism/commands/validate.py,sha256=cA0CSvcbTr0K_6C5EofULrJSEp5xthpRC0TZgb_eazU,4233
27
+ osism/commands/validate.py,sha256=E1n1kEo6h8J5c7Ns5OHpr0R7i4IU6uj08LE_gt3kBCg,3262
28
28
  osism/commands/vault.py,sha256=llaqNN8UH8t8cCu2KmdaURvprA4zeG6izCen_W7ulPs,2029
29
29
  osism/commands/volume.py,sha256=l6oAk__dFM8KKdLTWOvuSiI7tLh9wAPZp8hwmYF-NX0,6595
30
- osism/commands/wait.py,sha256=mKFDqEXcaLlKw1T3MuBEZpNh7CeL3lpUXgubD2_f8es,6580
30
+ osism/commands/wait.py,sha256=2Ncx63M0AFq4fq40VZVClf1LS-WHetD8iC_mG2dY_Cw,5275
31
31
  osism/commands/worker.py,sha256=iraCOEhCp7WgfjfZ0-12XQYQPUjpi9rSJK5Z9JfNJk4,1651
32
32
  osism/core/__init__.py,sha256=bG7Ffen4LvQtgnYPFEpFccsWs81t4zqqeqn9ZeirH6E,38
33
33
  osism/core/enums.py,sha256=gItIjOK6xWuOZSkMxpMdYLRyt4ezyhzkqA7BGiah2o0,10030
@@ -35,27 +35,37 @@ osism/core/playbooks.py,sha256=M3T3ajV-8Lt-orsRO3jAoukhaoYFr4EZ2dzYXQjt1kg,728
35
35
  osism/data/__init__.py,sha256=izXdh0J3vPLQI7kBhJI7ibJQzPqU_nlONP0L4Cf_k6A,1504
36
36
  osism/plugins/__init__.py,sha256=bG7Ffen4LvQtgnYPFEpFccsWs81t4zqqeqn9ZeirH6E,38
37
37
  osism/services/__init__.py,sha256=bG7Ffen4LvQtgnYPFEpFccsWs81t4zqqeqn9ZeirH6E,38
38
- osism/services/listener.py,sha256=eEamlQsJqCuU9K2QFmk3yM9LAJZEanVcTLtGMsNCKjs,9783
39
- osism/tasks/__init__.py,sha256=68mP3DBhGr0om4_oxBLPF8TWBiVMr61lU7kdWiqV0dk,8769
38
+ osism/services/listener.py,sha256=Vf8LOZkHzlspm40BZ1az3o1O_ar34_i6C83p-D8KzzM,9783
39
+ osism/tasks/__init__.py,sha256=kocG0q2bARhkkSjMBH2xWdFUIJodesdh5qVsV_DqZmE,7148
40
40
  osism/tasks/ansible.py,sha256=_2zrHwynwwEv9nDnX-LbNCzcwy9dTUGo_yyutt34HyQ,1346
41
41
  osism/tasks/ceph.py,sha256=eIQkah3Kj4INtOkF9kTjHbXJ3_J2lg48EWJKfHc-UYw,615
42
- osism/tasks/conductor.py,sha256=i-X4AOxOz7xV0g610AREBmDQPqc8i3kVmT2L5uuE2Rg,240
42
+ osism/tasks/conductor.py,sha256=WBLsoPtr0iGUzRGERs0Xt7CMYrnHQVEwNV9qXBssI3s,274
43
43
  osism/tasks/kolla.py,sha256=wJQpWn_01iWLkr7l7T7RNrQGfRgsgmYi4WQlTmNGvew,618
44
44
  osism/tasks/kubernetes.py,sha256=VzXq_VrYU_CLm4cOruqnE3Kq2ydfO9glZ3p0bp3OYoc,625
45
- osism/tasks/netbox.py,sha256=Dq2hg2yiv_dHV-zygJgy9T1ZhTSE32_a34fhfURUfTA,5912
45
+ osism/tasks/netbox.py,sha256=g0gL5QImiRTHqixRxze7LfNqPth7cXqLzVWQDUJLDjE,5928
46
46
  osism/tasks/openstack.py,sha256=g15tCll5vP1pC6ysxRCTZxplsdGmXbxaCH3k1Qdv5Xg,6367
47
- osism/tasks/reconciler.py,sha256=tnZEZZpveBCK4vHZkHE6wDcHfJAlsPcSjIVxB5ItSFM,1981
48
- osism/tasks/conductor/__init__.py,sha256=H428puHzYqik1AEqHijVUMGizEt0mDZL0RaxCiTsRYg,1315
47
+ osism/tasks/reconciler.py,sha256=6iC0EYxeGvitzU2NsRqQzUEDZWW6Il3jgq_IRTN0sZg,1855
48
+ osism/tasks/conductor/__init__.py,sha256=eBkisjRj0YRT0AArvuvpIHGNEqEijsNvR_55BuVX62I,1600
49
49
  osism/tasks/conductor/config.py,sha256=tvfuYNgvw0F_ZbvrjqnyHfrj3vF6z0zhsRtGNu-Lgvo,3410
50
- osism/tasks/conductor/ironic.py,sha256=cHcoa32Oa8hjoGY_GZtmnJO4qvOle301dDa0ACn1uF0,15355
51
- osism/tasks/conductor/netbox.py,sha256=Wv_FG75M1S9hCZBq_vC5ge30R7vcH57bpLqX011Xct8,1875
50
+ osism/tasks/conductor/ironic.py,sha256=tIhKH5EWvqzjVtZr32du8_jiVDP_9mFgTkxBjmtEm6g,16487
51
+ osism/tasks/conductor/netbox.py,sha256=5Nc7wrriDOtSuru1KDLt9QpA54vC7tXDPB2J0JP9GKo,11393
52
52
  osism/tasks/conductor/utils.py,sha256=-a0-pRuhV4Fjj0SgdgBqtRJtAdGdqck5pzfi6NYBApU,2338
53
- osism/utils/__init__.py,sha256=_Y4qchR5yyI_JKhBWd_jcsvDLYZjxO0c3iMA_VRQl58,4304
54
- osism-0.20250605.0.dist-info/licenses/AUTHORS,sha256=oWotd63qsnNR945QLJP9mEXaXNtCMaesfo8ZNuLjwpU,39
55
- osism-0.20250605.0.dist-info/licenses/LICENSE,sha256=tAkwu8-AdEyGxGoSvJ2gVmQdcicWw3j1ZZueVV74M-E,11357
56
- osism-0.20250605.0.dist-info/METADATA,sha256=tVmPS34kED3Kf1V34RHb-3WPXmu8-8jqzRUYf3EKwx4,2903
57
- osism-0.20250605.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
58
- osism-0.20250605.0.dist-info/entry_points.txt,sha256=cTxzUWJff6JKe1Jv-iMMKayIiC26S1_Fph3k5faiQvw,3252
59
- osism-0.20250605.0.dist-info/pbr.json,sha256=g9rrfXMHNdenzVrBTsDuavh4yqaAchyC2SB81rty5Gc,47
60
- osism-0.20250605.0.dist-info/top_level.txt,sha256=8L8dsI9hcaGHsdnR4k_LN9EM78EhwrXRFHyAryPXZtY,6
61
- osism-0.20250605.0.dist-info/RECORD,,
53
+ osism/tasks/conductor/sonic/__init__.py,sha256=oxTTl_MGK4iWK9uNDRNlULtGrDGCQHrlJZ04weh_Lh8,777
54
+ osism/tasks/conductor/sonic/bgp.py,sha256=PC6gGI5bCj2PCXcNGyMV9-EdlJWDsYaodzxigmYSZvw,3088
55
+ osism/tasks/conductor/sonic/cache.py,sha256=Asv2k3nLJejuq7iB0a_LyK8dEmJzypP9v3OHkNY3GwI,3438
56
+ osism/tasks/conductor/sonic/config_generator.py,sha256=Z2i6SvKp27EI-dK9fkSDo51ghbIIqTgM7qK0-xJtVwU,35098
57
+ osism/tasks/conductor/sonic/connections.py,sha256=NvRjwJv3NF3ry5Xe9qHzk7pQbfDQHYx_j3ATRMUs7gA,14244
58
+ osism/tasks/conductor/sonic/constants.py,sha256=nfsiKV1I5iiXPAUzkZgnFPWuSB_oy8xg3gNEZjn1Hb4,2194
59
+ osism/tasks/conductor/sonic/device.py,sha256=ZYJA0bQ8waKWStzWUPxbcwNWa2Z_hMB3pqs8aA_nxXA,2458
60
+ osism/tasks/conductor/sonic/exporter.py,sha256=25L1vbi84ZQD0xNHNTWk-anTz5QRkGJskCECBkeGQw4,8882
61
+ osism/tasks/conductor/sonic/interface.py,sha256=MM-HrYlVdh_5fYSKto_38DC4RcfzoqBGEYFxk-Tz760,32233
62
+ osism/tasks/conductor/sonic/sync.py,sha256=Jh2xbBv_yyrEJZZZkZRIk7vH0WV-IS4CA-4qQp56I2U,7823
63
+ osism/utils/__init__.py,sha256=gN5VtLJfrvyn6_snuTte7YR-vDygkpbORopIV8qSEsA,6064
64
+ osism-0.20250621.0.dist-info/licenses/AUTHORS,sha256=oWotd63qsnNR945QLJP9mEXaXNtCMaesfo8ZNuLjwpU,39
65
+ osism-0.20250621.0.dist-info/licenses/LICENSE,sha256=tAkwu8-AdEyGxGoSvJ2gVmQdcicWw3j1ZZueVV74M-E,11357
66
+ osism-0.20250621.0.dist-info/METADATA,sha256=0nTzEqeDkHWwUyPJftfn6_Az0MP26rQjhMQNPffXkdM,2903
67
+ osism-0.20250621.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
68
+ osism-0.20250621.0.dist-info/entry_points.txt,sha256=X1KbMeQim23k_lGGDFz8ldQIrdCrq8mKnFWgYrrEZI0,3469
69
+ osism-0.20250621.0.dist-info/pbr.json,sha256=nvF1nN4eUUNsct1PT2Fq9FvN3QNGbPvpeeWGR0BjJjU,47
70
+ osism-0.20250621.0.dist-info/top_level.txt,sha256=8L8dsI9hcaGHsdnR4k_LN9EM78EhwrXRFHyAryPXZtY,6
71
+ osism-0.20250621.0.dist-info/RECORD,,
@@ -37,13 +37,16 @@ manage compute migrate = osism.commands.compute:ComputeMigrate
37
37
  manage compute migration list = osism.commands.compute:ComputeMigrationList
38
38
  manage compute start = osism.commands.compute:ComputeStart
39
39
  manage compute stop = osism.commands.compute:ComputeStop
40
+ manage dnsmasq = osism.commands.manage:Dnsmasq
40
41
  manage flavors = osism.commands.manage:Flavors
41
42
  manage image clusterapi = osism.commands.manage:ImageClusterapi
42
43
  manage image octavia = osism.commands.manage:ImageOctavia
43
44
  manage images = osism.commands.manage:Images
45
+ manage ironic = osism.commands.netbox:Ironic
44
46
  manage netbox = osism.commands.netbox:Manage
45
47
  manage server list = osism.commands.server:ServerList
46
48
  manage server migrate = osism.commands.server:ServerMigrate
49
+ manage sonic = osism.commands.sync:Sonic
47
50
  manage volume list = osism.commands.volume:VolumeList
48
51
  netbox = osism.commands.netbox:Console
49
52
  noset bootstrap = osism.commands.noset:NoBootstrap
@@ -56,10 +59,12 @@ set bootstrap = osism.commands.set:Bootstrap
56
59
  set maintenance = osism.commands.set:Maintenance
57
60
  set vault password = osism.commands.vault:SetPassword
58
61
  sync configuration = osism.commands.configuration:Sync
62
+ sync dnsmasq = osism.commands.manage:Dnsmasq
59
63
  sync facts = osism.commands.sync:Facts
60
64
  sync inventory = osism.commands.reconciler:Sync
61
65
  sync ironic = osism.commands.netbox:Ironic
62
66
  sync netbox = osism.commands.netbox:Sync
67
+ sync sonic = osism.commands.sync:Sonic
63
68
  task list = osism.commands.get:Tasks
64
69
  task revoke = osism.commands.task:Revoke
65
70
  validate = osism.commands.validate:Run
@@ -0,0 +1 @@
1
+ {"git_version": "ed0a34c", "is_release": false}
@@ -1 +0,0 @@
1
- {"git_version": "f816350", "is_release": false}