1
0
mirror of https://github.com/openSUSE/osc.git synced 2024-12-25 09:26:14 +01:00

Merge pull request #1415 from dmach/rootless-kvm-and-podman

Rootless kvm and podman
This commit is contained in:
Daniel Mach 2023-10-04 09:12:18 +02:00 committed by GitHub
commit a16654663b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 71 additions and 47 deletions

View File

@ -4,6 +4,7 @@
# either version 2, or (at your option) any later version.
import fnmatch
import getpass
import glob
import os
import re
@ -605,20 +606,35 @@ def calculate_prj_pac(store, opts, descr):
return project, package
def calculate_build_root(apihost, prj, pac, repo, arch):
buildroot = os.environ.get('OSC_BUILD_ROOT', conf.config['build-root']) \
% {'repo': repo, 'arch': arch, 'project': prj, 'package': pac, 'apihost': apihost}
def calculate_build_root_user(vm_type):
if vm_type in ("kvm", "podman"):
return getpass.getuser()
return None
def calculate_build_root(apihost, prj, pac, repo, arch, user=None):
user = user or ""
dash_user = f"-{user:s}" if user else ""
buildroot = conf.config["build-root"] % {
'apihost': apihost,
'project': prj,
'package': pac,
'repo': repo,
'arch': arch,
"user": user,
"dash_user": dash_user,
}
return buildroot
def build_as_user():
if os.environ.get('OSC_SU_WRAPPER', conf.config['su-wrapper']).split():
if conf.config["su-wrapper"]:
return False
return True
def su_wrapper(cmd):
sucmd = os.environ.get('OSC_SU_WRAPPER', conf.config['su-wrapper']).split()
sucmd = conf.config['su-wrapper'].split()
if sucmd:
if sucmd[0] == 'su':
if sucmd[-1] == '-c':
@ -633,7 +649,12 @@ def run_build(opts, *args):
cmd = [conf.config['build-cmd']]
cmd += args
cmd = su_wrapper(cmd)
if opts.vm_type:
cmd.extend(["--vm-type", opts.vm_type])
user = calculate_build_root_user(opts.vm_type)
if not user:
cmd = su_wrapper(cmd)
if not opts.userootforbuild:
cmd.append('--norootforbuild')
@ -782,18 +803,6 @@ def main(apiurl, store, opts, argv):
if opts.wipe:
buildargs.append("--wipe")
orig_build_root = config['build-root']
# make it possible to override configuration of the rc file
for var in ['OSC_PACKAGECACHEDIR', 'OSC_SU_WRAPPER', 'OSC_BUILD_ROOT']:
val = os.getenv(var)
if val:
if var.startswith('OSC_'):
var = var[4:]
var = var.lower().replace('_', '-')
if var in config:
print('Overriding config value for %s=\'%s\' with \'%s\'' % (var, config[var], val))
config[var] = val
pacname = pac
if pacname == '_repository':
if not opts.local_package:
@ -805,15 +814,8 @@ def main(apiurl, store, opts, argv):
pacname = os.path.splitext(os.path.basename(build_descr))[0]
apihost = urlsplit(apiurl)[1]
if not build_root:
build_root = config['build-root']
if build_root == orig_build_root:
# ENV var was not set
build_root = config['api_host_options'][apiurl].get('build-root', build_root)
try:
build_root = build_root % {'repo': repo, 'arch': arch,
'project': prj, 'package': pacname, 'apihost': apihost}
except KeyError:
pass
user = calculate_build_root_user(vm_type)
build_root = calculate_build_root(apihost, prj, pacname, repo, arch, user)
# We configure sccache after pacname, so that in default cases we can have an sccache for each
# package to prevent cross-cache polutions. It helps to make the local-use case a bit nicer.
@ -1492,7 +1494,9 @@ def main(apiurl, store, opts, argv):
cmd += specialcmdopts + vm_options + buildargs
cmd += [build_descr]
cmd = su_wrapper(cmd)
# determine if we're building under root (user == None) and use su_wrapper accordingly
if calculate_build_root_user(vm_type) is None:
cmd = su_wrapper(cmd)
# change personality, if needed
if hostarch != bi.buildarch and bi.buildarch in change_personality:
@ -1506,7 +1510,12 @@ def main(apiurl, store, opts, argv):
rc = run_external(cmd[0], *cmd[1:])
if rc:
print()
print('The buildroot was:', build_root)
print(f"Build failed with exit code {rc}")
print(f"The buildroot was: {build_root}")
print()
print("Cleaning the build root may fix the problem or allow you to start debugging from a well-defined state:")
print(" - add '--clean' option to your 'osc build' command")
print(" - run 'osc wipe [--vm-type=...]' prior running your 'osc build' command again")
sys.exit(rc)
except KeyboardInterrupt as keyboard_interrupt_exception:
print("keyboard interrupt, killing build ...")

View File

@ -6423,10 +6423,9 @@ Please submit there instead, or use --nodevelproject to force direct submission.
raise oscerr.WrongArgs('Wrong number of arguments.')
# TODO: refactor/unify buildroot calculation and move it to core.py
buildroot = os.environ.get('OSC_BUILD_ROOT', conf.config['build-root'])
apihost = urlsplit(self.get_api_url())[1]
buildroot = buildroot % {'project': project, 'package': package,
'repo': repo, 'arch': arch, 'apihost': apihost}
buildroot = osc_build.calculate_build_root(apihost, project, package, repo, arch)
offset = 0
if opts.offset:
offset = int(opts.offset)
@ -7272,7 +7271,8 @@ Please submit there instead, or use --nodevelproject to force direct submission.
repo, arch, build_descr = args
prj, pac = osc_build.calculate_prj_pac(store, opts, build_descr)
apihost = urlsplit(self.get_api_url())[1]
build_root = osc_build.calculate_build_root(apihost, prj, pac, repo, arch)
user = osc_build.calculate_build_root_user(opts.vm_type)
build_root = osc_build.calculate_build_root(apihost, prj, pac, repo, arch, user)
print(build_root)
return
@ -7285,11 +7285,11 @@ Please submit there instead, or use --nodevelproject to force direct submission.
repo, arch, build_descr = args
prj, pac = osc_build.calculate_prj_pac(store, opts, build_descr)
apihost = urlsplit(self.get_api_url())[1]
build_root = osc_build.calculate_build_root(apihost, prj, pac, repo,
arch)
user = osc_build.calculate_build_root_user(opts.vm_type)
build_root = osc_build.calculate_build_root(apihost, prj, pac, repo, arch, user)
if opts.wipe and not opts.force:
# Confirm delete
print("Really wipe '%s'? [y/N]: " % build_root)
print("Really wipe '%s'? [y/N]: " % build_root, end="")
choice = raw_input().lower()
if choice != 'y':
print('Aborting')

View File

@ -970,17 +970,27 @@ class Options(OscOptions):
ini_key="build-jobs",
) # type: ignore[assignment]
build_type: Optional[str] = Field(
vm_type: Optional[str] = Field(
default=None,
description=textwrap.dedent(
"""
Type of the build environment passed the build tool as the ``--vm-type`` option:
- <empty>: chroot build
- kvm: KVM VM build (needs build-device, build-swap, build-memory)
- xen: XEN VM build (needs build-device, build-swap, build-memory)
- qemu: [EXPERIMENTAL] QEMU VM build
- lxc: [EXPERIMENTAL] LXC build
- <empty> chroot build
- kvm KVM VM build (rootless, needs build-device, build-swap, build-memory)
- xen XEN VM build (needs build-device, build-swap, build-memory)
- qemu [EXPERIMENTAL] QEMU VM build
- lxc [EXPERIMENTAL] LXC build
- uml
- zvm
- openstack
- ec2
- docker
- podman (rootless)
- pvm
- nspawn
See ``build --help`` for more details about supported options.
"""
),
ini_key="build-type",
@ -997,13 +1007,18 @@ class Options(OscOptions):
) # type: ignore[assignment]
build_root: str = Field(
default="/var/tmp/build-root/%(repo)s-%(arch)s",
default="/var/tmp/build-root%(dash_user)s/%(repo)s-%(arch)s",
description=textwrap.dedent(
"""
Path to the build root directory.
Supported substitutions: ``%(repo)s``, ``%(arch)s``, ``%(project)s``, ``%(package)s`` and ``%(apihost)s``
where ``apihost`` is the hostname extracted from the currently used ``apiurl``.
Supported substitutions: ``%(repo)s``, ``%(arch)s``, ``%(project)s``, ``%(package)s``, ``%(apihost)s``, ``%(user)s``, ``%(dash_user)s``
where::
- ``apihost`` is the hostname extracted from the currently used ``apiurl``.
- ``dash_user`` is the username prefixed with a dash. If ``user`` is empty, ``dash_user`` is also empty.
NOTE: The configuration holds the original unexpanded string. Call ``osc.build.get_build_root()`` with proper arguments to retrieve an actual path.
Passed as ``--root <VALUE>`` to the build tool.
"""
@ -1745,7 +1760,7 @@ def get_config(override_conffile=None,
Configure osc.
The configuration options are loaded with the following priority:
1. environment variables: OSC_<uppercase-option>
1. environment variables: OSC_<uppercase_option>
2. override arguments provided to get_config()
3. oscrc config file
"""
@ -1854,7 +1869,7 @@ def get_config(override_conffile=None,
# priority: env, overrides, config
if env_key in os.environ:
value = os.environ["env_key"]
value = os.environ[env_key]
elif name in overrides:
value = overrides.pop(name)
elif ini_key in overrides: