kiwi-el8/kiwi/system/root_init.py
Marcus Schäfer 4ac554355d
Fixup root init with existing host cache
Creating a new root init with a shared location which already
provides directories of the system failed on init of those
directories. Only create the not yet existing directories
2016-10-31 15:18:28 +01:00

163 lines
5.6 KiB
Python

# Copyright (c) 2015 SUSE Linux GmbH. All rights reserved.
#
# This file is part of kiwi.
#
# kiwi is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# kiwi is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with kiwi. If not, see <http://www.gnu.org/licenses/>
#
import stat
from pwd import getpwnam
from tempfile import mkdtemp
from shutil import rmtree
import os
# project
from ..utils.sync import DataSync
from ..command import Command
from ..path import Path
from ..defaults import Defaults
from ..exceptions import (
KiwiRootDirExists,
KiwiRootInitCreationError
)
class RootInit(object):
"""
Implements creation of new root directory for a linux system.
Host system independent static default files and device nodes
are created to initialize a new base system
Attributes
* :attr:`root_dir`
root directory path name
"""
def __init__(self, root_dir, allow_existing=False):
if not allow_existing and os.path.exists(root_dir):
raise KiwiRootDirExists(
'Root directory %s already exists' % root_dir
)
self.root_dir = root_dir
def delete(self):
"""
Force delete root directory and its contents
"""
Path.wipe(self.root_dir)
def create(self):
"""
Create new system root directory
The method creates a temporary directory and initializes it
for the purpose of building a system image from it. This
includes the following setup:
* create static core device nodes
* create core system paths
On success the contents of the temporary location are
synced to the specified root_dir and the temporary location
will be deleted. That way we never work on an incomplete
initial setup
"""
root = mkdtemp(prefix='kiwi_root.')
try:
self._create_base_directories(root)
self._create_device_nodes(root)
self._create_base_links(root)
self._setup_config_templates(root)
data = DataSync(root + '/', self.root_dir)
data.sync_data(
options=['-a', '--ignore-existing']
)
rmtree(root, ignore_errors=True)
except Exception as e:
rmtree(root, ignore_errors=True)
raise KiwiRootInitCreationError(
'%s: %s' % (type(e).__name__, format(e))
)
def _setup_config_templates(self, root):
group_template = '/var/adm/fillup-templates/group.aaa_base'
passwd_template = '/var/adm/fillup-templates/passwd.aaa_base'
proxy_template = '/var/adm/fillup-templates/sysconfig.proxy'
if os.path.exists(group_template):
Command.run(['cp', group_template, root + '/etc/group'])
if os.path.exists(passwd_template):
Command.run(['cp', passwd_template, root + '/etc/passwd'])
if os.path.exists(proxy_template):
Command.run(['cp', proxy_template, root + '/etc/sysconfig/proxy'])
def _create_device_nodes(self, root):
"""
Create minimum set of device nodes for a new root system
"""
mknod_data = [
(0o666, 'dev/null', stat.S_IFCHR, (1, 3)),
(0o666, 'dev/zero', stat.S_IFCHR, (1, 5)),
(0o622, 'dev/full', stat.S_IFCHR, (1, 7)),
(0o666, 'dev/random', stat.S_IFCHR, (1, 8)),
(0o644, 'dev/urandom', stat.S_IFCHR, (1, 9)),
(0o666, 'dev/tty', stat.S_IFCHR, (5, 0)),
(0o666, 'dev/ptmx', stat.S_IFCHR, (5, 2)),
(0o640, 'dev/loop0', stat.S_IFBLK, (7, 0)),
(0o640, 'dev/loop1', stat.S_IFBLK, (7, 1)),
(0o640, 'dev/loop2', stat.S_IFBLK, (7, 2)),
(0o666, 'dev/loop3', stat.S_IFBLK, (7, 3)),
(0o666, 'dev/loop4', stat.S_IFBLK, (7, 4))
]
for d_mode, d_path, d_type, d_dev in mknod_data:
root_path = os.sep.join([root, d_path])
os.mknod(root_path, d_mode | d_type, os.makedev(*d_dev))
def _create_base_directories(self, root):
"""
Create minimum collection of directories in the new
root system required for kiwi to operate
"""
base_system_paths = (
Defaults.get_shared_cache_location(),
'dev/pts',
'proc',
'etc/sysconfig',
'run',
'sys',
'var'
)
root_uid = getpwnam('root').pw_uid
root_gid = getpwnam('root').pw_gid
for path in base_system_paths:
root_path = os.sep.join([root, path])
if not os.path.exists(root_path):
os.makedirs(root_path)
os.chown(root_path, root_uid, root_gid)
def _create_base_links(self, root):
"""
Create minimum collection of file handle and runtime
links which needs to be present prior to any package
installation
"""
base_system_links = (
('/proc/self/fd', '%s/dev/fd'),
('fd/2', '%s/dev/stderr'),
('fd/0', '%s/dev/stdin'),
('fd/1', '%s/dev/stdout'),
('/run', '%s/var/run')
)
for src, target in base_system_links:
os.symlink(src, target % root, )