Exemplo n.º 1
0
 def testRuntoolCatch0(self):
     (rc, out) = runner.runtool("echo hello", catch=0)
     self.assertEqual(0, rc)
     self.assertEqual('', out)
     (rc, out) = runner.runtool("echo hello >&2", catch=0)
     self.assertEqual(0, rc)
     self.assertEqual('', out)
Exemplo n.º 2
0
 def testRuntoolCatch3(self):
     (rc, out) = runner.runtool("echo hello", catch=3)
     self.assertEqual(0, rc)
     self.assertEqual("hello\n", out)
     (rc, out) = runner.runtool("echo hello >&2", catch=2)
     self.assertEqual(0, rc)
     self.assertEqual("hello\n", out)
Exemplo n.º 3
0
 def testRuntoolCatch3(self):
     (rc, out) = runner.runtool("echo hello", catch=3)
     self.assertEqual(0, rc)
     self.assertEqual("hello\n", out)
     (rc, out) = runner.runtool("echo hello >&2", catch=2)
     self.assertEqual(0, rc)
     self.assertEqual("hello\n", out)
Exemplo n.º 4
0
def exec_cmd(cmd_and_args, as_shell=False, catch=3):
    """
    Execute command, catching stderr, stdout

    Need to execute as_shell if the command uses wildcards
    """
    msger.debug("exec_cmd: %s" % cmd_and_args)
    args = cmd_and_args.split()
    msger.debug(args)

    if (as_shell):
        rc, out = runner.runtool(cmd_and_args, catch)
    else:
        rc, out = runner.runtool(args, catch)
    out = out.strip()
    msger.debug("exec_cmd: output for %s (rc = %d): %s" % \
                    (cmd_and_args, rc, out))

    if rc != 0:
        # We don't throw exception when return code is not 0, because
        # parted always fails to reload part table with loop devices. This
        # prevents us from distinguishing real errors based on return
        # code.
        msger.debug("WARNING: %s returned '%s' instead of 0" % (args[0], rc))

    return (rc, out)
Exemplo n.º 5
0
 def testRuntoolCatch0(self):
     (rc, out) = runner.runtool("echo hello", catch=0)
     self.assertEqual(0, rc)
     self.assertEqual('', out)
     (rc, out) = runner.runtool("echo hello >&2", catch=0)
     self.assertEqual(0, rc)
     self.assertEqual('', out)
Exemplo n.º 6
0
    def __format_filesystem(self):
        if self.skipformat:
            msger.debug("Skip filesystem format.")
            return

        msger.verbose("Formating %s filesystem on %s" % (self.fstype, self.disk.device))
        cmdlist = [self.mkfscmd, "-F", "-L", self.fslabel, "-m", "1", "-b",
                   str(self.blocksize)]
        if self.extopts:
            cmdlist.extend(self.extopts.split())
        cmdlist.extend([self.disk.device])

        rc, errout = runner.runtool(cmdlist, catch=2)
        if rc != 0:
            raise MountError("Error creating %s filesystem on disk %s:\n%s" %
                             (self.fstype, self.disk.device, errout))

        if not self.extopts:
            msger.debug("Tuning filesystem on %s" % self.disk.device)
            runner.show([self.tune2fs, "-c0", "-i0", "-Odir_index", "-ouser_xattr,acl", self.disk.device])

        rc, out = runner.runtool([self.dumpe2fs, '-h', self.disk.device],
                                  catch=2)
        if rc != 0:
            raise MountError("Error dumpe2fs %s filesystem on disk %s:\n%s" %
                             (self.fstype, self.disk.device, out))
        # FIXME: specify uuid in mkfs parameter
        try:
            self.uuid = self.__parse_field(out, "Filesystem UUID")
        except:
            self.uuid = None
Exemplo n.º 7
0
def exec_cmd(cmd_and_args, as_shell = False, catch = 3):
    """
    Execute command, catching stderr, stdout

    Need to execute as_shell if the command uses wildcards
    """
    msger.debug("exec_cmd: %s" % cmd_and_args)
    args = cmd_and_args.split()
    msger.debug(args)

    if (as_shell):
        rc, out = runner.runtool(cmd_and_args, catch)
    else:
        rc, out = runner.runtool(args, catch)
    out = out.strip()
    msger.debug("exec_cmd: output for %s (rc = %d): %s" % \
                    (cmd_and_args, rc, out))

    if rc != 0:
        # We don't throw exception when return code is not 0, because
        # parted always fails to reload part table with loop devices. This
        # prevents us from distinguishing real errors based on return
        # code.
        msger.debug("WARNING: %s returned '%s' instead of 0" % (args[0], rc))

    return (rc, out)
Exemplo n.º 8
0
def get_file_size(filename):
    """ Return size in MB unit """
    cmd = ['du', "-s", "-b", "-B", "1M", filename]
    rc, duOutput  = runner.runtool(cmd)
    if rc != 0:
        raise CreatorError("Failed to run: %s" % ' '.join(cmd))
    size1 = int(duOutput.split()[0])

    cmd = ['du', "-s", "-B", "1M", filename]
    rc, duOutput = runner.runtool(cmd)
    if rc != 0:
        raise CreatorError("Failed to run: %s" % ' '.join(cmd))

    size2 = int(duOutput.split()[0])
    return max(size1, size2)
Exemplo n.º 9
0
 def installLocal(self, pkg, po=None, updateonly=False):
     if not self.ts:
         self.__initialize_transaction()
     solvfile = "%s/.solv" % (self.creator.cachedir)
     rc, out = runner.runtool([fs_related.find_binary_path("rpms2solv"), pkg])
     if rc == 0:
         f = open(solvfile, "w+")
         f.write(out)
         f.close()
         warnmsg = self.repo_manager.loadSolvFile(solvfile , os.path.basename(pkg))
         if warnmsg:
             msger.warning(warnmsg)
         os.unlink(solvfile)
     else:
         msger.warning('Can not get %s solv data.' % pkg)
     hdr = rpmmisc.readRpmHeader(self.ts, pkg)
     arch = zypp.Arch(hdr['arch'])
     if self.creator.target_arch == None:
         # TODO, get the default_arch from conf or detected from global settings
         sysarch = zypp.Arch('i686')
     else:
         sysarch = zypp.Arch(self.creator.target_arch)
     if arch.compatible_with (sysarch):
         pkgname = hdr['name']
         self.localpkgs[pkgname] = pkg
         self.selectPackage(pkgname)
         msger.info("Marking %s to be installed" % (pkg))
     else:
         msger.warning ("Cannot add package %s to transaction. Not a compatible architecture: %s" % (pkg, hdr['arch']))
Exemplo n.º 10
0
    def __map_partitions(self):
        """Load it if dm_snapshot isn't loaded"""
        load_module("dm_snapshot")

        for dev in self.disks.keys():
            d = self.disks[dev]
            if d['mapped']:
                continue

            msger.debug("Running kpartx on %s" % d['disk'].device )
            rc, kpartxOutput = runner.runtool([self.kpartx, "-l", "-v", d['disk'].device])
            kpartxOutput = kpartxOutput.splitlines()

            if rc != 0:
                raise MountError("Failed to query partition mapping for '%s'" %
                                 d['disk'].device)

            # Strip trailing blank and mask verbose output
            i = 0
            while i < len(kpartxOutput) and kpartxOutput[i][0:4] != "loop":
               i = i + 1
            kpartxOutput = kpartxOutput[i:]

            # Quick sanity check that the number of partitions matches
            # our expectation. If it doesn't, someone broke the code
            # further up
            if len(kpartxOutput) != d['numpart']:
                raise MountError("Unexpected number of partitions from kpartx: %d != %d" %
                                 (len(kpartxOutput), d['numpart']))

            for i in range(len(kpartxOutput)):
                line = kpartxOutput[i]
                newdev = line.split()[0]
                mapperdev = "/dev/mapper/" + newdev
                loopdev = d['disk'].device + newdev[-1]

                msger.debug("Dev %s: %s -> %s" % (newdev, loopdev, mapperdev))
                pnum = d['partitions'][i]
                self.partitions[pnum]['device'] = loopdev

                # grub's install wants partitions to be named
                # to match their parent device + partition num
                # kpartx doesn't work like this, so we add compat
                # symlinks to point to /dev/mapper
                if os.path.lexists(loopdev):
                    os.unlink(loopdev)
                os.symlink(mapperdev, loopdev)

            msger.debug("Adding partx mapping for %s" % d['disk'].device)
            rc = runner.show([self.kpartx, "-v", "-a", d['disk'].device])

            if rc != 0:
                # Make sure that the device maps are also removed on error case.
                # The d['mapped'] isn't set to True if the kpartx fails so
                # failed mapping will not be cleaned on cleanup either.
                runner.quiet([self.kpartx, "-d", d['disk'].device])
                raise MountError("Failed to map partitions for '%s'" %
                                 d['disk'].device)

            d['mapped'] = True
Exemplo n.º 11
0
 def installLocal(self, pkg, po=None, updateonly=False):
     if not self.ts:
         self.__initialize_transaction()
     solvfile = "%s/.solv" % (self.creator.cachedir)
     rc, out = runner.runtool(
         [fs_related.find_binary_path("rpms2solv"), pkg])
     if rc == 0:
         f = open(solvfile, "w+")
         f.write(out)
         f.close()
         warnmsg = self.repo_manager.loadSolvFile(solvfile,
                                                  os.path.basename(pkg))
         if warnmsg:
             msger.warning(warnmsg)
         os.unlink(solvfile)
     else:
         msger.warning('Can not get %s solv data.' % pkg)
     hdr = rpmmisc.readRpmHeader(self.ts, pkg)
     arch = zypp.Arch(hdr['arch'])
     if self.creator.target_arch == None:
         # TODO, get the default_arch from conf or detected from global settings
         sysarch = zypp.Arch('i686')
     else:
         sysarch = zypp.Arch(self.creator.target_arch)
     if arch.compatible_with(sysarch):
         pkgname = hdr['name']
         self.localpkgs[pkgname] = pkg
         self.selectPackage(pkgname)
         msger.info("Marking %s to be installed" % (pkg))
     else:
         msger.warning(
             "Cannot add package %s to transaction. Not a compatible architecture: %s"
             % (pkg, hdr['arch']))
Exemplo n.º 12
0
    def __create_subvolume_metadata(self, p, pdisk):
        if len(self.subvolumes) == 0:
            return

        argv = [ self.btrfscmd, "subvolume", "list", pdisk.mountdir ]
        rc, out = runner.runtool(argv)
        msger.debug(out)

        if rc != 0:
            raise MountError("Failed to get subvolume id from %s', return code: %d." % (pdisk.mountdir, rc))

        subvolid_items = out.splitlines()
        subvolume_metadata = ""
        for subvol in self.subvolumes:
            for line in subvolid_items:
                if line.endswith(" path %s" % subvol["subvol"]):
                    subvolid = line.split()[1]
                    if not subvolid.isdigit():
                        raise MountError("Invalid subvolume id: %s" % subvolid)

                    subvolid = int(subvolid)
                    opts = subvol["fsopts"].split(",")
                    for opt in opts:
                        if opt.strip().startswith("subvol="):
                            opts.remove(opt)
                            break
                    fsopts = ",".join(opts)
                    subvolume_metadata += "%d\t%s\t%s\t%s\n" % (subvolid, subvol["subvol"], subvol['mountpoint'], fsopts)

        if subvolume_metadata:
            fd = open("%s/.subvolume_metadata" % pdisk.mountdir, "w")
            fd.write(subvolume_metadata)
            fd.close()
Exemplo n.º 13
0
    def __map_partitions(self):
        """Load it if dm_snapshot isn't loaded"""
        load_module("dm_snapshot")

        for dev in self.disks.keys():
            d = self.disks[dev]
            if d['mapped']:
                continue

            msger.debug("Running kpartx on %s" % d['disk'].device )
            rc, kpartxOutput = runner.runtool([self.kpartx, "-l", "-v", d['disk'].device])
            kpartxOutput = kpartxOutput.splitlines()

            if rc != 0:
                raise MountError("Failed to query partition mapping for '%s'" %
                                 d['disk'].device)

            # Strip trailing blank and mask verbose output
            i = 0
            while i < len(kpartxOutput) and kpartxOutput[i][0:4] != "loop":
               i = i + 1
            kpartxOutput = kpartxOutput[i:]

            # Quick sanity check that the number of partitions matches
            # our expectation. If it doesn't, someone broke the code
            # further up
            if len(kpartxOutput) != d['numpart']:
                raise MountError("Unexpected number of partitions from kpartx: %d != %d" %
                                 (len(kpartxOutput), d['numpart']))

            for i in range(len(kpartxOutput)):
                line = kpartxOutput[i]
                newdev = line.split()[0]
                mapperdev = "/dev/mapper/" + newdev
                loopdev = d['disk'].device + newdev[-1]

                msger.debug("Dev %s: %s -> %s" % (newdev, loopdev, mapperdev))
                pnum = d['partitions'][i]
                self.partitions[pnum]['device'] = loopdev

                # grub's install wants partitions to be named
                # to match their parent device + partition num
                # kpartx doesn't work like this, so we add compat
                # symlinks to point to /dev/mapper
                if os.path.lexists(loopdev):
                    os.unlink(loopdev)
                os.symlink(mapperdev, loopdev)

            msger.debug("Adding partx mapping for %s" % d['disk'].device)
            rc = runner.show([self.kpartx, "-v", "-a", d['disk'].device])

            if rc != 0:
                # Make sure that the device maps are also removed on error case.
                # The d['mapped'] isn't set to True if the kpartx fails so
                # failed mapping will not be cleaned on cleanup either.
                runner.quiet([self.kpartx, "-d", d['disk'].device])
                raise MountError("Failed to map partitions for '%s'" %
                                 d['disk'].device)

            d['mapped'] = True
Exemplo n.º 14
0
    def __create_subvolume_metadata(self, p, pdisk):
        if len(self.subvolumes) == 0:
            return

        argv = [ self.btrfscmd, "subvolume", "list", pdisk.mountdir ]
        rc, out = runner.runtool(argv)
        msger.debug(out)

        if rc != 0:
            raise MountError("Failed to get subvolume id from %s', return code: %d." % (pdisk.mountdir, rc))

        subvolid_items = out.splitlines()
        subvolume_metadata = ""
        for subvol in self.subvolumes:
            for line in subvolid_items:
                if line.endswith(" path %s" % subvol["subvol"]):
                    subvolid = line.split()[1]
                    if not subvolid.isdigit():
                        raise MountError("Invalid subvolume id: %s" % subvolid)

                    subvolid = int(subvolid)
                    opts = subvol["fsopts"].split(",")
                    for opt in opts:
                        if opt.strip().startswith("subvol="):
                            opts.remove(opt)
                            break
                    fsopts = ",".join(opts)
                    subvolume_metadata += "%d\t%s\t%s\t%s\n" % (subvolid, subvol["subvol"], subvol['mountpoint'], fsopts)

        if subvolume_metadata:
            fd = open("%s/.subvolume_metadata" % pdisk.mountdir, "w")
            fd.write(subvolume_metadata)
            fd.close()
Exemplo n.º 15
0
    def __format_filesystem(self):
        if self.skipformat:
            msger.debug("Skip filesystem format.")
            return

        msger.verbose("Formating %s filesystem on %s" %
                      (self.fstype, self.disk.device))
        cmdlist = [
            self.mkfscmd, "-F", "-L", self.fslabel, "-m", "1", "-b",
            str(self.blocksize), "-U", self.uuid
        ]
        if self.extopts:
            cmdlist.extend(self.extopts.split())
        cmdlist.extend([self.disk.device])

        rc, errout = runner.runtool(cmdlist, catch=2)
        if rc != 0:
            raise MountError("Error creating %s filesystem on disk %s:\n%s" %
                             (self.fstype, self.disk.device, errout))

        if not self.extopts:
            msger.debug("Tuning filesystem on %s" % self.disk.device)
            runner.show([
                self.tune2fs, "-c0", "-i0", "-Odir_index", "-ouser_xattr,acl",
                self.disk.device
            ])
Exemplo n.º 16
0
 def _kpseek(self, device):
     rc, out = runner.runtool([self.kpartxcmd, '-l', '-v', device])
     if rc != 0:
         raise MountError("Can't query dm snapshot on %s" % device)
     for line in out.splitlines():
         if line and line.startswith("loop"):
             return True
     return False
Exemplo n.º 17
0
 def _kpseek(self, device):
     rc, out = runner.runtool([self.kpartxcmd, '-l', '-v', device])
     if rc != 0:
         raise MountError("Can't query dm snapshot on %s" % device)
     for line in out.splitlines():
         if line and line.startswith("loop"):
             return True
     return False
Exemplo n.º 18
0
 def _loseek(self, device):
     import re
     rc, out = runner.runtool([self.losetupcmd, '-a'])
     if rc != 0:
         raise MountError("Failed to run 'losetup -a'")
     for line in out.splitlines():
         m = re.match("([^:]+): .*", line)
         if m and m.group(1) == device:
             return True
     return False
Exemplo n.º 19
0
 def _loseek(self, device):
     import re
     rc, out = runner.runtool([self.losetupcmd, '-a'])
     if rc != 0:
         raise MountError("Failed to run 'losetup -a'")
     for line in out.splitlines():
         m = re.match("([^:]+): .*", line)
         if m and m.group(1) == device:
             return True
     return False
Exemplo n.º 20
0
class BindChrootMount:
    """Represents a bind mount of a directory into a chroot."""
    def __init__(self, src, chroot, dest=None, option=None):
        self.root = os.path.abspath(os.path.expanduser(chroot))
        self.mount_option = option

        self.orig_src = self.src = src
        if os.path.islink(src):
            self.src = os.readlink(src)
            if not self.src.startswith('/'):
                self.src = os.path.abspath(
                    os.path.join(os.path.dirname(src), self.src))

        if not dest:
            dest = self.src
        self.dest = os.path.join(self.root, dest.lstrip('/'))

        self.mounted = False
        self.mountcmd = find_binary_path("mount")
        self.umountcmd = find_binary_path("umount")

    def ismounted(self):
        with open('/proc/mounts') as f:
            for line in f:
                if line.split()[1] == os.path.abspath(self.dest):
                    return True

        return False

    def mount(self):
        if self.mounted or self.ismounted():
            return

        try:
            makedirs(self.dest)
        except OSError, err:
            if err.errno == errno.ENOSPC:
                msger.warning("No space left on device '%s'" % err.filename)
                return

        if self.mount_option:
            cmdline = [self.mountcmd, "-o" ,"bind", "-o", "%s" % \
                       self.mount_option, self.src, self.dest]
        else:
            cmdline = [self.mountcmd, "-o", "bind", self.src, self.dest]
        rc, errout = runner.runtool(cmdline, catch=2)
        if rc != 0:
            raise MountError("Bind-mounting '%s' to '%s' failed: %s" %
                             (self.src, self.dest, errout))

        self.mounted = True
        if os.path.islink(self.orig_src):
            dest = os.path.join(self.root, self.orig_src.lstrip('/'))
            if not os.path.exists(dest):
                os.symlink(self.src, dest)
Exemplo n.º 21
0
    def release_output(self, config, destdir, release):
        """ Create release directory and files
        """

        def _rpath(fn):
            """ release path """
            return os.path.join(destdir, fn)

        outimages = self.outimage

        # new ks
        new_kspath = _rpath(self.name + ".ks")
        with open(config) as fr:
            with open(new_kspath, "w") as wf:
                # When building a release we want to make sure the .ks
                # file generates the same build even when --release= is not used.
                wf.write(fr.read().replace("@BUILD_ID@", release))
        outimages.append(new_kspath)

        # rename iso and usbimg
        for f in os.listdir(destdir):
            if f.endswith(".iso"):
                newf = f[:-4] + ".img"
            elif f.endswith(".usbimg"):
                newf = f[:-7] + ".img"
            else:
                continue
            os.rename(_rpath(f), _rpath(newf))
            outimages.append(_rpath(newf))

        # generate MANIFEST
        with open(_rpath("MANIFEST"), "w") as wf:
            if os.path.exists("/usr/bin/md5sum"):
                for f in os.listdir(destdir):
                    if f == "MANIFEST":
                        continue
                    if os.path.isdir(os.path.join(destdir, f)):
                        continue

                    rc, md5sum = runner.runtool(["/usr/bin/md5sum", "-b", _rpath(f)])
                    if rc != 0:
                        msger.warning("Failed to generate md5sum for file %s" % _rpath(f))
                    else:
                        md5sum = md5sum.lstrip().split()[0]
                        wf.write(md5sum + " " + f + "\n")
            else:
                msger.warning("no md5sum tool found, no checksum string in MANIFEST")
                wf.writelines(os.listdir(destdir))
        outimages.append("%s/MANIFEST" % destdir)

        # Filter out the nonexist file
        for fp in outimages[:]:
            if not os.path.exists("%s" % fp):
                outimages.remove(fp)
Exemplo n.º 22
0
    def release_output(self, config, destdir, release):
        """ Create release directory and files
        """

        def _rpath(fn):
            """ release path """
            return os.path.join(destdir, fn)

        outimages = self.outimage

        # new ks
        new_kspath = _rpath(self.name+'.ks')
        with open(config) as fr:
            with open(new_kspath, "w") as wf:
                # When building a release we want to make sure the .ks
                # file generates the same build even when --release= is not used.
                wf.write(fr.read().replace("@BUILD_ID@", release))
        outimages.append(new_kspath)

        # rename iso and usbimg
        for f in os.listdir(destdir):
            if f.endswith(".iso"):
                newf = f[:-4] + '.img'
            elif f.endswith(".usbimg"):
                newf = f[:-7] + '.img'
            else:
                continue
            os.rename(_rpath(f), _rpath(newf))
            outimages.append(_rpath(newf))

        # generate MANIFEST
        with open(_rpath("MANIFEST"), "w") as wf:
            if os.path.exists("/usr/bin/md5sum"):
                for f in os.listdir(destdir):
                    if f == "MANIFEST": continue
                    if os.path.isdir(os.path.join(destdir,f)):
                        continue

                    rc, md5sum = runner.runtool(["/usr/bin/md5sum", "-b", _rpath(f)])
                    if rc != 0:
                        msger.warning("Failed to generate md5sum for file %s" % _rpath(f))
                    else:
                        md5sum = md5sum.lstrip().split()[0]
                        wf.write(md5sum+" "+ f +"\n")
            else:
                msger.warning('no md5sum tool found, no checksum string in MANIFEST')
                wf.writelines(os.listdir(destdir))
        outimages.append("%s/MANIFEST" % destdir)

        # Filter out the nonexist file
        for fp in outimages[:]:
            if not os.path.exists("%s" % fp):
                outimages.remove(fp)
Exemplo n.º 23
0
    def __run_parted(self, args):
        """ Run parted with arguments specified in the 'args' list. """

        args.insert(0, self.parted)
        msger.debug(args)

        rc, out = runner.runtool(args, catch = 3)
        out = out.strip()
        msger.debug("'parted': exitcode: %d, output: %s" % (rc, out))
        # We don't throw exception when return code is not 0, because
        # parted always fails to reload part table with loop devices. This
        # prevents us from distinguishing real errors based on return
        # code.
        return rc, out
Exemplo n.º 24
0
    def __run_parted(self, args):
        """ Run parted with arguments specified in the 'args' list. """

        args.insert(0, self.parted)
        msger.debug(args)

        rc, out = runner.runtool(args, catch=3)
        out = out.strip()
        msger.debug("'parted': exitcode: %d, output: %s" % (rc, out))
        # We don't throw exception when return code is not 0, because
        # parted always fails to reload part table with loop devices. This
        # prevents us from distinguishing real errors based on return
        # code.
        return rc, out
Exemplo n.º 25
0
    def __create_part_to_image(self,device, parttype, fstype, start, size):
        # Start is included to the size so we need to substract one from the end.
        end = start+size-1
        msger.debug("Added '%s' part at %d of size %d" % (parttype,start,end))
        part_cmd = [self.parted, "-s", device, "unit", "s", "mkpart", parttype]
        if fstype:
            part_cmd.extend([fstype])
        part_cmd.extend(["%d" % start, "%d" % end])

        msger.debug(part_cmd)
        rc, out = runner.runtool(part_cmd, catch=3)
        out = out.strip()
        if out:
            msger.debug('"parted" output: %s' % out)
        return rc
Exemplo n.º 26
0
    def __create_part_to_image(self,device, parttype, fstype, start, size):
        # Start is included to the size so we need to substract one from the end.
        end = start+size-1
        msger.debug("Added '%s' part at %d of size %d" % (parttype,start,end))
        part_cmd = [self.parted, "-s", device, "unit", "s", "mkpart", parttype]
        if fstype:
            part_cmd.extend([fstype])
        part_cmd.extend(["%d" % start, "%d" % end])

        msger.debug(part_cmd)
        rc, out = runner.runtool(part_cmd, catch=3)
        out = out.strip()
        if out:
            msger.debug('"parted" output: %s' % out)
        return rc
Exemplo n.º 27
0
    def do_genchecksum(self, image_name):
        if not self._genchecksum:
            return

        """ Generate md5sum if /usr/bin/md5sum is available """
        if os.path.exists("/usr/bin/md5sum"):
            (rc, md5sum) = runner.runtool(["/usr/bin/md5sum", "-b", image_name])
            if rc != 0:
                msger.warning("Can't generate md5sum for image %s" % image_name)
            else:
                pattern = re.compile("\*.*$")
                md5sum = pattern.sub("*" + os.path.basename(image_name), md5sum)
                fd = open(image_name + ".md5sum", "w")
                fd.write(md5sum)
                fd.close()
                self.outimage.append(image_name + ".md5sum")
Exemplo n.º 28
0
    def do_genchecksum(self, image_name):
        if not self._genchecksum:
            return

        """ Generate md5sum if /usr/bin/md5sum is available """
        if os.path.exists("/usr/bin/md5sum"):
            (rc, md5sum) = runner.runtool(["/usr/bin/md5sum", "-b", image_name])
            if rc != 0:
                msger.warning("Can't generate md5sum for image %s" % image_name)
            else:
                pattern = re.compile("\*.*$")
                md5sum = pattern.sub("*" + os.path.basename(image_name), md5sum)
                fd = open(image_name + ".md5sum", "w")
                fd.write(md5sum)
                fd.close()
                self.outimage.append(image_name+".md5sum")
Exemplo n.º 29
0
    def __run_parted(self, args):
        """ Run parted with arguments specified in the 'args' list. """

        args.insert(0, self.parted)
        msger.debug(args)

        rc, out = runner.runtool(args, catch = 3)
        out = out.strip()
        if out:
            msger.debug('"parted" output: %s' % out)

        if rc != 0:
            # We don't throw exception when return code is not 0, because
            # parted always fails to reload part table with loop devices. This
            # prevents us from distinguishing real errors based on return
            # code.
            msger.debug("WARNING: parted returned '%s' instead of 0" % rc)
Exemplo n.º 30
0
    def __run_parted(self, args):
        """ Run parted with arguments specified in the 'args' list. """

        args.insert(0, self.parted)
        msger.debug(args)

        rc, out = runner.runtool(args, catch = 3)
        out = out.strip()
        if out:
            msger.debug('"parted" output: %s' % out)

        if rc != 0:
            # We don't throw exception when return code is not 0, because
            # parted always fails to reload part table with loop devices. This
            # prevents us from distinguishing real errors based on return
            # code.
            msger.debug("WARNING: parted returned '%s' instead of 0" % rc)
Exemplo n.º 31
0
    def __get_subvolume_id(self, rootpath, subvol):
        if not self.btrfscmd:
            self.btrfscmd=find_binary_path("btrfs")
        argv = [ self.btrfscmd, "subvolume", "list", rootpath ]

        rc, out = runner.runtool(argv)
        msger.debug(out)

        if rc != 0:
            raise MountError("Failed to get subvolume id from %s', return code: %d." % (rootpath, rc))

        subvolid = -1
        for line in out.splitlines():
            if line.endswith(" path %s" % subvol):
                subvolid = line.split()[1]
                if not subvolid.isdigit():
                    raise MountError("Invalid subvolume id: %s" % subvolid)
                subvolid = int(subvolid)
                break
        return subvolid
Exemplo n.º 32
0
    def __format_filesystem(self):
        if self.skipformat:
            msger.debug("Skip filesystem format.")
            return

        msger.verbose("Formating %s filesystem on %s" % (self.fstype, self.disk.device))
        cmdlist = [self.mkfscmd, "-F", "-L", self.fslabel, "-m", "1", "-b",
                   str(self.blocksize), "-U", self.uuid]
        if self.extopts:
            cmdlist.extend(self.extopts.split())
        cmdlist.extend([self.disk.device])

        rc, errout = runner.runtool(cmdlist, catch=2)
        if rc != 0:
            raise MountError("Error creating %s filesystem on disk %s:\n%s" %
                             (self.fstype, self.disk.device, errout))

        if not self.extopts:
            msger.debug("Tuning filesystem on %s" % self.disk.device)
            runner.show([self.tune2fs, "-c0", "-i0", "-Odir_index", "-ouser_xattr,acl", self.disk.device])
Exemplo n.º 33
0
    def __get_subvolume_id(self, rootpath, subvol):
        if not self.btrfscmd:
            self.btrfscmd=find_binary_path("btrfs")
        argv = [ self.btrfscmd, "subvolume", "list", rootpath ]

        rc, out = runner.runtool(argv)
        msger.debug(out)

        if rc != 0:
            raise MountError("Failed to get subvolume id from %s', return code: %d." % (rootpath, rc))

        subvolid = -1
        for line in out.splitlines():
            if line.endswith(" path %s" % subvol):
                subvolid = line.split()[1]
                if not subvolid.isdigit():
                    raise MountError("Invalid subvolume id: %s" % subvolid)
                subvolid = int(subvolid)
                break
        return subvolid
Exemplo n.º 34
0
def get_loop_device(losetupcmd, lofile):
    global DEVICE_PIDFILE_DIR
    global DEVICE_LOCKFILE

    import fcntl
    makedirs(os.path.dirname(DEVICE_LOCKFILE))
    fp = open(DEVICE_LOCKFILE, 'w')
    fcntl.flock(fp, fcntl.LOCK_EX)
    try:
        loopdev = None
        devinst = LoopDevice()

        # clean up left loop device first
        clean_loop_devices()

        # provide an avaible loop device
        rc, out = runner.runtool([losetupcmd, "--find"])
        if rc == 0:
            loopdev = out.split()[0]
            devinst.register(loopdev)
        if not loopdev or not os.path.exists(loopdev):
            devinst.create()
            loopdev = devinst.device

        # setup a loop device for image file
        rc = runner.show([losetupcmd, loopdev, lofile])
        if rc != 0:
            raise MountError("Failed to setup loop device for '%s'" % lofile)

        devinst.reg_atexit()

        # try to save device and pid
        makedirs(DEVICE_PIDFILE_DIR)
        pidfile = os.path.join(DEVICE_PIDFILE_DIR, os.path.basename(loopdev))
        if os.path.exists(pidfile):
            os.unlink(pidfile)
        with open(pidfile, 'w') as wf:
            wf.write(str(os.getpid()))

    except MountError, err:
        raise CreatorError("%s" % str(err))
Exemplo n.º 35
0
def get_loop_device(losetupcmd, lofile):
    global DEVICE_PIDFILE_DIR
    global DEVICE_LOCKFILE

    import fcntl
    makedirs(os.path.dirname(DEVICE_LOCKFILE))
    fp = open(DEVICE_LOCKFILE, 'w')
    fcntl.flock(fp, fcntl.LOCK_EX)
    try:
        loopdev = None
        devinst = LoopDevice()

        # clean up left loop device first
        clean_loop_devices()

        # provide an avaible loop device
        rc, out = runner.runtool([losetupcmd, "--find"])
        if rc == 0 and out:
            loopdev = out.split()[0]
            devinst.register(loopdev)
        if not loopdev or not os.path.exists(loopdev):
            devinst.create()
            loopdev = devinst.device

        # setup a loop device for image file
        rc = runner.show([losetupcmd, loopdev, lofile])
        if rc != 0:
            raise MountError("Failed to setup loop device for '%s'" % lofile)

        devinst.reg_atexit()

        # try to save device and pid
        makedirs(DEVICE_PIDFILE_DIR)
        pidfile = os.path.join(DEVICE_PIDFILE_DIR, os.path.basename(loopdev))
        if os.path.exists(pidfile):
            os.unlink(pidfile)
        with open(pidfile, 'w') as wf:
            wf.write(str(os.getpid()))

    except MountError, err:
        raise CreatorError("%s" % str(err))
Exemplo n.º 36
0
    def __format_disks(self):
        msger.debug("Assigning partitions to disks")

        mbr_sector_skipped = False

        for n in range(len(self.partitions)):
            p = self.partitions[n]

            if not self.disks.has_key(p['disk']):
                raise MountError("No disk %s for partition %s" % (p['disk'], p['mountpoint']))

            if not mbr_sector_skipped:
                # This hack is used to remove one sector from the first partition,
                # that is the used to the MBR.
                p['size'] -= 1
                mbr_sector_skipped = True

            d = self.disks[p['disk']]
            d['numpart'] += 1
            if d['numpart'] > 3:
                # Increase allocation of extended partition to hold this partition
                d['extended'] += p['size']
                p['type'] = 'logical'
                p['num'] = d['numpart'] + 1
            else:
                p['type'] = 'primary'
                p['num'] = d['numpart']

            p['start'] = d['offset']
            d['offset'] += p['size']
            d['partitions'].append(n)
            msger.debug("Assigned %s to %s%d at %d at size %d" % (p['mountpoint'], p['disk'], p['num'], p['start'], p['size']))

        if self.skipformat:
            msger.debug("Skipping disk format, because skipformat flag is set.")
            return

        for dev in self.disks.keys():
            d = self.disks[dev]
            msger.debug("Initializing partition table for %s" % (d['disk'].device))
            rc, out = runner.runtool([self.parted, "-s", d['disk'].device, "mklabel", "msdos"], catch=3)
            out = out.strip()
            if out:
                msger.debug('"parted" output: %s' % out)

            if rc != 0:
                # NOTE: We don't throw exception when return code is not 0, because
                # parted always fails to reload part table with loop devices.
                # This prevents us from distinguishing real errors based on return code.
                msger.debug("WARNING: parted returned '%s' instead of 0 when creating partition-table for disk '%s'." % (p1.returncode,d['disk'].device))

        msger.debug("Creating partitions")

        for p in self.partitions:
            d = self.disks[p['disk']]
            if p['num'] == 5:
                self.__create_part_to_image(d['disk'].device,"extended",None,p['start'],d['extended'])

            if p['fstype'] == "swap":
                parted_fs_type = "linux-swap"
            elif p['fstype'] == "vfat":
                parted_fs_type = "fat32"
            elif p['fstype'] == "msdos":
                parted_fs_type = "fat16"
            else:
                # Type for ext2/ext3/ext4/btrfs
                parted_fs_type = "ext2"

            # Boot ROM of OMAP boards require vfat boot partition to have an
            # even number of sectors.
            if p['mountpoint'] == "/boot" and p['fstype'] in ["vfat","msdos"] and p['size'] % 2:
                msger.debug("Substracting one sector from '%s' partition to get even number of sectors for the partition." % (p['mountpoint']))
                p['size'] -= 1

            ret = self.__create_part_to_image(d['disk'].device,p['type'],
                                             parted_fs_type, p['start'],
                                             p['size'])

            if ret != 0:
                # NOTE: We don't throw exception when return code is not 0, because
                # parted always fails to reload part table with loop devices.
                # This prevents us from distinguishing real errors based on return code.
                msger.debug("WARNING: parted returned '%s' instead of 0 when creating partition '%s' for disk '%s'." % (p1.returncode,p['mountpoint'],d['disk'].device))

            if p['boot']:
                msger.debug("Setting boot flag for partition '%s' on disk '%s'." % (p['num'],d['disk'].device))
                boot_cmd = [self.parted, "-s", d['disk'].device, "set", "%d" % p['num'], "boot", "on"]
                msger.debug(boot_cmd)
                rc = runner.show(boot_cmd)

                if rc != 0:
                    # NOTE: We don't throw exception when return code is not 0, because
                    # parted always fails to reload part table with loop devices.
                    # This prevents us from distinguishing real errors based on return code.
                    msger.warning("parted returned '%s' instead of 0 when adding boot flag for partition '%s' disk '%s'." % (rc,p['num'],d['disk'].device))
Exemplo n.º 37
0
 def testRuntoolCatch1(self):
     (rc, out) = runner.runtool("echo hello", catch=1)
     self.assertEqual(0, rc)
     self.assertEqual("hello\n", out)
Exemplo n.º 38
0
    def __map_partitions(self):
        """Load it if dm_snapshot isn't loaded. """
        load_module("dm_snapshot")

        for dev in self.disks.keys():
            d = self.disks[dev]
            if d['mapped']:
                continue

            msger.debug("Running kpartx on %s" % d['disk'].device)
            rc, kpartx_output = runner.runtool(
                [self.kpartx, "-l", "-v", d['disk'].device])
            kpartx_output = kpartx_output.splitlines()

            if rc != 0:
                raise MountError("Failed to query partition mapping for '%s'" %
                                 d['disk'].device)

            # Strip trailing blank and mask verbose output
            i = 0
            while i < len(kpartx_output) and kpartx_output[i][0:4] != "loop":
                i = i + 1
            kpartx_output = kpartx_output[i:]

            # Make sure kpartx reported the right count of partitions
            if len(kpartx_output) != d['numpart']:
                # If this disk has more than 3 partitions, then in case of MBR
                # paritions there is an extended parition. Different versions
                # of kpartx behave differently WRT the extended partition -
                # some map it, some ignore it. This is why we do the below hack
                # - if kpartx reported one more partition and the partition
                # table type is "msdos" and the amount of partitions is more
                # than 3, we just assume kpartx mapped the extended parition
                # and we remove it.
                if len(kpartx_output) == d['numpart'] + 1 \
                   and d['ptable_format'] == 'msdos' and len(kpartx_output) > 3:
                    kpartx_output.pop(3)
                else:
                    raise MountError("Unexpected number of partitions from " \
                                     "kpartx: %d != %d" % \
                                        (len(kpartx_output), d['numpart']))

            for i in range(len(kpartx_output)):
                line = kpartx_output[i]
                newdev = line.split()[0]
                mapperdev = "/dev/mapper/" + newdev
                loopdev = d['disk'].device + newdev[-1]

                msger.debug("Dev %s: %s -> %s" % (newdev, loopdev, mapperdev))
                pnum = d['partitions'][i]
                self.partitions[pnum]['device'] = loopdev
                self.partitions[pnum]['mapper_device'] = mapperdev

                # grub's install wants partitions to be named
                # to match their parent device + partition num
                # kpartx doesn't work like this, so we add compat
                # symlinks to point to /dev/mapper
                if os.path.lexists(loopdev):
                    os.unlink(loopdev)
                os.symlink(mapperdev, loopdev)

            msger.debug("Adding partx mapping for %s" % d['disk'].device)
            rc = runner.show([self.kpartx, "-v", "-sa", d['disk'].device])

            if rc != 0:
                # Make sure that the device maps are also removed on error case.
                # The d['mapped'] isn't set to True if the kpartx fails so
                # failed mapping will not be cleaned on cleanup either.
                runner.quiet([self.kpartx, "-sd", d['disk'].device])
                raise MountError("Failed to map partitions for '%s'" %
                                 d['disk'].device)

            for p in self.partitions:
                if p['mapper_device'] and os.path.islink(p['mapper_device']):
                    p['mpath_device'] = resolve_ref(p['mapper_device'])
                else:
                    p['mpath_device'] = ''

            # FIXME: need a better way to fix the latency
            import time
            time.sleep(1)

            if not os.path.exists(mapperdev):
                # load mapper device if not updated
                runner.quiet([self.dmsetup, "mknodes"])
                # still not updated, roll back
                if not os.path.exists(mapperdev):
                    runner.quiet([self.kpartx, "-sd", d['disk'].device])
                    raise MountError("Failed to load mapper devices for '%s'" %
                                     d['disk'].device)

            d['mapped'] = True
Exemplo n.º 39
0
 def testRuntoolCatch1(self):
     (rc, out) = runner.runtool("echo hello", catch=1)
     self.assertEqual(0, rc)
     self.assertEqual("hello\n", out)
Exemplo n.º 40
0
    def __format_disks(self):
        msger.debug("Assigning partitions to disks")

        mbr_sector_skipped = False

        # Go through partitions in the order they are added in .ks file
        for n in range(len(self.partitions)):
            p = self.partitions[n]

            if not self.disks.has_key(p['disk']):
                raise MountError("No disk %s for partition %s" %
                                 (p['disk'], p['mountpoint']))

            if not mbr_sector_skipped:
                #  This hack is used to remove one sector from the first partition,
                #  that is the used to the MBR.
                p['size'] -= 1
                mbr_sector_skipped = True

            # Get the disk where the partition is located
            d = self.disks[p['disk']]
            d['numpart'] += 1

            # alignment in sectors
            align_sectors = None
            # if first partition then we need to skip the first sector
            # where the MBR is located, if the alignment isn't set
            # See: https://wiki.linaro.org/WorkingGroups/Kernel/Projects/FlashCardSurvey
            if d['numpart'] == 1:
                if p['align'] and p['align'] > 0:
                    align_sectors = p['align'] * 1024 / self.sector_size
                else:
                    align_sectors = MBR_SECTOR_LEN
            elif p['align']:
                # If not first partition and we do have alignment set we need
                # to align the partition.
                # FIXME: This leaves a empty spaces to the disk. To fill the
                # gaps we could enlargea the previous partition?

                # Calc how much the alignment is off.
                align_sectors = d['offset'] % (p['align'] * 1024 /
                                               self.sector_size)
                # We need to move forward to the next alignment point
                align_sectors = (p['align'] * 1024 /
                                 self.sector_size) - align_sectors

            if align_sectors:
                if p['align'] and p['align'] > 0:
                    msger.debug(
                        "Realignment for %s%s with %s sectors, original"
                        " offset %s, target alignment is %sK." %
                        (p['disk'], d['numpart'], align_sectors, d['offset'],
                         p['align']))
                # p['size'] already converted in secctors
                if p['size'] <= align_sectors:
                    raise MountError("Partition for %s is too small to handle "
                                     "the alignment change." % p['mountpoint'])

                # increase the offset so we actually start the partition on right alignment
                d['offset'] += align_sectors

            if d['numpart'] > 3:
                # Increase allocation of extended partition to hold this partition
                d['extended'] += p['size']
                p['type'] = 'logical'
                p['num'] = d['numpart'] + 1
            else:
                p['type'] = 'primary'
                p['num'] = d['numpart']

            p['start'] = d['offset']
            d['offset'] += p['size']
            d['partitions'].append(n)
            msger.debug(
                "Assigned %s to %s%d at Sector %d with size %d sectors "
                "/ %d bytes." %
                (p['mountpoint'], p['disk'], p['num'], p['start'], p['size'],
                 p['size'] * self.sector_size))

        if self.skipformat:
            msger.debug(
                "Skipping disk format, because skipformat flag is set.")
            return

        for dev in self.disks.keys():
            d = self.disks[dev]
            msger.debug("Initializing partition table for %s" %
                        (d['disk'].device))
            rc, out = runner.runtool(
                [self.parted, "-s", d['disk'].device, "mklabel", "msdos"],
                catch=3)
            out = out.strip()
            if out:
                msger.debug('"parted" output: %s' % out)

            if rc != 0:
                # NOTE: We don't throw exception when return code is not 0, because
                # parted always fails to reload part table with loop devices.
                # This prevents us from distinguishing real errors based on return code.
                msger.debug(
                    "WARNING: parted returned '%s' instead of 0 when creating partition-table for disk '%s'."
                    % (rc, d['disk'].device))

        msger.debug("Creating partitions")

        for p in self.partitions:
            d = self.disks[p['disk']]
            if p['num'] == 5:
                self.__create_part_to_image(d['disk'].device, "extended", None,
                                            p['start'], d['extended'])

            if p['fstype'] == "swap":
                parted_fs_type = "linux-swap"
            elif p['fstype'] == "vfat":
                parted_fs_type = "fat32"
            elif p['fstype'] == "msdos":
                parted_fs_type = "fat16"
            else:
                # Type for ext2/ext3/ext4/btrfs
                parted_fs_type = "ext2"

            # Boot ROM of OMAP boards require vfat boot partition to have an
            # even number of sectors.
            if p['mountpoint'] == "/boot" and p['fstype'] in [
                    "vfat", "msdos"
            ] and p['size'] % 2:
                msger.debug(
                    "Substracting one sector from '%s' partition to get even number of sectors for the partition."
                    % (p['mountpoint']))
                p['size'] -= 1

            ret = self.__create_part_to_image(d['disk'].device, p['type'],
                                              parted_fs_type, p['start'],
                                              p['size'])

            if ret != 0:
                # NOTE: We don't throw exception when return code is not 0, because
                # parted always fails to reload part table with loop devices.
                # This prevents us from distinguishing real errors based on return code.
                msger.debug(
                    "WARNING: parted returned '%s' instead of 0 when creating partition '%s' for disk '%s'."
                    % (ret, p['mountpoint'], d['disk'].device))

            if p['boot']:
                msger.debug(
                    "Setting boot flag for partition '%s' on disk '%s'." %
                    (p['num'], d['disk'].device))
                boot_cmd = [
                    self.parted, "-s", d['disk'].device, "set",
                    "%d" % p['num'], "boot", "on"
                ]
                msger.debug(boot_cmd)
                rc = runner.show(boot_cmd)

                if rc != 0:
                    # NOTE: We don't throw exception when return code is not 0, because
                    # parted always fails to reload part table with loop devices.
                    # This prevents us from distinguishing real errors based on return code.
                    msger.warning(
                        "parted returned '%s' instead of 0 when adding boot flag for partition '%s' disk '%s'."
                        % (rc, p['num'], d['disk'].device))
Exemplo n.º 41
0
    def __format_disks(self):
        msger.debug("Assigning partitions to disks")

        mbr_sector_skipped = False

        # Go through partitions in the order they are added in .ks file
        for n in range(len(self.partitions)):
            p = self.partitions[n]

            if not self.disks.has_key(p['disk']):
                raise MountError("No disk %s for partition %s" % (p['disk'], p['mountpoint']))

            if not mbr_sector_skipped:
                #  This hack is used to remove one sector from the first partition,
                #  that is the used to the MBR.
                p['size'] -= 1
                mbr_sector_skipped = True

            # Get the disk where the partition is located
            d = self.disks[p['disk']]
            d['numpart'] += 1

            # alignment in sectors
            align_sectors = None
            # if first partition then we need to skip the first sector
            # where the MBR is located, if the alignment isn't set
            # See: https://wiki.linaro.org/WorkingGroups/Kernel/Projects/FlashCardSurvey
            if d['numpart'] == 1:
                if p['align'] and p['align'] > 0:
                    align_sectors = p['align'] * 1024 / self.sector_size
                else:
                    align_sectors = MBR_SECTOR_LEN
            elif p['align']:
                # If not first partition and we do have alignment set we need
                # to align the partition.
                # FIXME: This leaves a empty spaces to the disk. To fill the
                # gaps we could enlargea the previous partition?

                # Calc how much the alignment is off.
                align_sectors = d['offset'] % (p['align'] * 1024 / self.sector_size)
                # We need to move forward to the next alignment point
                align_sectors = (p['align'] * 1024 / self.sector_size) - align_sectors

            if align_sectors:
                if p['align'] and p['align'] > 0:
                    msger.debug("Realignment for %s%s with %s sectors, original"
                                " offset %s, target alignment is %sK." %
                                (p['disk'], d['numpart'], align_sectors,
                                 d['offset'], p['align']))
                # p['size'] already converted in secctors
                if p['size'] <= align_sectors:
                    raise MountError("Partition for %s is too small to handle "
                                     "the alignment change." % p['mountpoint'])

                # increase the offset so we actually start the partition on right alignment
                d['offset'] += align_sectors

            if d['numpart'] > 3:
                # Increase allocation of extended partition to hold this partition
                d['extended'] += p['size']
                p['type'] = 'logical'
                p['num'] = d['numpart'] + 1
            else:
                p['type'] = 'primary'
                p['num'] = d['numpart']

            p['start'] = d['offset']
            d['offset'] += p['size']
            d['partitions'].append(n)
            msger.debug("Assigned %s to %s%d at Sector %d with size %d sectors "
                        "/ %d bytes." % (p['mountpoint'], p['disk'], p['num'],
                                         p['start'], p['size'],
                                         p['size'] * self.sector_size))

        if self.skipformat:
            msger.debug("Skipping disk format, because skipformat flag is set.")
            return

        for dev in self.disks.keys():
            d = self.disks[dev]
            msger.debug("Initializing partition table for %s" % (d['disk'].device))
            rc, out = runner.runtool([self.parted, "-s", d['disk'].device, "mklabel", "msdos"], catch=3)
            out = out.strip()
            if out:
                msger.debug('"parted" output: %s' % out)

            if rc != 0:
                # NOTE: We don't throw exception when return code is not 0, because
                # parted always fails to reload part table with loop devices.
                # This prevents us from distinguishing real errors based on return code.
                msger.debug("WARNING: parted returned '%s' instead of 0 when creating partition-table for disk '%s'." % (rc, d['disk'].device))

        msger.debug("Creating partitions")

        for p in self.partitions:
            d = self.disks[p['disk']]
            if p['num'] == 5:
                self.__create_part_to_image(d['disk'].device,"extended",None,p['start'],d['extended'])

            if p['fstype'] == "swap":
                parted_fs_type = "linux-swap"
            elif p['fstype'] == "vfat":
                parted_fs_type = "fat32"
            elif p['fstype'] == "msdos":
                parted_fs_type = "fat16"
            else:
                # Type for ext2/ext3/ext4/btrfs
                parted_fs_type = "ext2"

            # Boot ROM of OMAP boards require vfat boot partition to have an
            # even number of sectors.
            if p['mountpoint'] == "/boot" and p['fstype'] in ["vfat","msdos"] and p['size'] % 2:
                msger.debug("Substracting one sector from '%s' partition to get even number of sectors for the partition." % (p['mountpoint']))
                p['size'] -= 1

            ret = self.__create_part_to_image(d['disk'].device,p['type'],
                                             parted_fs_type, p['start'],
                                             p['size'])

            if ret != 0:
                # NOTE: We don't throw exception when return code is not 0, because
                # parted always fails to reload part table with loop devices.
                # This prevents us from distinguishing real errors based on return code.
                msger.debug("WARNING: parted returned '%s' instead of 0 when creating partition '%s' for disk '%s'." % (ret, p['mountpoint'], d['disk'].device))

            if p['boot']:
                msger.debug("Setting boot flag for partition '%s' on disk '%s'." % (p['num'],d['disk'].device))
                boot_cmd = [self.parted, "-s", d['disk'].device, "set", "%d" % p['num'], "boot", "on"]
                msger.debug(boot_cmd)
                rc = runner.show(boot_cmd)

                if rc != 0:
                    # NOTE: We don't throw exception when return code is not 0, because
                    # parted always fails to reload part table with loop devices.
                    # This prevents us from distinguishing real errors based on return code.
                    msger.warning("parted returned '%s' instead of 0 when adding boot flag for partition '%s' disk '%s'." % (rc,p['num'],d['disk'].device))
Exemplo n.º 42
0
    def __format_disks(self):
        msger.debug("Assigning partitions to disks")

        mbr_sector_skipped = False

        for n in range(len(self.partitions)):
            p = self.partitions[n]

            if not self.disks.has_key(p['disk']):
                raise MountError("No disk %s for partition %s" % (p['disk'], p['mountpoint']))

            if not mbr_sector_skipped:
                # This hack is used to remove one sector from the first partition,
                # that is the used to the MBR.
                p['size'] -= 1
                mbr_sector_skipped = True

            d = self.disks[p['disk']]
            d['numpart'] += 1
            if d['numpart'] > 3:
                # Increase allocation of extended partition to hold this partition
                d['extended'] += p['size']
                p['type'] = 'logical'
                p['num'] = d['numpart'] + 1
            else:
                p['type'] = 'primary'
                p['num'] = d['numpart']

            p['start'] = d['offset']
            d['offset'] += p['size']
            d['partitions'].append(n)
            msger.debug("Assigned %s to %s%d at %d at size %d" % (p['mountpoint'], p['disk'], p['num'], p['start'], p['size']))

        if self.skipformat:
            msger.debug("Skipping disk format, because skipformat flag is set.")
            return

        for dev in self.disks.keys():
            d = self.disks[dev]
            msger.debug("Initializing partition table for %s" % (d['disk'].device))
            rc, out = runner.runtool([self.parted, "-s", d['disk'].device, "mklabel", "msdos"], catch=3)
            out = out.strip()
            if out:
                msger.debug('"parted" output: %s' % out)

            if rc != 0:
                # NOTE: We don't throw exception when return code is not 0, because
                # parted always fails to reload part table with loop devices.
                # This prevents us from distinguishing real errors based on return code.
                msger.debug("WARNING: parted returned '%s' instead of 0 when creating partition-table for disk '%s'." % (rc, d['disk'].device))

        msger.debug("Creating partitions")

        for p in self.partitions:
            d = self.disks[p['disk']]
            if p['num'] == 5:
                self.__create_part_to_image(d['disk'].device,"extended",None,p['start'],d['extended'])

            if p['fstype'] == "swap":
                parted_fs_type = "linux-swap"
            elif p['fstype'] == "vfat":
                parted_fs_type = "fat32"
            elif p['fstype'] == "msdos":
                parted_fs_type = "fat16"
            else:
                # Type for ext2/ext3/ext4/btrfs
                parted_fs_type = "ext2"

            # Boot ROM of OMAP boards require vfat boot partition to have an
            # even number of sectors.
            if p['mountpoint'] == "/boot" and p['fstype'] in ["vfat","msdos"] and p['size'] % 2:
                msger.debug("Substracting one sector from '%s' partition to get even number of sectors for the partition." % (p['mountpoint']))
                p['size'] -= 1

            ret = self.__create_part_to_image(d['disk'].device,p['type'],
                                             parted_fs_type, p['start'],
                                             p['size'])

            if ret != 0:
                # NOTE: We don't throw exception when return code is not 0, because
                # parted always fails to reload part table with loop devices.
                # This prevents us from distinguishing real errors based on return code.
                msger.debug("WARNING: parted returned '%s' instead of 0 when creating partition '%s' for disk '%s'." % (ret, p['mountpoint'], d['disk'].device))

            if p['boot']:
                msger.debug("Setting boot flag for partition '%s' on disk '%s'." % (p['num'],d['disk'].device))
                boot_cmd = [self.parted, "-s", d['disk'].device, "set", "%d" % p['num'], "boot", "on"]
                msger.debug(boot_cmd)
                rc = runner.show(boot_cmd)

                if rc != 0:
                    # NOTE: We don't throw exception when return code is not 0, because
                    # parted always fails to reload part table with loop devices.
                    # This prevents us from distinguishing real errors based on return code.
                    msger.warning("parted returned '%s' instead of 0 when adding boot flag for partition '%s' disk '%s'." % (rc,p['num'],d['disk'].device))
Exemplo n.º 43
0
    def __map_partitions(self):
        """Load it if dm_snapshot isn't loaded. """
        load_module("dm_snapshot")

        for dev in self.disks.keys():
            d = self.disks[dev]
            if d['mapped']:
                continue

            msger.debug("Running kpartx on %s" % d['disk'].device )
            rc, kpartxOutput = runner.runtool([self.kpartx, "-l", "-v", d['disk'].device])
            kpartxOutput = kpartxOutput.splitlines()

            if rc != 0:
                raise MountError("Failed to query partition mapping for '%s'" %
                                 d['disk'].device)

            # Strip trailing blank and mask verbose output
            i = 0
            while i < len(kpartxOutput) and kpartxOutput[i][0:4] != "loop":
                i = i + 1
            kpartxOutput = kpartxOutput[i:]

            # Make sure kpartx reported the right count of partitions
            if len(kpartxOutput) != d['numpart']:
                # If this disk has more than 3 partitions, then in case of MBR
                # paritions there is an extended parition. Different versions
                # of kpartx behave differently WRT the extended partition -
                # some map it, some ignore it. This is why we do the below hack
                # - if kpartx reported one more partition and the partition
                # table type is "msdos" and the amount of partitions is more
                # than 3, we just assume kpartx mapped the extended parition
                # and we remove it.
                if len(kpartxOutput) == d['numpart'] + 1 \
                   and d['ptable_format'] == 'msdos' and len(kpartxOutput) > 3:
                    kpartxOutput.pop(3)
                else:
                    raise MountError("Unexpected number of partitions from " \
                                     "kpartx: %d != %d" % \
                                        (len(kpartxOutput), d['numpart']))

            for i in range(len(kpartxOutput)):
                line = kpartxOutput[i]
                newdev = line.split()[0]
                mapperdev = "/dev/mapper/" + newdev
                loopdev = d['disk'].device + newdev[-1]

                msger.debug("Dev %s: %s -> %s" % (newdev, loopdev, mapperdev))
                pnum = d['partitions'][i]
                self.partitions[pnum]['device'] = loopdev

                # grub's install wants partitions to be named
                # to match their parent device + partition num
                # kpartx doesn't work like this, so we add compat
                # symlinks to point to /dev/mapper
                if os.path.lexists(loopdev):
                    os.unlink(loopdev)
                os.symlink(mapperdev, loopdev)

            msger.debug("Adding partx mapping for %s" % d['disk'].device)
            rc = runner.show([self.kpartx, "-v", "-a", d['disk'].device])

            if rc != 0:
                # Make sure that the device maps are also removed on error case.
                # The d['mapped'] isn't set to True if the kpartx fails so
                # failed mapping will not be cleaned on cleanup either.
                runner.quiet([self.kpartx, "-d", d['disk'].device])
                raise MountError("Failed to map partitions for '%s'" %
                                 d['disk'].device)

            # FIXME: there is a bit delay for multipath device setup,
            # wait 10ms for the setup
            import time
            time.sleep(10)
            d['mapped'] = True