serve_repo.py 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. #!/usr/bin/env vpython3
  2. # Copyright 2022 The Chromium Authors. All rights reserved.
  3. # Use of this source code is governed by a BSD-style license that can be
  4. # found in the LICENSE file.
  5. """Implements commands for serving a TUF repository."""
  6. import argparse
  7. import contextlib
  8. import sys
  9. from typing import Iterator, Optional
  10. from common import REPO_ALIAS, register_device_args, run_ffx_command
  11. from ffx_integration import get_config
  12. _REPO_NAME = 'chromium-test-package-server'
  13. def _ensure_ffx_config(key: str, value: str) -> bool:
  14. """Ensures ffx config for a given key is value. Returns True if the config
  15. was changed, False otherwise."""
  16. if get_config(key) == value:
  17. return False
  18. run_ffx_command(['config', 'set', key, value])
  19. return True
  20. def _stop_serving(repo_name: str, target: Optional[str]) -> None:
  21. """Stop serving a repository."""
  22. # Attempt to clean up.
  23. run_ffx_command(['target', 'repository', 'deregister', '-r', repo_name],
  24. target,
  25. check=False)
  26. run_ffx_command(['repository', 'remove', repo_name], check=False)
  27. run_ffx_command(['repository', 'server', 'stop'], check=False)
  28. def _start_serving(repo_dir: str, repo_name: str,
  29. target: Optional[str]) -> None:
  30. """Start serving a repository to a target device.
  31. Args:
  32. repo_dir: directory the repository is served from.
  33. repo_name: repository name.
  34. target: Fuchsia device the repository is served to.
  35. """
  36. # Check ffx configs, restart daemon if the configuration was updated.
  37. config_updated = False
  38. config_updated |= _ensure_ffx_config('ffx_repository', 'true')
  39. config_updated |= _ensure_ffx_config('repository.server.mode', '\"ffx\"')
  40. if config_updated:
  41. run_ffx_command(['doctor', '--restart-daemon'])
  42. run_ffx_command(['repository', 'server', 'start'])
  43. run_ffx_command(['repository', 'add-from-pm', repo_dir, '-r', repo_name])
  44. run_ffx_command([
  45. 'target', 'repository', 'register', '-r', repo_name, '--alias',
  46. REPO_ALIAS
  47. ], target)
  48. def register_serve_args(arg_parser: argparse.ArgumentParser) -> None:
  49. """Register common arguments for repository serving."""
  50. serve_args = arg_parser.add_argument_group('serve',
  51. 'repo serving arguments')
  52. serve_args.add_argument('--serve-repo',
  53. dest='repo',
  54. help='Directory the repository is served from.')
  55. serve_args.add_argument('--repo-name',
  56. default=_REPO_NAME,
  57. help='Name of the repository.')
  58. def run_serve_cmd(cmd: str, args: argparse.Namespace) -> None:
  59. """Helper for running serve commands."""
  60. if cmd == 'start':
  61. _start_serving(args.repo, args.repo_name, args.target_id)
  62. else:
  63. _stop_serving(args.repo_name, args.target_id)
  64. @contextlib.contextmanager
  65. def serve_repository(args: argparse.Namespace) -> Iterator[None]:
  66. """Context manager for serving a repository."""
  67. run_serve_cmd('start', args)
  68. try:
  69. yield None
  70. finally:
  71. run_serve_cmd('stop', args)
  72. def main():
  73. """Stand-alone function for serving a repository."""
  74. parser = argparse.ArgumentParser()
  75. parser.add_argument('cmd',
  76. choices=['start', 'stop'],
  77. help='Choose to start|stop repository serving.')
  78. register_device_args(parser)
  79. register_serve_args(parser)
  80. args = parser.parse_args()
  81. if args.cmd == 'start' and not args.repo:
  82. raise ValueError('Directory the repository is serving from needs '
  83. 'to be specified.')
  84. run_serve_cmd(args.cmd, args)
  85. if __name__ == '__main__':
  86. sys.exit(main())