108 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
			
		
		
	
	
			108 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
| #!/usr/bin/env python3
 | |
| # Copyright 2021 The Chromium OS Authors. All rights reserved.
 | |
| # Use of this source code is governed by a BSD-style license that can be
 | |
| # found in the LICENSE file.
 | |
| #
 | |
| # Usage:
 | |
| #
 | |
| # To get an interactive shell for development:
 | |
| #   ./tools/dev_container
 | |
| #
 | |
| # To run a command in the container, e.g. to run presubmits:
 | |
| #   ./tools/dev_container ./tools/presubmit
 | |
| #
 | |
| # The state of the container (including build artifacts) are preserved between
 | |
| # calls. To stop the container call:
 | |
| #   ./tools/dev_container --stop
 | |
| #
 | |
| # The dev container can also be called with a fresh container for each call that
 | |
| # is cleaned up afterwards (e.g. when run by Kokoro):
 | |
| #
 | |
| #   ./tools/dev_container --hermetic CMD
 | |
| 
 | |
| import argparse
 | |
| import getpass
 | |
| from argh import arg
 | |
| from impl.common import CROSVM_ROOT, run_main, cmd, chdir, quoted
 | |
| import sys
 | |
| import os
 | |
| 
 | |
| CONTAINER_NAME = f"crosvm_dev_{getpass.getuser()}"
 | |
| IMAGE_VERSION = (CROSVM_ROOT / "tools/impl/dev_container/version").read_text().strip()
 | |
| 
 | |
| try:
 | |
|     docker = cmd(os.environ.get("DOCKER", "docker"))
 | |
| except ValueError:
 | |
|     docker = cmd("podman")
 | |
| 
 | |
| is_podman = docker.executable.name == "podman"
 | |
| 
 | |
| # Enable interactive mode when running in an interactive terminal.
 | |
| TTY_ARGS = "--interactive --tty" if sys.stdin.isatty() else None
 | |
| 
 | |
| 
 | |
| DOCKER_ARGS = [
 | |
|     TTY_ARGS,
 | |
|     # Podman will not share devices when `--privileged` is specified
 | |
|     "--privileged" if not is_podman else None,
 | |
|     # Share crosvm source
 | |
|     f"--volume {quoted(CROSVM_ROOT)}:/workspace:rw",
 | |
|     # Share devices and syslog
 | |
|     "--device /dev/kvm",
 | |
|     "--volume /dev/log:/dev/log",
 | |
|     "--device /dev/net/tun",
 | |
|     "--device /dev/vhost-net",
 | |
|     "--device /dev/vhost-vsock",
 | |
|     # Use tmpfs in the container for faster performance.
 | |
|     "--mount type=tmpfs,destination=/tmp",
 | |
|     # For plugin process jail
 | |
|     "--mount type=tmpfs,destination=/var/empty",
 | |
|     f"gcr.io/crosvm-packages/crosvm_dev:{IMAGE_VERSION}",
 | |
| ]
 | |
| 
 | |
| 
 | |
| def container_revision(container_id: str):
 | |
|     image = docker("container inspect -f {{.Config.Image}}", container_id).stdout()
 | |
|     parts = image.split(":")
 | |
|     assert len(parts) == 2, f"Invalid image name {image}"
 | |
|     return parts[1]
 | |
| 
 | |
| 
 | |
| @arg("command", nargs=argparse.REMAINDER)
 | |
| def main(command: tuple[str, ...], stop: bool = False, hermetic: bool = False):
 | |
|     chdir(CROSVM_ROOT)
 | |
|     container_id = docker(f"ps -q -f name={CONTAINER_NAME}").stdout()
 | |
| 
 | |
|     # Start an interactive shell by default
 | |
|     if not command:
 | |
|         command = ("/bin/bash",)
 | |
| 
 | |
|     command = list(map(quoted, command))
 | |
| 
 | |
|     if stop:
 | |
|         if container_id:
 | |
|             print(f"Stopping dev-container {container_id}.")
 | |
|             docker("rm -f", container_id).fg(quiet=True)
 | |
|         else:
 | |
|             print(f"Dev-container is not running.")
 | |
|         return
 | |
| 
 | |
|     if hermetic:
 | |
|         docker(f"run --rm", *DOCKER_ARGS, *command).fg()
 | |
|     else:
 | |
|         if container_id and container_revision(container_id) != IMAGE_VERSION:
 | |
|             print(f"New image is available. Stopping old container ({container_id}).")
 | |
|             docker("rm -f", container_id).fg(quiet=True)
 | |
|             container_id = None
 | |
| 
 | |
|         if not container_id:
 | |
|             container_id = docker(f"run --detach --name {CONTAINER_NAME}", *DOCKER_ARGS).stdout()
 | |
|             print(f"Started dev-container ({container_id}).")
 | |
|         else:
 | |
|             print(f"Using existing dev-container instance ({container_id}).")
 | |
| 
 | |
|         docker("exec", TTY_ARGS, container_id, *command).fg()
 | |
| 
 | |
| 
 | |
| run_main(main)
 |