|
10 | 10 | from nebula.controller.federation.utils_requests import factory_requests_path |
11 | 11 | from nebula.controller.federation.utils_requests import NodeUpdateRequest, NodeDoneRequest |
12 | 12 | from typing import Dict |
13 | | -from fastapi import Request |
14 | 13 | from nebula.config.config import Config |
15 | 14 | from nebula.core.utils.certificate import generate_ca_certificate |
16 | 15 | from nebula.core.utils.locker import Locker |
@@ -113,93 +112,50 @@ async def stop_scenario(self, federation_id: str): |
113 | 112 | Reads ALL scenario.metadata and removes all listed containers and the network, then deletes the metadata file. |
114 | 113 | Also forcibly stops and removes any containers still attached to the network before removing it. |
115 | 114 | """ |
116 | | - federation_scenario_name = await self._remove_nebula_federation_from_pool(federation_id) |
117 | | - if not federation_scenario_name: |
| 115 | + federation = await self._remove_nebula_federation_from_pool(federation_id) |
| 116 | + if not federation: |
118 | 117 | return False |
119 | 118 |
|
120 | | - # Try multiple possible config directory locations. This depends on where the user called the function from. |
121 | | - possible_config_dirs = [ |
122 | | - os.environ.get("NEBULA_CONFIG_DIR"), |
123 | | - "/nebula/app/config", |
124 | | - "./app/config", |
125 | | - os.path.join(os.getcwd(), "app", "config"), |
126 | | - os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), "app", "config"), |
127 | | - ] |
128 | | - |
129 | | - config_dir = None |
130 | | - for dir_path in possible_config_dirs: |
131 | | - if dir_path and os.path.exists(dir_path): |
132 | | - config_dir = dir_path |
133 | | - break |
134 | | - |
135 | | - if not config_dir: |
136 | | - self.logger.info("No valid config directory found, skipping cleanup") |
137 | | - return |
138 | | - |
139 | | - scenario_dirs = [] |
140 | | - self.logger.info(f"Config directory: {config_dir}") |
141 | | - if os.path.exists(config_dir): |
142 | | - for item in os.listdir(config_dir): |
143 | | - scenario_path = os.path.join(config_dir, item) |
144 | | - if os.path.isdir(scenario_path): |
145 | | - metadata_file = os.path.join(scenario_path, "scenario.metadata") |
146 | | - if os.path.exists(metadata_file): |
147 | | - scenario_dirs.append(scenario_path) |
148 | | - |
149 | | - self.logger.info(f"Removing scenario containers for {scenario_dirs}") |
150 | | - if not scenario_dirs: |
151 | | - self.logger.info("No active scenarios found to clean up") |
152 | | - return |
153 | | - |
154 | 119 | client = docker.from_env() |
155 | | - |
156 | | - for scenario_dir in scenario_dirs: |
157 | | - if scenario_dir != federation_scenario_name: |
158 | | - continue |
159 | | - |
160 | | - metadata_path = os.path.join(scenario_dir, "scenario.metadata") |
161 | | - if not os.path.exists(metadata_path): |
162 | | - self.logger.info(f"Skipping {scenario_dir} - no scenario.metadata found") |
163 | | - continue |
164 | | - |
165 | | - with open(metadata_path) as f: |
166 | | - meta = json.load(f) |
167 | | - |
168 | | - # Remove containers listed in metadata |
169 | | - for name in meta.get("containers", []): |
170 | | - try: |
171 | | - container = client.containers.get(name) |
172 | | - container.remove(force=True) |
173 | | - self.logger.info(f"Removed scenario container {name}") |
174 | | - except Exception as e: |
175 | | - self.logger.info(f"Could not remove scenario container {name}: {e}") |
176 | | - |
177 | | - # Remove network, but first forcibly remove any containers still attached |
178 | | - network_name = meta.get("network") |
179 | | - if network_name: |
180 | | - try: |
181 | | - network = client.networks.get(network_name) |
182 | | - attached_containers = network.attrs.get("Containers") or {} |
183 | | - for container_id in attached_containers: |
184 | | - try: |
185 | | - c = client.containers.get(container_id) |
186 | | - c.remove(force=True) |
187 | | - self.logger.info(f"Force-removed container {c.name} attached to {network_name}") |
188 | | - except Exception as e: |
189 | | - self.logger.info(f"Could not force-remove container {container_id}: {e}") |
190 | | - network.remove() |
191 | | - self.logger.info(f"Removed scenario network {network_name}") |
192 | | - except Exception as e: |
193 | | - self.logger.info(f"Could not remove scenario network {network_name}: {e}") |
194 | | - |
195 | | - # Remove metadata file |
| 120 | + metadata_path = os.path.join(federation.config_dir, "scenario.metadata") |
| 121 | + |
| 122 | + if not os.path.exists(metadata_path): |
| 123 | + self.logger.info(f"ERROR {metadata_path} - no 'scenario.metadata' found") |
| 124 | + return False |
| 125 | + |
| 126 | + with open(metadata_path) as f: |
| 127 | + meta = json.load(f) |
| 128 | + # Remove containers listed in metadata |
| 129 | + for name in meta.get("containers", []): |
196 | 130 | try: |
197 | | - os.remove(metadata_path) |
| 131 | + container = client.containers.get(name) |
| 132 | + container.remove(force=True) |
| 133 | + self.logger.info(f"Removed scenario container {name}") |
198 | 134 | except Exception as e: |
199 | | - self.logger.info(f"Could not remove scenario.metadata: {e}") |
200 | | - |
201 | | - if scenario_dir == federation_scenario_name: |
202 | | - break |
| 135 | + self.logger.info(f"Could not remove scenario container {name}: {e}") |
| 136 | + # Remove network, but first forcibly remove any containers still attached |
| 137 | + network_name = meta.get("network") |
| 138 | + if network_name: |
| 139 | + try: |
| 140 | + network = client.networks.get(network_name) |
| 141 | + attached_containers = network.attrs.get("Containers") or {} |
| 142 | + for container_id in attached_containers: |
| 143 | + try: |
| 144 | + c = client.containers.get(container_id) |
| 145 | + c.remove(force=True) |
| 146 | + self.logger.info(f"Force-removed container {c.name} attached to {network_name}") |
| 147 | + except Exception as e: |
| 148 | + self.logger.info(f"Could not force-remove container {container_id}: {e}") |
| 149 | + network.remove() |
| 150 | + self.logger.info(f"Removed scenario network {network_name}") |
| 151 | + except Exception as e: |
| 152 | + self.logger.info(f"Could not remove scenario network {network_name}: {e}") |
| 153 | + # Remove metadata file |
| 154 | + try: |
| 155 | + os.remove(metadata_path) |
| 156 | + except Exception as e: |
| 157 | + self.logger.info(f"Could not remove scenario.metadata: {e}") |
| 158 | + return False |
203 | 159 |
|
204 | 160 | return True #TODO care about cases |
205 | 161 |
|
@@ -269,15 +225,15 @@ async def _add_nebula_federation_to_pool(self, federation_id: str, user: str): |
269 | 225 | self.logger.info(f"ERROR: trying to add ({federation_id}) to federations pool..") |
270 | 226 | return fed |
271 | 227 |
|
272 | | - async def _remove_nebula_federation_from_pool(self, federation_id: str): |
| 228 | + async def _remove_nebula_federation_from_pool(self, federation_id: str) -> NebulaFederationDocker | None: |
273 | 229 | async with self._federations_dict_lock: |
274 | 230 | if federation_id in self.nfp: |
275 | 231 | federation = self.nfp.pop(federation_id) |
276 | 232 | self.logger.info(f"SUCCESS: Federation ID: ({federation_id}) removed from pool") |
277 | | - return federation.scenario_name |
| 233 | + return federation |
278 | 234 | else: |
279 | 235 | self.logger.info(f"ERROR: trying to remove ({federation_id}) from federations pool..") |
280 | | - return "" |
| 236 | + return None |
281 | 237 |
|
282 | 238 | async def _update_federation_on_pool(self, federation_id: str, user: str, nf: NebulaFederationDocker): |
283 | 239 | updated = False |
|
0 commit comments