#!/usr/bin/env python3 # SPDX-License-Identifier: GPL-3.0-or-later # # Copyright (C) 2026 YueGuobin # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . """ Web Wireshark Management Script (CLI Tool) This script provides a command-line interface for managing Web Wireshark containers. It is intended for manual management, debugging, and testing purposes. NOTE: For programmatic access within GNS3 server, use WebWiresharkManager class directly from gns3server.agent.web_wireshark.manager instead of calling this script via subprocess. Usage Examples: # Start a Web Wireshark session python manage_wireshark.py start \\ --project-id \\ --link-id \\ --jwt-token # Stop a Web Wireshark session python manage_wireshark.py stop \\ --project-id \\ --link-id # Restart a Web Wireshark session python manage_wireshark.py restart \\ --project-id \\ --link-id \\ --jwt-token # Stop all sessions for a project python manage_wireshark.py stop-all --project-id # Delete project container python manage_wireshark.py delete --project-id Available Commands: start Start a new Web Wireshark session stop Stop a Web Wireshark session restart Restart a Web Wireshark session stop-all Stop all Web Wireshark sessions for a project delete Delete the Web Wireshark container stop-container Stop container without deleting delete-container Delete the container Output Format: All commands output JSON to stdout for easy parsing: - Success: {"status": "...", "ws_url": "...", ...} - Error: {"error": "message"} (to stderr) For more information on each command, use: python manage_wireshark.py --help """ import sys import json import argparse import logging import asyncio import os from typing import Optional from gns3server.utils.uuid_validator import validate_uuid # Add parent directory to path for imports when run directly if __name__ == "__main__": sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))) try: from gns3server.agent.web_wireshark.manager import WebWiresharkManager except ImportError: from manager import WebWiresharkManager logger = logging.getLogger(__name__) def setup_logging(verbose: bool = False): """Setup logging configuration.""" level = logging.DEBUG if verbose else logging.INFO logging.basicConfig( level=level, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s" ) async def cmd_start(args) -> int: """Start Web Wireshark session. Args: args: Command line arguments Returns: Exit code (0 for success) """ manager = WebWiresharkManager() try: await manager.ensure_network() result = await manager.start_wireshark_session( project_id=args.project_id, link_id=args.link_id, jwt_token=args.jwt_token, capture_stream_url=args.capture_url, image=args.image, memory=args.memory, cpus=args.cpus, pids_limit=args.pids_limit ) print(json.dumps(result, indent=2)) return 0 except Exception as e: logger.error(f"Error: {e}") print(json.dumps({"error": str(e)}), file=sys.stderr) return 1 finally: await manager.close() async def cmd_stop(args) -> int: """Stop Web Wireshark session. Args: args: Command line arguments Returns: Exit code (0 for success) """ manager = WebWiresharkManager() try: await manager.stop_wireshark_session( project_id=args.project_id, link_id=args.link_id ) print(json.dumps({"status": "stopped"})) return 0 except Exception as e: logger.error(f"Error: {e}") print(json.dumps({"error": str(e)}), file=sys.stderr) return 1 finally: await manager.close() async def cmd_restart(args) -> int: """Restart Web Wireshark session. Args: args: Command line arguments Returns: Exit code (0 for success) """ manager = WebWiresharkManager() try: result = await manager.restart_wireshark_session( project_id=args.project_id, link_id=args.link_id, jwt_token=args.jwt_token, capture_stream_url=args.capture_url ) print(json.dumps(result, indent=2)) return 0 except Exception as e: logger.error(f"Error: {e}") print(json.dumps({"error": str(e)}), file=sys.stderr) return 1 finally: await manager.close() async def cmd_stop_all(args) -> int: """Stop all Web Wireshark sessions for a project. Args: args: Command line arguments Returns: Exit code (0 for success) """ manager = WebWiresharkManager() try: await manager.stop_all_sessions(project_id=args.project_id) print(json.dumps({"status": "all sessions stopped"})) return 0 except Exception as e: logger.error(f"Error: {e}") print(json.dumps({"error": str(e)}), file=sys.stderr) return 1 finally: await manager.close() async def cmd_stop_container(args) -> int: """Stop Web Wireshark container (without deleting). Args: args: Command line arguments Returns: Exit code (0 for success) """ manager = WebWiresharkManager() try: await manager.stop_container(project_id=args.project_id) print(json.dumps({"status": "stopped"})) return 0 except Exception as e: logger.error(f"Error: {e}") print(json.dumps({"error": str(e)}), file=sys.stderr) return 1 finally: await manager.close() async def cmd_delete_container(args) -> int: """Delete Web Wireshark container. Args: args: Command line arguments Returns: Exit code (0 for success) """ manager = WebWiresharkManager() try: await manager.delete_container(project_id=args.project_id) print(json.dumps({"status": "deleted"})) return 0 except Exception as e: logger.error(f"Error: {e}") print(json.dumps({"error": str(e)}), file=sys.stderr) return 1 finally: await manager.close() async def cmd_delete(args) -> int: """Delete Web Wireshark container. Args: args: Command line arguments Returns: Exit code (0 for success) """ manager = WebWiresharkManager() try: await manager.delete_container(project_id=args.project_id) print(json.dumps({"status": "deleted"})) return 0 except Exception as e: logger.error(f"Error: {e}") print(json.dumps({"error": str(e)}), file=sys.stderr) return 1 finally: await manager.close() def create_parser() -> argparse.ArgumentParser: """Create command line argument parser.""" parser = argparse.ArgumentParser( description="Web Wireshark container management" ) parser.add_argument( "--verbose", "-v", action="store_true", help="Enable verbose logging" ) subparsers = parser.add_subparsers(dest="command", help="Commands") # Start command start_parser = subparsers.add_parser("start", help="Start Web Wireshark session") start_parser.add_argument("--project-id", required=True, type=validate_uuid, help="Project ID") start_parser.add_argument("--link-id", required=True, type=validate_uuid, help="Link ID") start_parser.add_argument("--jwt-token", required=True, help="JWT token") start_parser.add_argument( "--capture-url", help="Capture stream URL (auto-detected if not provided)" ) start_parser.add_argument( "--image", default="gns3/web-wireshark:latest", help="Docker image (default: gns3/web-wireshark:latest)" ) start_parser.add_argument( "--memory", default="2g", help="Memory limit (default: 2g)" ) start_parser.add_argument( "--cpus", type=float, default=1.0, help="CPU cores (default: 1.0)" ) start_parser.add_argument( "--pids-limit", type=int, default=1000, help="Process limit (default: 1000)" ) # Stop command stop_parser = subparsers.add_parser("stop", help="Stop Web Wireshark session") stop_parser.add_argument("--project-id", required=True, type=validate_uuid, help="Project ID") stop_parser.add_argument("--link-id", required=True, type=validate_uuid, help="Link ID") # Restart command restart_parser = subparsers.add_parser("restart", help="Restart Web Wireshark session") restart_parser.add_argument("--project-id", required=True, type=validate_uuid, help="Project ID") restart_parser.add_argument("--link-id", required=True, type=validate_uuid, help="Link ID") restart_parser.add_argument("--jwt-token", required=True, help="JWT token") restart_parser.add_argument( "--capture-url", help="Capture stream URL (auto-detected if not provided)" ) # Stop all command stop_all_parser = subparsers.add_parser("stop-all", help="Stop all sessions") stop_all_parser.add_argument("--project-id", required=True, type=validate_uuid, help="Project ID") # Delete command delete_parser = subparsers.add_parser("delete", help="Delete container") delete_parser.add_argument("--project-id", required=True, type=validate_uuid, help="Project ID") # Stop container command stop_container_parser = subparsers.add_parser("stop-container", help="Stop container (without deleting)") stop_container_parser.add_argument("--project-id", required=True, type=validate_uuid, help="Project ID") # Delete container command delete_container_parser = subparsers.add_parser("delete-container", help="Delete container") delete_container_parser.add_argument("--project-id", required=True, type=validate_uuid, help="Project ID") return parser async def main() -> int: """Main entry point.""" parser = create_parser() args = parser.parse_args() if not args.command: parser.print_help() return 1 setup_logging(args.verbose) commands = { "start": cmd_start, "stop": cmd_stop, "restart": cmd_restart, "stop-all": cmd_stop_all, "delete": cmd_delete, "stop-container": cmd_stop_container, "delete-container": cmd_delete_container, } return await commands[args.command](args) if __name__ == "__main__": exit_code = asyncio.run(main()) sys.exit(exit_code)