Skip to content

Commit

Permalink
Merge pull request #1415 from dmach/rootless-kvm-and-podman
Browse files Browse the repository at this point in the history
Rootless kvm and podman
  • Loading branch information
dmach committed Oct 4, 2023
2 parents bd14f7e + a694658 commit a166546
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 47 deletions.
67 changes: 38 additions & 29 deletions osc/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
# either version 2, or (at your option) any later version.

import fnmatch
import getpass
import glob
import os
import re
Expand Down Expand Up @@ -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':
Expand All @@ -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')
Expand Down Expand Up @@ -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:
Expand All @@ -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.
Expand Down Expand Up @@ -1492,7 +1494,9 @@ def __str__(self):
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:
Expand All @@ -1506,7 +1510,12 @@ def __str__(self):
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 ...")
Expand Down
14 changes: 7 additions & 7 deletions osc/commandline.py
Original file line number Diff line number Diff line change
Expand Up @@ -6423,10 +6423,9 @@ def do_localbuildlog(self, subcmd, opts, *args):
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)
Expand Down Expand Up @@ -7272,7 +7271,8 @@ def do_build(self, subcmd, opts, *args):
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

Expand All @@ -7285,11 +7285,11 @@ def do_build(self, subcmd, opts, *args):
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')
Expand Down
37 changes: 26 additions & 11 deletions osc/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -970,17 +970,27 @@ def apiurl_aliases(self):
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",
Expand All @@ -997,13 +1007,18 @@ def apiurl_aliases(self):
) # 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.
"""
Expand Down Expand Up @@ -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
"""
Expand Down Expand Up @@ -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:
Expand Down

0 comments on commit a166546

Please sign in to comment.