def exec(cmd: List[str], workdir: str = "") -> int: """Run a user-supplied command inside the container""" c = _get_client() ctr = _get_ctr(c) if not ctr: common.fatal("Container not running") log = common.logger() log.debug("Running: %r", cmd) # Workaround docker-py ignoring $TERM env = {"TERM": os.getenv("TERM", "xterm")} tty = sys.stdin.isatty() # Based on docker-compose's exec_command implementation. exec_id = c.api.exec_create( ctr.id, cmd, stdin=True, tty=tty, environment=env, workdir=workdir, ) op = dockerpty.ExecOperation(c.api, exec_id, interactive=tty) pty = dockerpty.PseudoTerminal(c.api, op) pty.start() ret = c.api.exec_inspect(exec_id).get("ExitCode") log.debug("Exited with %d", ret) return ret
def start(rm: bool) -> None: """Run docker container""" c = _get_client() try: img = c.images.get(IMAGE) except docker.errors.ImageNotFound: common.fatal("Docker image '%s' not found" % IMAGE) c.containers.run( img, # Allow container to run in background: https://stackoverflow.com/a/36872226/2104168 tty=True, detach=True, auto_remove=rm, name=CONTAINER, volumes={ common.cache_dir(): { "bind": CACHE_MNT, "mode": "ro" }, VOLUME: { "bind": MYSQL_BIN_MNT, "mode": "rw" }, }, tmpfs={ "/root/sandboxes": "exec", }, network_mode="host", )
def stop() -> str: c = _get_client() log = common.logger() ctr = _get_ctr(c) if not ctr: common.fatal("Container not found") if ctr.status == "exited": status = "Already stopped" else: log.debug("Stopping") ctr.stop() status = "Stopped" log.info(status) return status
def replication(version: str, port: int, args: List[str]) -> None: """Deploy 'replication' sandbox. If VERSION is not specified, the default database version is used.""" sb_type = common.TOPO_TYPE_REPLICATION try: d = dbver.get_ver(version) except KeyError: common.fatal("Unknown db version '%s'" % version) sb_name = d.sandbox_name(sb_type) _deploy( sb_name, sb_type, d.ver, "--base-port=%d" % port, "--change-master-options=master_heartbeat_period=1", *args, )
def single(version: str, port: int, args: List[str]) -> None: """Deploy 'single' sandbox. If VERSION is not specified, the default database version is used.""" sb_type = common.TOPO_TYPE_SINGLE try: d = dbver.get_ver(version) except KeyError: common.fatal("Unknown db version '%s'" % version) sb_name = d.sandbox_name(sb_type) _deploy( sb_name, sb_type, d.ver, "--port=%d" % port, "--master", *args, )
def populate_dbver( ctr: docker.models.containers.Container, d: dbver.DBVersion, ) -> None: log = common.prefix_logger("%s: %s" % (d.flavor, d.ver)) retcode, output = _run_cmd( ctr, "stat -c %%F %s" % os.path.join(MYSQL_BIN_MNT, d.ver)) log.debug("Stat sandbox dir [%d]: %s", retcode, output) if retcode == 0: log.debug("Dir already exists in sandbox, skipping") return log.info("Version not already present in sandbox, unpacking from cache") print("Unpacking %s" % d.ver) retcode, output = _run_cmd( ctr, "dbdeployer unpack --verbosity 0 %s" % os.path.join(CACHE_MNT, d.filename()), ) if retcode != 0: common.fatal("Unpacking failed [%d]: %s" % (retcode, output)) else: log.debug("Unpacking [%d]: %r", retcode, output)
def start(rm: bool) -> None: """Start docker container.""" status = docker_env.status() log = common.logger() log.debug("Initial container status: %s", status) if status == docker_env.STATUS_RUNNING: common.fatal("Already running") elif status == docker_env.STATUS_EXITED: common.fatal("Container exists but is stopped") if status not in docker_env.STATUSES: common.fatal("Unsupported container status '%s'" % status) docker_env.start(rm) docker_env.populate_dbvers(dbver.DB_VERSIONS) print("Started")