"""Portable source-checkout command line interface.""" import argparse import json import os import sys from pathlib import Path from .profiles import Profile from .runtime import Runtime, RuntimeError def parser() -> argparse.ArgumentParser: cli = argparse.ArgumentParser(prog='hydra', description='Independent HydraOS VM manager') cli.add_argument('--config', type=Path, default=Path(os.environ.get('XDG_CONFIG_HOME', Path.home() / '.config')) / 'hydra') cli.add_argument('--state', type=Path, default=Path(os.environ.get('XDG_STATE_HOME', Path.home() / '.local/state')) / 'hydra') cli.add_argument('--runtime', type=Path, default=Path(os.environ.get('XDG_RUNTIME_DIR', f'/tmp/hydra-{os.getuid()}')) / 'hydra') commands = cli.add_subparsers(dest='command', required=True) add = commands.add_parser('add', help='Create a VM profile without starting it') add.add_argument('name') add.add_argument('--iso', type=Path, required=True) add.add_argument('--memory', type=int, default=4096) add.add_argument('--cpus', type=int, default=2) add.add_argument('--disk-size', default='40G') add.add_argument('--graphics', choices=('auto', 'software'), default='auto') add.add_argument('--network', choices=('user', 'bridge'), default='user') add.add_argument('--bridge', default='hydrabr0') commands.add_parser('list', help='List configured VMs') status = commands.add_parser('status', help='Query VM state through private QMP') status.add_argument('name', nargs='?') for command in ('start', 'shutdown', 'stop'): cmd = commands.add_parser(command) cmd.add_argument('name') if command == 'stop': cmd.add_argument('--force', action='store_true', required=True) return cli def main(argv: list[str] | None = None) -> int: args = parser().parse_args(argv) runtime = Runtime(args.config, args.state, args.runtime) try: if args.command == 'add': profile = Profile(args.name, args.iso, args.memory, args.cpus, args.disk_size, args.graphics, args.network, args.bridge) runtime.add(profile) result = {'name': profile.name, 'status': 'added'} elif args.command == 'list': result = [{'name': profile.name, 'iso': str(profile.iso)} for profile in runtime.profiles()] elif args.command == 'status': result = runtime.status(args.name) if args.name else [runtime.status(p.name) for p in runtime.profiles()] elif args.command == 'stop': result = runtime.stop(args.name, force=args.force) else: result = getattr(runtime, args.command)(args.name) print(json.dumps(result, indent=2)) return 0 except (RuntimeError, OSError, ValueError) as exc: print(f'hydra: {exc}', file=sys.stderr) return 1