Exemple #1
0
def main():
    "Main executable entry point."

    # initial sanity check for correct invocation method
    rootcheck()

    # drop unprivileged to parse args, etc.
    #   uidManager saves current real uid/gid which are unprivileged (callers)
    #   due to suid helper, our current effective uid is 0
    #   also supports being run by sudo
    #
    #   setuid wrapper has real uid = unpriv,  effective uid = 0
    #   sudo sets real/effective = 0, and sets env vars
    #   setuid wrapper clears environment, so there wont be any conflict between these two

    mockgid = grp.getgrnam('mock').gr_gid
    uidManager = setup_uid_manager(mockgid)

    # go unpriv only when root to make --help etc work for non-mock users
    if os.geteuid() == 0:
        uidManager.dropPrivsTemp()

    (options, args) = command_parse()
    if options.printrootpath or options.list_snapshots:
        options.verbose = 0

    # config path -- can be overridden on cmdline
    config_path = MOCKCONFDIR
    if options.configdir:
        config_path = options.configdir

    config_opts = util.load_config(config_path, options.chroot, uidManager,
                                   __VERSION__, PKGPYTHONDIR)
    config_opts['config_path'] = config_path

    # cmdline options override config options
    util.set_config_opts_per_cmdline(config_opts, options, args)

    # allow a different mock group to be specified
    if config_opts['chrootgid'] != mockgid:
        uidManager.restorePrivs()
        os.setgroups((mockgid, config_opts['chrootgid']))
        uidManager.dropPrivsTemp()

    # verify that our unprivileged uid is in the mock group
    groupcheck(uidManager.unprivGid, config_opts['chrootgid'])

    # configure logging
    setup_logging(config_path, config_opts, options)

    # verify that we're not trying to build an arch that we can't
    check_arch_combination(config_opts['rpmbuild_arch'], config_opts)

    # security cleanup (don't need/want this in the chroot)
    if 'SSH_AUTH_SOCK' in os.environ:
        del os.environ['SSH_AUTH_SOCK']

    # elevate privs
    uidManager.become_user_without_push(0, 0)

    # do whatever we're here to do
    py_version = '{0}.{1}.{2}'.format(*sys.version_info[:3])
    log.info("mock.py version %s starting (python version = %s)...",
             __VERSION__, py_version)
    state = State()
    plugins = Plugins(config_opts, state)

    # outer buildroot to bootstrap the installation - based on main config with some differences
    bootstrap_buildroot = None
    if config_opts['use_bootstrap_container']:
        # first take a copy of the config so we can make some modifications
        bootstrap_buildroot_config = config_opts.copy()
        # copy plugins configuration so we get a separate deep copy
        bootstrap_buildroot_config['plugin_conf'] = config_opts[
            'plugin_conf'].copy()  # pylint: disable=no-member
        # add '-bootstrap' to the end of the root name
        bootstrap_buildroot_config[
            'root'] = bootstrap_buildroot_config['root'] + '-bootstrap'
        # share a yum cache to save downloading everything twice
        bootstrap_buildroot_config['plugin_conf']['yum_cache_opts']['dir'] = \
            "%(cache_topdir)s/" + config_opts['root'] + "/%(package_manager)s_cache/"
        # we don't want to affect the bootstrap.config['nspawn_args'] array, deep copy
        bootstrap_buildroot_config['nspawn_args'] = config_opts.get(
            'nspawn_args', []).copy()

        # allow bootstrap buildroot to access the network for getting packages
        bootstrap_buildroot_config['rpmbuild_networking'] = True
        bootstrap_buildroot_config['use_host_resolv'] = True
        util.setup_host_resolv(bootstrap_buildroot_config)

        # use system_*_command for bootstrapping
        bootstrap_buildroot_config['yum_command'] = bootstrap_buildroot_config[
            'system_yum_command']
        bootstrap_buildroot_config['dnf_command'] = bootstrap_buildroot_config[
            'system_dnf_command']

        bootstrap_buildroot_state = State(bootstrap=True)
        bootstrap_plugins = Plugins(bootstrap_buildroot_config,
                                    bootstrap_buildroot_state)
        bootstrap_buildroot = Buildroot(bootstrap_buildroot_config,
                                        uidManager,
                                        bootstrap_buildroot_state,
                                        bootstrap_plugins,
                                        is_bootstrap=True)
        # this bit of config is needed after we have created the bootstrap buildroot since we need to
        # query pkg_manager to know which manager is in use
        bootstrap_buildroot.config[
            'chroot_setup_cmd'] = bootstrap_buildroot.pkg_manager.install_command
        # override configs for bootstrap_*
        for k in bootstrap_buildroot.config.copy():
            if "bootstrap_" + k in bootstrap_buildroot.config:
                bootstrap_buildroot.config[k] = bootstrap_buildroot_config[
                    "bootstrap_" + k]
                del bootstrap_buildroot.config["bootstrap_" + k]

    # this changes config_opts['nspawn_args'], so do it after initializing
    # bootstrap chroot to not inherit the changes there
    util.setup_host_resolv(config_opts)

    buildroot = Buildroot(config_opts, uidManager, state, plugins,
                          bootstrap_buildroot)
    commands = Commands(config_opts, uidManager, plugins, state, buildroot,
                        bootstrap_buildroot)

    if config_opts['use_bootstrap_container']:
        bootstrap_buildroot.config[
            'chroot_setup_cmd'] = buildroot.pkg_manager.install_command

    state.start("run")

    if options.printrootpath:
        print(buildroot.make_chroot_path(''))
        sys.exit(0)

    if options.list_snapshots:
        plugins.call_hooks('list_snapshots', required=True)
        if bootstrap_buildroot is not None:
            bootstrap_buildroot.plugins.call_hooks('list_snapshots',
                                                   required=True)
        sys.exit(0)

    # dump configuration to log
    log.debug("mock final configuration:")
    for k, v in list(config_opts.items()):
        log.debug("    %s:  %s", k, v)

    os.umask(0o02)
    os.environ["HOME"] = buildroot.homedir

    # New namespace starting from here
    unshare_namespace(config_opts)

    if config_opts['hostname']:
        util.sethostname(config_opts['hostname'])

    # set personality (ie. setarch)
    util.condPersonality(config_opts['target_arch'])

    result = 0
    try:
        result = run_command(options, args, config_opts, commands, buildroot,
                             state)
    except mockbuild.exception.Error:
        result = 1
    finally:
        buildroot.uid_manager.becomeUser(0, 0)
        buildroot.finalize()
        if bootstrap_buildroot is not None:
            bootstrap_buildroot.finalize()
        buildroot.uid_manager.restorePrivs()
    return result
Exemple #2
0
def main():
    "Main executable entry point."

    # initial sanity check for correct invocation method
    rootcheck()

    # drop unprivileged to parse args, etc.
    #   uidManager saves current real uid/gid which are unprivileged (callers)
    #   due to suid helper, our current effective uid is 0
    #   also supports being run by sudo
    #
    #   setuid wrapper has real uid = unpriv,  effective uid = 0
    #   sudo sets real/effective = 0, and sets env vars
    #   setuid wrapper clears environment, so there wont be any conflict between these two

    mockgid = grp.getgrnam('mock').gr_gid
    uidManager = setup_uid_manager(mockgid)

    # go unpriv only when root to make --help etc work for non-mock users
    if os.geteuid() == 0:
        uidManager.dropPrivsTemp()

    (options, args) = command_parse()
    if options.printrootpath or options.list_snapshots:
        options.verbose = 0

    # config path -- can be overridden on cmdline
    config_path = MOCKCONFDIR
    if options.configdir:
        config_path = options.configdir

    config_opts = util.load_config(config_path, options.chroot, uidManager, __VERSION__, PKGPYTHONDIR)

    # cmdline options override config options
    util.set_config_opts_per_cmdline(config_opts, options, args)

    util.subscription_redhat_init(config_opts)

    # allow a different mock group to be specified
    if config_opts['chrootgid'] != mockgid:
        uidManager.restorePrivs()
        os.setgroups((mockgid, config_opts['chrootgid']))
        uidManager.dropPrivsTemp()

    # verify that our unprivileged uid is in the mock group
    groupcheck(uidManager.unprivGid, config_opts['chrootgid'])

    # configure logging
    setup_logging(config_path, config_opts, options)

    # verify that we're not trying to build an arch that we can't
    check_arch_combination(config_opts['rpmbuild_arch'], config_opts)

    # security cleanup (don't need/want this in the chroot)
    if 'SSH_AUTH_SOCK' in os.environ:
        del os.environ['SSH_AUTH_SOCK']

    # elevate privs
    uidManager.become_user_without_push(0, 0)

    # do whatever we're here to do
    py_version = '{0}.{1}.{2}'.format(*sys.version_info[:3])
    log.info("mock.py version %s starting (python version = %s)...",
             __VERSION__, py_version)
    state = State()
    plugins = Plugins(config_opts, state)

    # When scrubbing all, we also want to scrub a bootstrap chroot
    if options.scrub:
        config_opts['use_bootstrap'] = True

    # outer buildroot to bootstrap the installation - based on main config with some differences
    bootstrap_buildroot = None
    if config_opts['use_bootstrap']:
        # first take a copy of the config so we can make some modifications
        bootstrap_buildroot_config = config_opts.copy()
        # copy plugins configuration so we get a separate deep copy
        bootstrap_buildroot_config['plugin_conf'] = \
            copy.deepcopy(config_opts['plugin_conf'])  # pylint: disable=no-member
        # add '-bootstrap' to the end of the root name
        bootstrap_buildroot_config['root'] = bootstrap_buildroot_config['root'] + '-bootstrap'
        # don't share root cache tarball
        bootstrap_buildroot_config['plugin_conf']['root_cache_opts']['dir'] = \
            "{{cache_topdir}}/" + bootstrap_buildroot_config['root'] + "/root_cache/"
        # we don't want to affect the bootstrap.config['nspawn_args'] array, deep copy
        bootstrap_buildroot_config['nspawn_args'] = config_opts.get('nspawn_args', []).copy()

        # allow bootstrap buildroot to access the network for getting packages
        bootstrap_buildroot_config['rpmbuild_networking'] = True
        bootstrap_buildroot_config['use_host_resolv'] = True
        util.setup_host_resolv(bootstrap_buildroot_config)

        # use system_*_command for bootstrapping
        bootstrap_buildroot_config['yum_command'] = bootstrap_buildroot_config['system_yum_command']
        bootstrap_buildroot_config['dnf_command'] = bootstrap_buildroot_config['system_dnf_command']

        # disable updating bootstrap chroot
        bootstrap_buildroot_config['update_before_build'] = False

        bootstrap_buildroot_state = State(bootstrap=True)
        bootstrap_plugins = Plugins(bootstrap_buildroot_config, bootstrap_buildroot_state)
        bootstrap_buildroot = Buildroot(bootstrap_buildroot_config,
                                        uidManager, bootstrap_buildroot_state, bootstrap_plugins,
                                        is_bootstrap=True)
        # this bit of config is needed after we have created the bootstrap buildroot since we need to
        # query pkg_manager to know which manager is in use
        bootstrap_buildroot.config['chroot_setup_cmd'] = bootstrap_buildroot.pkg_manager.install_command
        # override configs for bootstrap_*
        for k in bootstrap_buildroot.config.copy():
            if "bootstrap_" + k in bootstrap_buildroot.config:
                bootstrap_buildroot.config[k] = bootstrap_buildroot_config["bootstrap_" + k]
                del bootstrap_buildroot.config["bootstrap_" + k]

        if config_opts['redhat_subscription_required']:
            key_dir = '/etc/pki/entitlement'
            chroot_dir = bootstrap_buildroot.make_chroot_path(key_dir)
            mount_point = BindMountPoint(srcpath=key_dir, bindpath=chroot_dir)
            bootstrap_buildroot.mounts.add(mount_point)

    # this changes config_opts['nspawn_args'], so do it after initializing
    # bootstrap chroot to not inherit the changes there
    util.setup_host_resolv(config_opts)

    buildroot = Buildroot(config_opts, uidManager, state, plugins, bootstrap_buildroot)

    if bootstrap_buildroot is not None:
        # add the extra bind mount to the outer chroot
        inner_mount = bootstrap_buildroot.make_chroot_path(buildroot.make_chroot_path())

        # Hide re-mounted chroot from host by private tmpfs.
        buildroot.mounts.managed_mounts.append(
            FileSystemMountPoint(filetype='tmpfs',
                                 device='hide_root_in_bootstrap',
                                 path=inner_mount,
                                 options="private"))
        buildroot.mounts.managed_mounts.append(
            BindMountPoint(buildroot.make_chroot_path(), inner_mount,
                           recursive=True, options="private"))

    signal.signal(signal.SIGTERM, partial(handle_signals, buildroot))
    signal.signal(signal.SIGPIPE, partial(handle_signals, buildroot))
    signal.signal(signal.SIGHUP, partial(handle_signals, buildroot))

    # postprocess option arguments for bootstrap
    if options.mode in ['installdeps', 'install']:
        args = [buildroot.file_on_cmdline(arg) for arg in args]

    log.info("Signal handler active")
    commands = Commands(config_opts, uidManager, plugins, state, buildroot, bootstrap_buildroot)

    if config_opts['use_bootstrap']:
        bootstrap_buildroot.config['chroot_setup_cmd'] = buildroot.pkg_manager.install_command

    state.start("run")

    if options.printrootpath:
        print(buildroot.make_chroot_path(''))
        sys.exit(0)

    if options.list_snapshots:
        plugins.call_hooks('list_snapshots', required=True)
        if bootstrap_buildroot is not None:
            bootstrap_buildroot.plugins.call_hooks('list_snapshots', required=True)
        sys.exit(0)

    # dump configuration to log
    log.debug("mock final configuration:")
    for k, v in list(config_opts.items()):
        log.debug("    %s:  %s", k, v)

    os.umask(0o02)
    os.environ["HOME"] = buildroot.homedir

    # New namespace starting from here
    unshare_namespace(config_opts)

    if config_opts['hostname']:
        util.sethostname(config_opts['hostname'])

    # set personality (ie. setarch)
    util.condPersonality(config_opts['target_arch'])

    result = 0
    try:
        result = run_command(options, args, config_opts, commands, buildroot, state)
    finally:
        buildroot.finalize()
        if bootstrap_buildroot is not None:
            bootstrap_buildroot.finalize()
    return result