"""pivot_root way to mount container
"""

import logging
import os

from treadmill import fs
from treadmill.syscall import pivot_root as proot
from treadmill.fs import linux as fs_linux

_LOGGER = logging.getLogger(__name__)

# we need to mount move /sys/xxxx
MOVE_MOUNTS = [
    'proc',
]
PIVOT_PATH = '.old-pivot'


def _umount_with_detach(entry_path):
    """umount the path,
    if failed with device busy, we detach (lazy umount) it
    """
    try:
        fs_linux.umount_filesystem(entry_path)
    except OSError as err:
        _LOGGER.warning('Failed to umount %s: %s',
                        entry_path, err)
        # 16 means device busy
        if err.errno == 16:
            try:
                fs_linux.umount_filesystem(entry_path, lazy=True)
            except OSError as err:
                _LOGGER.warning('Failed to lazy umount %s: %s',
                                entry_path, err)


def make_root(root_dir):
    """create container root by calling pivot_root
    """
    newroot_norm = fs.norm_safe(root_dir)
    old_pivot = os.path.join(newroot_norm, PIVOT_PATH)
    fs.mkdir_safe(old_pivot)

    proot.pivot_root(newroot_norm, old_pivot)
    # return list of mount to be umounted from down to top
    to_umount = move_mounts(os.path.sep + PIVOT_PATH)

    # umount entries from down to top
    for mount_entry in to_umount:
        _umount_with_detach(mount_entry.target)


def _move_mount(original_root, mount_entry):
    """mount move a single entry from original_root to new root
    """
    target = mount_entry.target[len(original_root):]
    _LOGGER.info('Mount move %r => %s', mount_entry, target)

    try:
        fs_linux.mount_move(target, mount_entry.target)
    except FileNotFoundError as err:
        _LOGGER.warning('missing mountpoint %r: %s',
                        mount_entry.target, err)


def move_mounts(original_root):
    """Move mounts from pivot_root original root to new root
    """

    _LOGGER.info('Moving all mounts in %r', MOVE_MOUNTS)
    # we may have mutiple /proc mounts, we mount the lowest in container
    full_path_move_mounts = [
        os.path.join(original_root, mount)
        for mount in MOVE_MOUNTS
    ]

    moved = {}

    mountinfo = os.path.join(
        original_root, 'proc', 'self', 'mountinfo'
    )
    sorted_mounts = fs_linux.generate_sorted_mounts(mountinfo)
    to_umount = []

    for mount_entry in sorted_mounts:
        # if not starting with original_root, the mount is added by us before
        if not mount_entry.target.startswith(original_root):
            continue

        if mount_entry.target in full_path_move_mounts:
            if mount_entry.target in moved:
                to_umount.append(mount_entry)
            else:
                _move_mount(original_root, mount_entry)
                moved[mount_entry.target] = mount_entry
        else:
            # we remove all other entries not matching move mounts
            to_umount.append(mount_entry)

    return to_umount

ff8f26108d4a0c54818792590c2f7cf54dba5399
<mask token>


def make_root(root_dir):
    """create container root by calling pivot_root
    """
    newroot_norm = fs.norm_safe(root_dir)
    old_pivot = os.path.join(newroot_norm, PIVOT_PATH)
    fs.mkdir_safe(old_pivot)
    proot.pivot_root(newroot_norm, old_pivot)
    to_umount = move_mounts(os.path.sep + PIVOT_PATH)
    for mount_entry in to_umount:
        _umount_with_detach(mount_entry.target)


def _move_mount(original_root, mount_entry):
    """mount move a single entry from original_root to new root
    """
    target = mount_entry.target[len(original_root):]
    _LOGGER.info('Mount move %r => %s', mount_entry, target)
    try:
        fs_linux.mount_move(target, mount_entry.target)
    except FileNotFoundError as err:
        _LOGGER.warning('missing mountpoint %r: %s', mount_entry.target, err)


def move_mounts(original_root):
    """Move mounts from pivot_root original root to new root
    """
    _LOGGER.info('Moving all mounts in %r', MOVE_MOUNTS)
    full_path_move_mounts = [os.path.join(original_root, mount) for mount in
        MOVE_MOUNTS]
    moved = {}
    mountinfo = os.path.join(original_root, 'proc', 'self', 'mountinfo')
    sorted_mounts = fs_linux.generate_sorted_mounts(mountinfo)
    to_umount = []
    for mount_entry in sorted_mounts:
        if not mount_entry.target.startswith(original_root):
            continue
        if mount_entry.target in full_path_move_mounts:
            if mount_entry.target in moved:
                to_umount.append(mount_entry)
            else:
                _move_mount(original_root, mount_entry)
                moved[mount_entry.target] = mount_entry
        else:
            to_umount.append(mount_entry)
    return to_umount

<mask token>


def _umount_with_detach(entry_path):
    """umount the path,
    if failed with device busy, we detach (lazy umount) it
    """
    try:
        fs_linux.umount_filesystem(entry_path)
    except OSError as err:
        _LOGGER.warning('Failed to umount %s: %s', entry_path, err)
        if err.errno == 16:
            try:
                fs_linux.umount_filesystem(entry_path, lazy=True)
            except OSError as err:
                _LOGGER.warning('Failed to lazy umount %s: %s', entry_path, err
                    )


def make_root(root_dir):
    """create container root by calling pivot_root
    """
    newroot_norm = fs.norm_safe(root_dir)
    old_pivot = os.path.join(newroot_norm, PIVOT_PATH)
    fs.mkdir_safe(old_pivot)
    proot.pivot_root(newroot_norm, old_pivot)
    to_umount = move_mounts(os.path.sep + PIVOT_PATH)
    for mount_entry in to_umount:
        _umount_with_detach(mount_entry.target)


def _move_mount(original_root, mount_entry):
    """mount move a single entry from original_root to new root
    """
    target = mount_entry.target[len(original_root):]
    _LOGGER.info('Mount move %r => %s', mount_entry, target)
    try:
        fs_linux.mount_move(target, mount_entry.target)
    except FileNotFoundError as err:
        _LOGGER.warning('missing mountpoint %r: %s', mount_entry.target, err)


def move_mounts(original_root):
    """Move mounts from pivot_root original root to new root
    """
    _LOGGER.info('Moving all mounts in %r', MOVE_MOUNTS)
    full_path_move_mounts = [os.path.join(original_root, mount) for mount in
        MOVE_MOUNTS]
    moved = {}
    mountinfo = os.path.join(original_root, 'proc', 'self', 'mountinfo')
    sorted_mounts = fs_linux.generate_sorted_mounts(mountinfo)
    to_umount = []
    for mount_entry in sorted_mounts:
        if not mount_entry.target.startswith(original_root):
            continue
        if mount_entry.target in full_path_move_mounts:
            if mount_entry.target in moved:
                to_umount.append(mount_entry)
            else:
                _move_mount(original_root, mount_entry)
                moved[mount_entry.target] = mount_entry
        else:
            to_umount.append(mount_entry)
    return to_umount

<mask token>
_LOGGER = logging.getLogger(__name__)
MOVE_MOUNTS = ['proc']
PIVOT_PATH = '.old-pivot'


def _umount_with_detach(entry_path):
    """umount the path,
    if failed with device busy, we detach (lazy umount) it
    """
    try:
        fs_linux.umount_filesystem(entry_path)
    except OSError as err:
        _LOGGER.warning('Failed to umount %s: %s', entry_path, err)
        if err.errno == 16:
            try:
                fs_linux.umount_filesystem(entry_path, lazy=True)
            except OSError as err:
                _LOGGER.warning('Failed to lazy umount %s: %s', entry_path, err
                    )


def make_root(root_dir):
    """create container root by calling pivot_root
    """
    newroot_norm = fs.norm_safe(root_dir)
    old_pivot = os.path.join(newroot_norm, PIVOT_PATH)
    fs.mkdir_safe(old_pivot)
    proot.pivot_root(newroot_norm, old_pivot)
    to_umount = move_mounts(os.path.sep + PIVOT_PATH)
    for mount_entry in to_umount:
        _umount_with_detach(mount_entry.target)


def _move_mount(original_root, mount_entry):
    """mount move a single entry from original_root to new root
    """
    target = mount_entry.target[len(original_root):]
    _LOGGER.info('Mount move %r => %s', mount_entry, target)
    try:
        fs_linux.mount_move(target, mount_entry.target)
    except FileNotFoundError as err:
        _LOGGER.warning('missing mountpoint %r: %s', mount_entry.target, err)


def move_mounts(original_root):
    """Move mounts from pivot_root original root to new root
    """
    _LOGGER.info('Moving all mounts in %r', MOVE_MOUNTS)
    full_path_move_mounts = [os.path.join(original_root, mount) for mount in
        MOVE_MOUNTS]
    moved = {}
    mountinfo = os.path.join(original_root, 'proc', 'self', 'mountinfo')
    sorted_mounts = fs_linux.generate_sorted_mounts(mountinfo)
    to_umount = []
    for mount_entry in sorted_mounts:
        if not mount_entry.target.startswith(original_root):
            continue
        if mount_entry.target in full_path_move_mounts:
            if mount_entry.target in moved:
                to_umount.append(mount_entry)
            else:
                _move_mount(original_root, mount_entry)
                moved[mount_entry.target] = mount_entry
        else:
            to_umount.append(mount_entry)
    return to_umount

<mask token>
import logging
import os
from treadmill import fs
from treadmill.syscall import pivot_root as proot
from treadmill.fs import linux as fs_linux
_LOGGER = logging.getLogger(__name__)
MOVE_MOUNTS = ['proc']
PIVOT_PATH = '.old-pivot'


def _umount_with_detach(entry_path):
    """umount the path,
    if failed with device busy, we detach (lazy umount) it
    """
    try:
        fs_linux.umount_filesystem(entry_path)
    except OSError as err:
        _LOGGER.warning('Failed to umount %s: %s', entry_path, err)
        if err.errno == 16:
            try:
                fs_linux.umount_filesystem(entry_path, lazy=True)
            except OSError as err:
                _LOGGER.warning('Failed to lazy umount %s: %s', entry_path, err
                    )


def make_root(root_dir):
    """create container root by calling pivot_root
    """
    newroot_norm = fs.norm_safe(root_dir)
    old_pivot = os.path.join(newroot_norm, PIVOT_PATH)
    fs.mkdir_safe(old_pivot)
    proot.pivot_root(newroot_norm, old_pivot)
    to_umount = move_mounts(os.path.sep + PIVOT_PATH)
    for mount_entry in to_umount:
        _umount_with_detach(mount_entry.target)


def _move_mount(original_root, mount_entry):
    """mount move a single entry from original_root to new root
    """
    target = mount_entry.target[len(original_root):]
    _LOGGER.info('Mount move %r => %s', mount_entry, target)
    try:
        fs_linux.mount_move(target, mount_entry.target)
    except FileNotFoundError as err:
        _LOGGER.warning('missing mountpoint %r: %s', mount_entry.target, err)


def move_mounts(original_root):
    """Move mounts from pivot_root original root to new root
    """
    _LOGGER.info('Moving all mounts in %r', MOVE_MOUNTS)
    full_path_move_mounts = [os.path.join(original_root, mount) for mount in
        MOVE_MOUNTS]
    moved = {}
    mountinfo = os.path.join(original_root, 'proc', 'self', 'mountinfo')
    sorted_mounts = fs_linux.generate_sorted_mounts(mountinfo)
    to_umount = []
    for mount_entry in sorted_mounts:
        if not mount_entry.target.startswith(original_root):
            continue
        if mount_entry.target in full_path_move_mounts:
            if mount_entry.target in moved:
                to_umount.append(mount_entry)
            else:
                _move_mount(original_root, mount_entry)
                moved[mount_entry.target] = mount_entry
        else:
            to_umount.append(mount_entry)
    return to_umount

"""pivot_root way to mount container
"""

import logging
import os

from treadmill import fs
from treadmill.syscall import pivot_root as proot
from treadmill.fs import linux as fs_linux

_LOGGER = logging.getLogger(__name__)

# we need to mount move /sys/xxxx
MOVE_MOUNTS = [
    'proc',
]
PIVOT_PATH = '.old-pivot'


def _umount_with_detach(entry_path):
    """umount the path,
    if failed with device busy, we detach (lazy umount) it
    """
    try:
        fs_linux.umount_filesystem(entry_path)
    except OSError as err:
        _LOGGER.warning('Failed to umount %s: %s',
                        entry_path, err)
        # 16 means device busy
        if err.errno == 16:
            try:
                fs_linux.umount_filesystem(entry_path, lazy=True)
            except OSError as err:
                _LOGGER.warning('Failed to lazy umount %s: %s',
                                entry_path, err)


def make_root(root_dir):
    """create container root by calling pivot_root
    """
    newroot_norm = fs.norm_safe(root_dir)
    old_pivot = os.path.join(newroot_norm, PIVOT_PATH)
    fs.mkdir_safe(old_pivot)

    proot.pivot_root(newroot_norm, old_pivot)
    # return list of mount to be umounted from down to top
    to_umount = move_mounts(os.path.sep + PIVOT_PATH)

    # umount entries from down to top
    for mount_entry in to_umount:
        _umount_with_detach(mount_entry.target)


def _move_mount(original_root, mount_entry):
    """mount move a single entry from original_root to new root
    """
    target = mount_entry.target[len(original_root):]
    _LOGGER.info('Mount move %r => %s', mount_entry, target)

    try:
        fs_linux.mount_move(target, mount_entry.target)
    except FileNotFoundError as err:
        _LOGGER.warning('missing mountpoint %r: %s',
                        mount_entry.target, err)


def move_mounts(original_root):
    """Move mounts from pivot_root original root to new root
    """

    _LOGGER.info('Moving all mounts in %r', MOVE_MOUNTS)
    # we may have mutiple /proc mounts, we mount the lowest in container
    full_path_move_mounts = [
        os.path.join(original_root, mount)
        for mount in MOVE_MOUNTS
    ]

    moved = {}

    mountinfo = os.path.join(
        original_root, 'proc', 'self', 'mountinfo'
    )
    sorted_mounts = fs_linux.generate_sorted_mounts(mountinfo)
    to_umount = []

    for mount_entry in sorted_mounts:
        # if not starting with original_root, the mount is added by us before
        if not mount_entry.target.startswith(original_root):
            continue

        if mount_entry.target in full_path_move_mounts:
            if mount_entry.target in moved:
                to_umount.append(mount_entry)
            else:
                _move_mount(original_root, mount_entry)
                moved[mount_entry.target] = mount_entry
        else:
            # we remove all other entries not matching move mounts
            to_umount.append(mount_entry)

    return to_umount
