Recreate device nodes in chroot after shutdown (#1447)
Device nodes in the chroots get created in a tmpfs, so they can be created even if the filesystem where the chroot resides does not support device nodes (#1317). In "pmbootstrap shutdown" we umount the `dev` folder, which means all device nodes that were created inside this folder are gone. This commit changes the code to actually recreate the device nodes when using the chroot again. Details: * move `pmb.chroot.init.create_device_nodes` to `pmb.chroot.mount.crete_device_nodes` * don't call it in `pmb.chroot.init()` anymore, but in `pmb.chroot.mount_dev_tmpfs()` * Create the `null` device as well (`apk --initdb` also creates it on `init`, but we don't call it after `shutdown`)
This commit is contained in:
parent
f49da75998
commit
4e665a2190
|
@ -45,46 +45,6 @@ def copy_resolv_conf(args, suffix="native"):
|
|||
pmb.helpers.run.root(args, ["touch", chroot])
|
||||
|
||||
|
||||
def create_device_nodes(args, suffix):
|
||||
error = "Failed to create device nodes in the '" + suffix + "' chroot."
|
||||
|
||||
# Folder sturcture
|
||||
chroot = args.work + "/chroot_" + suffix
|
||||
pmb.helpers.run.root(args, ["mkdir", "-p", chroot + "/dev"])
|
||||
|
||||
try:
|
||||
# Create all device nodes as specified in the config
|
||||
for dev in pmb.config.chroot_device_nodes:
|
||||
path = chroot + "/dev/" + str(dev[4])
|
||||
if not os.path.exists(path):
|
||||
pmb.helpers.run.root(args, ["mknod",
|
||||
"-m", str(dev[0]), # permissions
|
||||
path, # name
|
||||
str(dev[1]), # type
|
||||
str(dev[2]), # major
|
||||
str(dev[3]), # minor
|
||||
])
|
||||
|
||||
# Verify major and minor numbers of created nodes
|
||||
for dev in pmb.config.chroot_device_nodes:
|
||||
path = chroot + "/dev/" + str(dev[4])
|
||||
stat_result = os.stat(path)
|
||||
rdev = stat_result.st_rdev
|
||||
assert os.major(rdev) == dev[2], "Wrong major in " + path
|
||||
assert os.minor(rdev) == dev[3], "Wrong minor in " + path
|
||||
|
||||
# Verify /dev/zero reading and writing
|
||||
path = chroot + "/dev/zero"
|
||||
with open(path, "r+b", 0) as handle:
|
||||
assert handle.write(bytes([0xff])), "Write failed for " + path
|
||||
assert handle.read(1) == bytes([0x00]), "Read failed for " + path
|
||||
|
||||
# On failure: Show filesystem-related error
|
||||
except Exception as e:
|
||||
logging.info(str(e) + "!")
|
||||
raise RuntimeError(error)
|
||||
|
||||
|
||||
def init(args, suffix="native"):
|
||||
# When already initialized: just prepare the chroot
|
||||
chroot = args.work + "/chroot_" + suffix
|
||||
|
@ -110,8 +70,7 @@ def init(args, suffix="native"):
|
|||
|
||||
logging.info("(" + suffix + ") install alpine-base")
|
||||
|
||||
# Initialize device nodes and cache
|
||||
create_device_nodes(args, suffix)
|
||||
# Initialize cache
|
||||
apk_cache = args.work + "/cache_apk_" + arch
|
||||
pmb.helpers.run.root(args, ["ln", "-s", "-f", "/var/cache/apk", chroot +
|
||||
"/etc/apk/cache"])
|
||||
|
|
|
@ -16,12 +16,53 @@ GNU General Public License for more details.
|
|||
You should have received a copy of the GNU General Public License
|
||||
along with pmbootstrap. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""
|
||||
import logging
|
||||
import os
|
||||
import pmb.config
|
||||
import pmb.parse
|
||||
import pmb.helpers.mount
|
||||
|
||||
|
||||
def create_device_nodes(args, suffix):
|
||||
"""
|
||||
Create device nodes for null, zero, full, random, urandom in the chroot.
|
||||
"""
|
||||
try:
|
||||
chroot = args.work + "/chroot_" + suffix
|
||||
|
||||
# Create all device nodes as specified in the config
|
||||
for dev in pmb.config.chroot_device_nodes:
|
||||
path = chroot + "/dev/" + str(dev[4])
|
||||
if not os.path.exists(path):
|
||||
pmb.helpers.run.root(args, ["mknod",
|
||||
"-m", str(dev[0]), # permissions
|
||||
path, # name
|
||||
str(dev[1]), # type
|
||||
str(dev[2]), # major
|
||||
str(dev[3]), # minor
|
||||
])
|
||||
|
||||
# Verify major and minor numbers of created nodes
|
||||
for dev in pmb.config.chroot_device_nodes:
|
||||
path = chroot + "/dev/" + str(dev[4])
|
||||
stat_result = os.stat(path)
|
||||
rdev = stat_result.st_rdev
|
||||
assert os.major(rdev) == dev[2], "Wrong major in " + path
|
||||
assert os.minor(rdev) == dev[3], "Wrong minor in " + path
|
||||
|
||||
# Verify /dev/zero reading and writing
|
||||
path = chroot + "/dev/zero"
|
||||
with open(path, "r+b", 0) as handle:
|
||||
assert handle.write(bytes([0xff])), "Write failed for " + path
|
||||
assert handle.read(1) == bytes([0x00]), "Read failed for " + path
|
||||
|
||||
# On failure: Show filesystem-related error
|
||||
except Exception as e:
|
||||
logging.info(str(e) + "!")
|
||||
raise RuntimeError("Failed to create device nodes in the '" +
|
||||
suffix + "' chroot.")
|
||||
|
||||
|
||||
def mount_dev_tmpfs(args, suffix="native"):
|
||||
"""
|
||||
Mount tmpfs inside the chroot's dev folder to make sure we can create
|
||||
|
@ -33,13 +74,16 @@ def mount_dev_tmpfs(args, suffix="native"):
|
|||
if pmb.helpers.mount.ismount(dev):
|
||||
return
|
||||
|
||||
# Create the folder structure and mount it
|
||||
if not os.path.exists(dev):
|
||||
pmb.helpers.run.root(args, ["mkdir", "-p", dev])
|
||||
# Create the $chroot/dev folder and mount tmpfs there
|
||||
pmb.helpers.run.root(args, ["mkdir", "-p", dev])
|
||||
pmb.helpers.run.root(args, ["mount", "-t", "tmpfs",
|
||||
"-o", "size=1M,noexec,dev",
|
||||
"tmpfs", dev])
|
||||
|
||||
# Create pts, shm folders and device nodes
|
||||
pmb.helpers.run.root(args, ["mkdir", "-p", dev + "/pts", dev + "/shm"])
|
||||
create_device_nodes(args, suffix)
|
||||
|
||||
|
||||
def mount(args, suffix="native"):
|
||||
# Mount tmpfs as the chroot's /dev
|
||||
|
|
|
@ -132,10 +132,10 @@ chroot_home_symlinks = {
|
|||
"/mnt/pmbootstrap-packages": "/home/pmos/packages/pmos",
|
||||
}
|
||||
|
||||
# The package alpine-base only creates some device nodes. Specify here, which
|
||||
# additional nodes will get created during initialization of the chroot.
|
||||
# Syntax for each entry: [permissions, type, major, minor, name]
|
||||
# Device nodes to be created in each chroot. Syntax for each entry:
|
||||
# [permissions, type, major, minor, name]
|
||||
chroot_device_nodes = [
|
||||
[666, "c", 1, 3, "null"],
|
||||
[666, "c", 1, 5, "zero"],
|
||||
[666, "c", 1, 7, "full"],
|
||||
[644, "c", 1, 8, "random"],
|
||||
|
|
Loading…
Reference in New Issue