#!/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)