Process all IPs with alive status set to 1
(self, current_data)
| 292 | logger.error(f"Module {module_name} is missing required attributes: {e}") |
| 293 | |
| 294 | def process_alive_ips(self, current_data): |
| 295 | """Process all IPs with alive status set to 1""" |
| 296 | any_action_executed = False |
| 297 | action_executed_status = None |
| 298 | |
| 299 | # Debug: Log what we're processing |
| 300 | alive_hosts = [row for row in current_data if row.get("Alive") == '1'] |
| 301 | logger.debug(f"Processing {len(alive_hosts)} alive hosts out of {len(current_data)} total hosts") |
| 302 | logger.debug(f"Available actions: {len(self.actions)} (parent+child actions)") |
| 303 | |
| 304 | if not alive_hosts: |
| 305 | logger.warning("No alive hosts to process - all hosts have Alive != '1'") |
| 306 | return False |
| 307 | |
| 308 | if not self.actions: |
| 309 | logger.warning("No actions loaded - check actions.json configuration") |
| 310 | return False |
| 311 | |
| 312 | # Process all parent actions (those without dependencies) across ALL hosts |
| 313 | for action in self.actions: |
| 314 | if action.b_parent_action is None: |
| 315 | action_key = action.action_name |
| 316 | required_port = getattr(action, 'port', None) |
| 317 | |
| 318 | # Pre-filter hosts by port requirement (FAST - no semaphore needed) |
| 319 | for row in current_data: |
| 320 | if row["Alive"] != '1': |
| 321 | continue |
| 322 | |
| 323 | ip = row["IPs"] |
| 324 | ports = self._extract_ports(row) |
| 325 | |
| 326 | # OPTIMIZATION: Check port requirement BEFORE acquiring semaphore |
| 327 | # This prevents serializing hundreds of "port not found" checks |
| 328 | if required_port not in (None, '', 0, '0'): |
| 329 | required_port_str = str(required_port).strip().split('/')[0] |
| 330 | ports_normalized = [str(p).strip().split('/')[0] for p in ports] |
| 331 | |
| 332 | if required_port_str not in ports_normalized: |
| 333 | # Skip silently - port not available (no semaphore needed) |
| 334 | continue |
| 335 | |
| 336 | # MEMORY CHECK: Prevent OOM kills |
| 337 | if not resource_monitor.can_start_operation(f"action_{action_key}", min_memory_mb=30): |
| 338 | logger.warning(f"Insufficient memory to execute {action_key}, skipping to prevent OOM") |
| 339 | continue |
| 340 | |
| 341 | # Only acquire semaphore when we actually need to execute |
| 342 | with self.semaphore: |
| 343 | if self.execute_action(action, ip, ports, row, action_key, current_data): |
| 344 | action_executed_status = action_key |
| 345 | any_action_executed = True |
| 346 | self.shared_data.ragnarorch_status = action_executed_status |
| 347 | |
| 348 | # After parent succeeds, immediately try child actions on same host |
| 349 | # Note: Already within semaphore context, no need to re-acquire |
| 350 | for child_action in self.actions: |
| 351 | if child_action.b_parent_action == action_key: |
no test coverage detected