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
Beispiel #4
0
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,
    )
Beispiel #5
0
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)
Beispiel #7
0
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")