Exemple #1
0
def destroy(buildname: str):
    """Destroy an existing build.

    Will always remove the existing configuration for build BUILDNAME.
    Optionally, may also remove existing an existing build, and the build's
    containers.

    BUILDNAME is the name of the build to be destroyed.
    """

    if not config.build_exists(buildname):
        pinfo(f"build '{buildname}' does not exist")
        sys.exit(errno.ENOENT)

    if not click.confirm(
            swarn(f"Are you sure you want to remove build '{buildname}?"),
            default=False):
        sys.exit(0)

    remove_build = click.confirm(
        swarn("Do you want to remove the build directory?"), default=False)
    remove_containers = click.confirm(
        swarn("Do you want to remove the containers?"), default=False)
    success: bool = \
        Build.destroy(config, buildname,
                      remove_install=remove_build,
                      remove_containers=remove_containers)

    if not success:
        perror(f"error destroying build '{buildname}'; aborted.")
    else:
        pinfo(f"destroyed build '{buildname}'")
Exemple #2
0
def _is_alive_registry_url(url: str) -> bool:
    pinfo(f"Trying to reach registry at {url}...")
    try:
        conn = HTTPConnection(url, timeout=30)
        conn.request("GET", "/v2/")
    except Exception as e:
        perror(f"error: {str(e)}")
        return False
    return True
Exemple #3
0
def shell(buildname: str):
    """Drop into shell of build's latest container.

    BUILDNAME is the name of the build for which we want a shell.
    """
    if not config.build_exists(buildname):
        perror(f"build '{buildname}' does not exist.")
        sys.exit(errno.ENOENT)

    if not Images.run_shell(buildname):
        perror(f"unable to run shell for build '{buildname}'")
        sys.exit(errno.EINVAL)
Exemple #4
0
def _init_tree() -> Tuple[Path, Path]:
    tree_root_dir = _prompt_directory("Builder tree directory",
                                      must_exist=False)
    if not tree_root_dir:
        perror("Must specify a directory")
        sys.exit(errno.EINVAL)

    tree_path = Path(tree_root_dir)
    installs_path = tree_path.joinpath("installs")
    ccache_path = tree_path.joinpath("ccache")

    return (installs_path, ccache_path)
Exemple #5
0
def _prompt_directory(prompt_text: str, must_exist=True) -> Path:
    path = None
    while True:
        pathstr = click.prompt(sinfo(prompt_text), type=str, default=None)
        path = Path(pathstr).absolute()
        if must_exist and not path.exists():
            perror("error: path must exist")
            continue

        if path.exists() and not path.is_dir():
            perror("error: path is not a directory.")
            continue
        break
    return path
Exemple #6
0
def build(buildname: str, nuke_install: bool, with_fresh_build: bool):
    """
    Starts a new build.

    Will run a new build for the sources specified by BUILDNAME, and
    will create an image, either original or incremental.

    BUILDNAME is the name of the build being built.

    """
    if not config.build_exists(buildname):
        perror(f"error: build '{buildname}' does not exist.")
        sys.exit(errno.ENOENT)

    if nuke_install:
        sure = click.confirm(
            swarn("Are you sure you want to remove the install directory?"),
            default=False)
        if not sure:
            sys.exit(1)

    if with_fresh_build:
        sure = click.confirm(
            swarn("Are you sure you want to run a fresh build?"),
            default=False)
        if not sure:
            sys.exit(1)

    build: Build = Build(config, buildname)
    assert build._vendor
    assert build._release
    assert build._sources
    if not ImageChecker.check_has_images(build._vendor, build._release):
        # create build images.
        pwarn("=> missing build images; creating...")
        vendor: str = build._vendor
        release: str = build._release
        sp: Path = Path(build._sources)
        if not check_create_images(vendor, release, sp):
            perror("=> error creating images for build")
            sys.exit(errno.ENOTRECOVERABLE)

    Build.build(config,
                buildname,
                nuke_install=nuke_install,
                with_fresh_build=with_fresh_build)
Exemple #7
0
def _prompt_ccache_size() -> str:
    ccache_size = None
    while True:
        ccache_size = click.prompt(sinfo("ccache size (in G, T)"),
                                   type=str,
                                   default="10G")
        match = re.match(r'^[ ]*([0-9]+)[ ]*([GT])[ ]*$', ccache_size.upper())
        if not match or len(match.groups()) != 2:
            perror("invalid size format.")
            continue
        size = int(match.group(1))
        unit = match.group(2)
        if size <= 0:
            perror("invalid value for size; must be greater than zero.")
            continue
        elif size < 2 and unit == 'G':
            pwarn("size may be too small to cache one build.")
        ccache_size = f"{size}{unit}"
        break
    return ccache_size
Exemple #8
0
def build_info(buildname: str):
    """Show build information, including images.

    Will show information about a given build, including its configuration and
    existing images.

    BUILDNAME   name of build to show info for.
    """
    if not config.build_exists(buildname):
        perror(f"build '{buildname}' does not exist.")
        sys.exit(errno.ENOENT)

    build = Build(config, buildname)
    build.print(with_prefix=True, verbose=True)

    images: List[ContainerImage] = Images.find_build_images(buildname)
    if len(images) == 0:
        perror(f"no images for build '{buildname}'")
        sys.exit(0)

    img: ContainerImage
    for img in images:
        img.print()
Exemple #9
0
def create(buildname: str,
           vendor: str,
           release: str,
           sourcedir: str,
           with_debug: bool,
           with_tests: bool,
           build_base_image: bool,
           clone_from_repo: str = None,
           clone_from_branch: str = None):
    """Create a new build; does not build.

    BUILDNAME is the name for the build.\n
    VENDOR is the vendor to be used for this build.\n
    RELEASE is the release to be used for this build.\n
    SOURCEDIR is the directory where sources for this build are expected.\n
    """
    if config.build_exists(buildname):
        perror(f"build '{buildname}' already exists.")
        sys.exit(errno.EEXIST)

    # check whether a build image for <vendor>:<release> exists

    do_build_image: bool = False
    if not ImageChecker.check_has_images(vendor, release):
        pwarn("=> required images not found, building at a later stage")
        do_build_image = True

    sourcepath: Path = Path(sourcedir).resolve()

    if clone_from_repo is not None:
        if len(clone_from_repo) == 0:
            perror("error: valid git repository required.")
            sys.exit(errno.EINVAL)

        extra_opts = ""
        if clone_from_branch is not None:
            if len(clone_from_branch) == 0:
                perror("error: valid branch required.")
                sys.exit(errno.EINVAL)
            extra_opts += f"-b {clone_from_branch}"

        if sourcepath.exists():
            perror(f"error: SOURCEDIR exists at {sourcepath}.")
            perror("can't clone to an existing directory")
            sys.exit(errno.EEXIST)

        cmd = f"git clone {extra_opts} {clone_from_repo} {sourcedir}"
        proc = subprocess.run(shlex.split(cmd))
        if proc.returncode != 0:
            perror("error: unable to clone repository")
            sys.exit(proc.returncode)

    elif clone_from_branch is not None:
        perror("error: --clone-from-branch requires --clone-from-repo")
        sys.exit(errno.EINVAL)

    # check whether sourcedir is a ceph repository
    if not sourcepath.exists() or not sourcepath.is_dir():
        perror("error: sourcedir expected to exist as a directory")
        sys.exit(errno.ENOTDIR)

    specfile = sourcepath.joinpath('ceph.spec.in')
    if not specfile.exists():
        perror("error: sourcedir is not a ceph git source tree")
        sys.exit(errno.EINVAL)

    if do_build_image:
        pinfo(f"=> building images for vendor {vendor} release {release}")
        if not check_create_images(vendor, release, sourcepath):
            perror("=> unable to create images; abort.")
            sys.exit(errno.ENOTRECOVERABLE)

    build = Build.create(config,
                         buildname,
                         vendor,
                         release,
                         sourcedir,
                         with_debug=with_debug,
                         with_tests=with_tests)
    build.print()
    pokay(f"created build '{buildname}'")