Bug 1239013 - Bind mount plugin deletes host directory!
Summary: Bind mount plugin deletes host directory!
Keywords:
Status: CLOSED CURRENTRELEASE
Alias: None
Product: Fedora
Classification: Fedora
Component: mock
Version: 22
Hardware: Unspecified
OS: Unspecified
unspecified
high
Target Milestone: ---
Assignee: Miroslav Suchý
QA Contact: Fedora Extras Quality Assurance
URL:
Whiteboard:
: 1260063 (view as bug list)
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2015-07-03 09:12 UTC by Matthew Booth
Modified: 2015-09-04 15:06 UTC (History)
8 users (show)

Fixed In Version: mock-1.2.11
Doc Type: Bug Fix
Doc Text:
Clone Of:
Environment:
Last Closed: 2015-09-04 12:09:32 UTC
Type: Bug
Embargoed:


Attachments (Terms of Use)

Description Matthew Booth 2015-07-03 09:12:34 UTC
Description of problem:

Before I continue, I set the severity to high. Yeah, I know, everybody does that. However, this bug just deleted my working directory, which is pretty severe.

I put the following in a mock config:
config_opts['plugin_conf']['bind_mount_enable'] = True
config_opts['plugin_conf']['bind_mount_opts']['dirs'].append(('/home/mbooth/src/openstack/nova', '/builddir/nova' ))

This dies with:
OSError: [Errno 16] Device or resource busy: '/var/lib/mock/rhos-7.0-rhel-7-candidate-x86_64/root/builddir/tester/nova'

On inspection, /home/mbooth/src/openstack/nova is now empty. It has not had anything bind mounted over it.

The following works, and does not delete the host directory:

config_opts['plugin_conf']['bind_mount_enable'] = True
config_opts['plugin_conf']['bind_mount_opts']['dirs'].append(('/home/mbooth/src/openstack/nova', '/builddir/foo/nova' ))

It appears that if the plugin has to create the parent directory in the chroot, it doesn't delete the host directory.

Don't test this with data you care about.

Version-Release number of selected component (if applicable):
mock-1.2.10-1.fc22.noarch

How reproducible:
Always

Comment 1 Miroslav Suchý 2015-07-04 11:21:24 UTC
It dies (beside the error message) with traceback, which is super helpful for me.
Is it this one?
Traceback (most recent call last):
  File "/usr/sbin/mock", line 831, in <module>
    main()
  File "/usr/lib/python2.7/site-packages/mockbuild/trace_decorator.py", line 84, in trace
    result = func(*args, **kw)
  File "/usr/sbin/mock", line 653, in main
    run_command(options, args, config_opts, commands, buildroot, state)
  File "/usr/lib/python2.7/site-packages/mockbuild/trace_decorator.py", line 84, in trace
    result = func(*args, **kw)
  File "/usr/sbin/mock", line 684, in run_command
    commands.init(do_log=False)
  File "/usr/lib/python2.7/site-packages/mockbuild/trace_decorator.py", line 84, in trace
    result = func(*args, **kw)
  File "/usr/lib/python2.7/site-packages/mockbuild/backend.py", line 123, in init
    self.buildroot.initialize(**kwargs)
  File "/usr/lib/python2.7/site-packages/mockbuild/trace_decorator.py", line 84, in trace
    result = func(*args, **kw)
  File "/usr/lib/python2.7/site-packages/mockbuild/buildroot.py", line 84, in initialize
    self._init(prebuild=prebuild, do_log=do_log)
  File "/usr/lib/python2.7/site-packages/mockbuild/trace_decorator.py", line 84, in trace
    result = func(*args, **kw)
  File "/usr/lib/python2.7/site-packages/mockbuild/buildroot.py", line 146, in _init
    self._make_build_user()
  File "/usr/lib/python2.7/site-packages/mockbuild/trace_decorator.py", line 84, in trace
    result = func(*args, **kw)
  File "/usr/lib/python2.7/site-packages/mockbuild/buildroot.py", line 234, in _make_build_user
    selinux=self.selinux, exclude=excluded)
  File "/usr/lib/python2.7/site-packages/mockbuild/trace_decorator.py", line 84, in trace
    result = func(*args, **kw)
  File "/usr/lib/python2.7/site-packages/mockbuild/util.py", line 135, in rmtree
    rmtree(fullname, selinux=selinux, exclude=exclude)
  File "/usr/lib/python2.7/site-packages/mockbuild/trace_decorator.py", line 84, in trace
    result = func(*args, **kw)
  File "/usr/lib/python2.7/site-packages/mockbuild/util.py", line 144, in rmtree
    os.rmdir(path)
OSError: [Errno 16] Device or resource busy: '/var/lib/mock/fedora-22-x86_64/root/builddir/nova'


The problem seems to be that to keep reproducibility we remove /builddir/* in chroot before we start building (there were good reason for that). We only preserve:

# The build user's homedir is partially cleaned up even when --no-clean is
# specified in order to prevent garbage from previous builds from altering
# succesive builds. Mock can be configured to exclude certain files/directories
# from this. Default is SOURCES directory to support nosrc rpms. Paths are
# relative to build user's homedir
# config_opts['exclude_from_homedir_cleanup'] = ['build/SOURCES']

It seems that we mount ['bind_mount_opts']['dirs'] first and then we remove /builddir/, therefore if you mount something there is is deleted :(
I will try to move mounting of those directories after that deleting. That should fix this bug.

Comment 2 Miroslav Suchý 2015-07-04 11:35:49 UTC
Notes for myself - this should work too:
--- /usr/lib/python2.7/site-packages/mockbuild/util.py.orig     2015-07-04 07:34:30.678596660 -0400
+++ /usr/lib/python2.7/site-packages/mockbuild/util.py  2015-07-04 07:34:39.267596410 -0400
@@ -122,8 +122,6 @@
     while try_again:
         try_again = False
         try:
+            if os.path.ismount(path):
+                continue
             names = os.listdir(path)
             for name in names:
                 fullname = os.path.join(path, name)

But I should check other calling of rmtree() first.

Comment 3 Matthew Booth 2015-07-06 09:12:22 UTC
(In reply to Miroslav Suchý from comment #1)
> It dies (beside the error message) with traceback, which is super helpful
> for me.
> Is it this one?
> Traceback (most recent call last):
>   File "/usr/sbin/mock", line 831, in <module>
>     main()
>   File "/usr/lib/python2.7/site-packages/mockbuild/trace_decorator.py", line
> 84, in trace
>     result = func(*args, **kw)
>   File "/usr/sbin/mock", line 653, in main
>     run_command(options, args, config_opts, commands, buildroot, state)
>   File "/usr/lib/python2.7/site-packages/mockbuild/trace_decorator.py", line
> 84, in trace
>     result = func(*args, **kw)
>   File "/usr/sbin/mock", line 684, in run_command
>     commands.init(do_log=False)
>   File "/usr/lib/python2.7/site-packages/mockbuild/trace_decorator.py", line
> 84, in trace
>     result = func(*args, **kw)
>   File "/usr/lib/python2.7/site-packages/mockbuild/backend.py", line 123, in
> init
>     self.buildroot.initialize(**kwargs)
>   File "/usr/lib/python2.7/site-packages/mockbuild/trace_decorator.py", line
> 84, in trace
>     result = func(*args, **kw)
>   File "/usr/lib/python2.7/site-packages/mockbuild/buildroot.py", line 84,
> in initialize
>     self._init(prebuild=prebuild, do_log=do_log)
>   File "/usr/lib/python2.7/site-packages/mockbuild/trace_decorator.py", line
> 84, in trace
>     result = func(*args, **kw)
>   File "/usr/lib/python2.7/site-packages/mockbuild/buildroot.py", line 146,
> in _init
>     self._make_build_user()
>   File "/usr/lib/python2.7/site-packages/mockbuild/trace_decorator.py", line
> 84, in trace
>     result = func(*args, **kw)
>   File "/usr/lib/python2.7/site-packages/mockbuild/buildroot.py", line 234,
> in _make_build_user
>     selinux=self.selinux, exclude=excluded)
>   File "/usr/lib/python2.7/site-packages/mockbuild/trace_decorator.py", line
> 84, in trace
>     result = func(*args, **kw)
>   File "/usr/lib/python2.7/site-packages/mockbuild/util.py", line 135, in
> rmtree
>     rmtree(fullname, selinux=selinux, exclude=exclude)
>   File "/usr/lib/python2.7/site-packages/mockbuild/trace_decorator.py", line
> 84, in trace
>     result = func(*args, **kw)
>   File "/usr/lib/python2.7/site-packages/mockbuild/util.py", line 144, in
> rmtree
>     os.rmdir(path)
> OSError: [Errno 16] Device or resource busy:
> '/var/lib/mock/fedora-22-x86_64/root/builddir/nova'

Yup.

> The problem seems to be that to keep reproducibility we remove /builddir/*
> in chroot before we start building (there were good reason for that). We
> only preserve:
> 
> # The build user's homedir is partially cleaned up even when --no-clean is
> # specified in order to prevent garbage from previous builds from altering
> # succesive builds. Mock can be configured to exclude certain
> files/directories
> # from this. Default is SOURCES directory to support nosrc rpms. Paths are
> # relative to build user's homedir
> # config_opts['exclude_from_homedir_cleanup'] = ['build/SOURCES']
> 
> It seems that we mount ['bind_mount_opts']['dirs'] first and then we remove
> /builddir/, therefore if you mount something there is is deleted :(
> I will try to move mounting of those directories after that deleting. That
> should fix this bug.

Thanks for looking at this.

Comment 4 Miroslav Suchý 2015-07-07 14:53:33 UTC
Fixed by commit:
* 101d694  exclude our mountpoints from deleting when deleting homedir in chroot [RHBZ#1239013]

Comment 5 Miroslav Suchý 2015-09-04 11:07:17 UTC
*** Bug 1260063 has been marked as a duplicate of this bug. ***

Comment 6 Dennis Jacobfeuerborn 2015-09-04 11:22:19 UTC
I can't find the commit in any of the branches here:
https://git.fedorahosted.org/cgit/mock.git/

I want to test if this fixes my issue so is this commit the change you mentioned in comment #2 or is this a different fix?

Comment 7 Miroslav Suchý 2015-09-04 12:09:32 UTC
https://git.fedorahosted.org/cgit/mock.git/commit/?id=101d694a68ca2bd517449b1e2981f6e5a79a3130&h=master

And as I see it should be already in mock-1.2.11

Comment 8 Dennis Jacobfeuerborn 2015-09-04 15:06:22 UTC
Yes, I didn't pay attention to the date and though it must have been added very recently. 

Why was my other bug marked as a duplicate of this one though? I'm running version 1.2.12 and have the problem mentioned in the original bug despite the presence of the patch mentioned in this one.


Note You need to log in before you can comment on or make changes to this bug.