def ldr_autodetect(rootdir): '''Tries to guess the installed bootloader''' if which('grub', rootdir=rootdir): return 'grub' elif which('grub-mkrescue', rootdir=rootdir): return 'grub2' elif os.path.isfile(os.path.join(rootdir, 'etc/lilo.conf')): return lilo
def call_umount(umountdir, lazy=False): umnt = which('umount') if lazy: cmd = [umnt, '-l'] else: cmd = [umnt] cmd.append(umountdir) return popen2log(cmd, LOG)
def mount(block, target): '''Mounts a partition to the given directory :param str block: block device :param str target: target directory :raises DiskError:''' mnt = which('mount') exitc = popen2log([mnt, block, target], LOG) if not exitc == 0: raise DiskError('Mount to "%s" failed for "%s"' % (target, block))
def umount(self, mountpoint, lazy=False): '''Unmounts a previously mounted partition''' targd = self._mounts[mountpoint] umnt = which('umount') cmd = [umnt] if lazy: cmd += ['-l'] cmd += [targd] exitc = popen2log(cmd, LOG) if not exitc == 0: raise DiskError('Unmounting of %s failed. See the logs for '\ 'details' % (targd,)) os.rmdir(targd)
def blkid(device): '''Returns the UUID of a partition. :param str device: device path :returns str: uuid if successful, `None` otherwise ''' # blkid -s UUID -o value -c /dev/null _blkid = tools.which('blkid') proc = subprocess.Popen([_blkid, device, '-s', 'UUID', '-o', 'value', '-c', '/dev/null'], stdout=subprocess.PIPE, ) stdout, _ = proc.communicate() if proc.returncode == 0: # pylint: disable=E1103 return stdout.splitlines()[0]
def test_parted(): parted = which('parted') if not parted: raise Exception('parted not found. Partitioning is not available') pout = subprocess.check_output([parted, '-v']) print 'Found parted: ' + pout.splitlines()[0]
def check_installed(execlist): for prog in execlist: if which(prog) is None: raise Exception('Can\'t find %s executable. Please install it' % prog)
def test_qemu(): qemu_img = which('qemu-img') assert qemu_img is not None
def test_mkfs(): mkfs = which('mkfs') if not mkfs: raise Exception('mkfs not found')
'''Functions for raw block device handling''' import os import stat import subprocess import time #from servus.tools import which, popen2log from servus import tools import servus.exceptions as exc from servus.log import get_logger LOG = get_logger() MOUNT = tools.which('mount') UMOUNT = tools.which('umount') def detect_parts_devnames(partitions, devpath): major, minor = get_majorminor(devpath) for part in partitions: if part.sysnum is None: continue devname = get_devicepath((major, minor + part.sysnum)) # wait for partitions (5 seconds timeout) for i in xrange(50): try: os.stat(devname) except OSError: pass else:
def do_install(manifest): """Installs a system from the given manifest object :param servus.DiskConfig manifest: manifest object :raises ValueError: if manifest is not an instance of\ :py:class:`servus.Manifest` """ if not isinstance(manifest, Manifest): raise ValueError("manifest is not an instance of servus.Manifest class") name = manifest.name if manifest.name else "Unknown" LOG.info('Starting installation of "%s"' % name) manifest.validate() # TODO: Support more than one disk disk_c = manifest.disks[0] disk = do_disk_setup(disk_c) for image in manifest.images: # TODO: Check if path is outside chroot if image.chdir: mntd = os.path.join(disk.mountdir, image.chdir) else: mntd = disk.mountdir ftch = fetch.Fetcher(image.url, mntd) ftch.unpack() hookf = os.path.join(disk.mountdir, HOOK_SCRIPT_AFT.lstrip("/")) # mount /sys /dev /proc disk.mount_chroot() CHROOT = tools.which("chroot") env = { "SERVUS_DISK": disk.blockdevice, # 'SERVUS_ROOTPART': rootdev, # 'SERVUS_BOOTDISK': } for part in disk.partitions: if part.mountpoint == "/": env["SERVUS_ROOT_PART"] = part.devpath env["SERVUS_ROOT_UUID"] = part.uuid elif part.mountpoint == "/boot": env["SERVUS_BOOT_PART"] = part.devpath env["SERVUS_BOOT_UUID"] = part.uuid if not "SERVUS_BOOT_PART" in env and "SERVUS_ROOT_PART" in env: env["SERVUS_BOOT_PART"] = env["SERVUS_ROOT_PART"] env["SERVUS_BOOT_UUID"] = env["SERVUS_ROOT_UUID"] # fstab stuff try: fst = Fstab(os.path.join(disk.mountdir, "etc/fstab")) except IOError: LOG.error("Can't find existing fstab. Creating a new one.") fst = Fstab() for part in disk.partitions: if part.mountpoint: pass_ = "1" if part.mountpoint == "/" else "2" fst.add_line(("UUID=%s" % part.uuid.lower(), part.mountpoint, part.filesystem, "defaults", "0", pass_)) elif part.filesystem == "swap": for swap in fst.get_fstype("swap"): indx = fst.lines.index(swap) del fst.lines[indx] fst.add_line(("UUID=%s" % part.uuid.lower(), "none", "swap", "defaults", "0", "0")) cfg = manifest.config if cfg is not None: cfg.write_config(disk.mountdir) # write fstab open(os.path.join(disk.mountdir, "etc/fstab"), "w").write(fst.dumps()) # run after install hook (if file is executable) if os.path.isfile(hookf) and stat.S_IXUSR & os.stat(hookf)[stat.ST_MODE]: pop = subprocess.Popen([CHROOT, disk.mountdir, HOOK_SCRIPT_AFT], env=env) pop.wait() # delete hook dir shutil.rmtree(os.path.join(disk.mountdir, HOOK_DIR.lstrip("/"))) disk.unmount_all() disk.detach()
def call_mount(params): mnt = which('mount') return popen2log([mnt] + params, LOG)
# -*- coding: UTF-8 -*- from uuid import uuid4 from servus.tools import which, popen2log import servus.exceptions as exc from servus.log import get_logger LOG = get_logger() MKSWAP = which('mkswap') MKFS = which('mkfs') def make_filesystems(partitions): '''Takes a list of partitions and runs mkfs on them. The function requires the the ``devname`` from the :py:class:`servus.block.Partition` set correctly or the function will ignore the partition. :param list partitions: a list of :py:class:`servus.block.Partition`\ instances. ''' for part in partitions: if not part.mkfs: continue mkfs(part) def mkfs(part): '''Runs mkfs on a partition. Currently supported file systems are ext2, ext3, ext4 and swap
# -*- coding: UTF-8 -*- '''QEMU block device handling''' import subprocess import re import os from servus.log import get_logger from servus.tools import which, popen2log from servus.exceptions import DiskError from servus.block.blktools import get_majorminor, get_disksize LOG = get_logger() QEMU_IMG = which('qemu-img') def needs_qemu_img(func): '''Function decorator which raises DiskError if qemu-img executable is not available''' def chkfunc(*args, **kwargs): # pylint: disable=C0111 if QEMU_IMG is None: raise DiskError( 'qemu-img executable could not be found. Please install it' ) return func(*args, **kwargs) return chkfunc @needs_qemu_img def qemu_img_call(params):
def __init__(self, stdin, fetcher, tparams, *args, **kwargs): self.tparams = tparams self.tar = which('tar') self._process = None Unpacker.__init__(self, stdin, fetcher, *args, **kwargs)
import subprocess import tempfile from servus import validators as valid from servus import tools #from servus.block.blktools import blockround, is_blockdevice, get_majorminor, \ # get_disksize # from servus.exceptions import DiskError import servus.exceptions as exc from servus.block import qemu, blktools, parted from servus import log from servus import PartitionConfig LOG = log.get_logger() QEMU_NBD = tools.which('qemu-nbd') # start block for all partitions #PART_STARTPOS = 2048 * 512 def part_config2part(part, def_filesystem=None): if not isinstance(part, PartitionConfig): raise TypeError('part argument has to be an instance of '\ '\'servus.PartitionConfig\'') if part.filesystem is None: fsys = def_filesystem else: fsys = part.filesystem pobj = Partition(size=part.size, filesystem=fsys, mkfs=part.mkfs, mountpoint=part.mountpoint, boot=part.boot) return pobj
# -*- coding: UTF-8 -*- import subprocess from servus.tools import which from servus.exceptions import DiskError PARTED = which('parted') def parts2partedcmd(parts, table='msdos'): '''Converts a list of Partitions to the corresponding parted commands to partition the disk''' cmds = [] cmds.append('unit b') cmds.append('mklabel %s' % table) for part in parts: pfs = part.filesystem if pfs in ('ext3','ext4'): pfs = 'ext2' elif pfs == 'swap': pfs = 'linux-swap' endpos = part.startpos + part.size - 1 cmds.append('mkpart primary %s %i %i' % (pfs, part.startpos, endpos)) if part.boot: cmds.append('toggle %i boot' % (part.sysnum)) return ' '.join(cmds) def call_parted(path, arguments): '''Wrapper around GNU parted''' if not PARTED: raise DiskError('Error while calling parted. Parted was not found, '\