def _get_metadata_from_repo(baseurl, proxies, cachedir, reponame, filename, sumtype=None, checksum=None): url = baseurl.join(filename) filename_tmp = str("%s/%s/%s" % (cachedir, reponame, os.path.basename(filename))) if os.path.splitext(filename_tmp)[1] in (".gz", ".bz2"): filename = os.path.splitext(filename_tmp)[0] else: filename = filename_tmp if sumtype and checksum and os.path.exists(filename): try: sumcmd = find_binary_path("%ssum" % sumtype) except: file_checksum = None else: file_checksum = runner.outs([sumcmd, filename]).split()[0] if file_checksum and file_checksum == checksum: return filename return _get_uncompressed_data_from_url(url, filename_tmp, proxies)
def get_image_type(path): def _get_extension_name(path): match = re.search("(?<=\.)\w+$", path) if match: return match.group(0) else: return None if os.path.isdir(path): _check_mic_chroot(path) return "fs" maptab = { "tar": "loop", "raw":"raw", "vmdk":"vmdk", "vdi":"vdi", "iso":"livecd", "usbimg":"liveusb", } extension = _get_extension_name(path) if extension in maptab: return maptab[extension] fd = open(path, "rb") file_header = fd.read(1024) fd.close() vdi_flag = "<<< Sun VirtualBox Disk Image >>>" if file_header[0:len(vdi_flag)] == vdi_flag: return maptab["vdi"] output = runner.outs(['file', path]) isoptn = re.compile(r".*ISO 9660 CD-ROM filesystem.*(bootable).*") usbimgptn = re.compile(r".*x86 boot sector.*active.*") rawptn = re.compile(r".*x86 boot sector.*") vmdkptn = re.compile(r".*VMware. disk image.*") ext3fsimgptn = re.compile(r".*Linux.*ext3 filesystem data.*") ext4fsimgptn = re.compile(r".*Linux.*ext4 filesystem data.*") btrfsimgptn = re.compile(r".*BTRFS.*") if isoptn.match(output): return maptab["iso"] elif usbimgptn.match(output): return maptab["usbimg"] elif rawptn.match(output): return maptab["raw"] elif vmdkptn.match(output): return maptab["vmdk"] elif ext3fsimgptn.match(output): return "ext3fsimg" elif ext4fsimgptn.match(output): return "ext4fsimg" elif btrfsimgptn.match(output): return "btrfsimg" else: raise CreatorError("Cannot detect the type of image: %s" % path)
def setup_qemu_emulator(rootdir, arch): # mount binfmt_misc if it doesn't exist if not os.path.exists("/proc/sys/fs/binfmt_misc"): modprobecmd = find_binary_path("modprobe") runner.show([modprobecmd, "binfmt_misc"]) if not os.path.exists("/proc/sys/fs/binfmt_misc/register"): mountcmd = find_binary_path("mount") runner.show([mountcmd, "-t", "binfmt_misc", "none", "/proc/sys/fs/binfmt_misc"]) # qemu_emulator is a special case, we can't use find_binary_path # qemu emulator should be a statically-linked executable file qemu_emulator = "/usr/bin/qemu-arm" if not os.path.exists(qemu_emulator) or not is_statically_linked(qemu_emulator): qemu_emulator = "/usr/bin/qemu-arm-static" if not os.path.exists(qemu_emulator): raise CreatorError("Please install a statically-linked qemu-arm") # qemu emulator version check armv7_list = [arch for arch in rpmmisc.archPolicies.keys() if arch.startswith('armv7')] if arch in armv7_list: # need qemu (>=0.13.0) qemuout = runner.outs([qemu_emulator, "-h"]) m = re.search("version\s*([.\d]+)", qemuout) if m: qemu_version = m.group(1) if qemu_version < "0.13": raise CreatorError("Requires %s version >=0.13 for %s" % (qemu_emulator, arch)) else: msger.warning("Can't get version info of %s, please make sure it's higher than 0.13.0" % qemu_emulator) if not os.path.exists(rootdir + "/usr/bin"): makedirs(rootdir + "/usr/bin") shutil.copy(qemu_emulator, rootdir + "/usr/bin/qemu-arm-static") qemu_emulator = "/usr/bin/qemu-arm-static" # disable selinux, selinux will block qemu emulator to run if os.path.exists("/usr/sbin/setenforce"): msger.info('Try to disable selinux') runner.show(["/usr/sbin/setenforce", "0"]) # unregister it if it has been registered and is a dynamically-linked executable node = "/proc/sys/fs/binfmt_misc/arm" if os.path.exists(node): qemu_unregister_string = "-1\n" fd = open("/proc/sys/fs/binfmt_misc/arm", "w") fd.write(qemu_unregister_string) fd.close() # register qemu emulator for interpreting other arch executable file if not os.path.exists(node): qemu_arm_string = ":arm:M::\\x7fELF\\x01\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\x28\\x00:\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xfa\\xff\\xff\\xff:%s:\n" % qemu_emulator fd = open("/proc/sys/fs/binfmt_misc/register", "w") fd.write(qemu_arm_string) fd.close() return qemu_emulator
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)) rc = runner.show([self.mkfscmd, "-L", self.fslabel, self.disk.device]) if rc != 0: raise MountError("Error creating %s filesystem on disk %s" % (self.fstype,self.disk.device)) self.uuid = self.__parse_field(runner.outs([self.blkidcmd, self.disk.device]), "UUID")
def selinux_check(arch, fstypes): try: getenforce = find_binary_path('getenforce') except CreatorError: return selinux_status = runner.outs([getenforce]) if arch and arch.startswith("arm") and selinux_status == "Enforcing": raise CreatorError("Can't create arm image if selinux is enabled, " "please run 'setenforce 0' to disable selinux") use_btrfs = filter(lambda typ: typ == 'btrfs', fstypes) if use_btrfs and selinux_status == "Enforcing": raise CreatorError("Can't create btrfs image if selinux is enabled," " please run 'setenforce 0' to disable selinux")
def chroot(chrootdir, bindmounts = None, execute = "/bin/bash"): def mychroot(): os.chroot(chrootdir) os.chdir("/") dev_null = os.open("/dev/null", os.O_WRONLY) files_to_check = ["/bin/bash", "/sbin/init"] architecture_found = False """ Register statically-linked qemu-arm if it is an ARM fs """ qemu_emulator = None for ftc in files_to_check: ftc = "%s/%s" % (chrootdir,ftc) # Return code of 'file' is "almost always" 0 based on some man pages # so we need to check the file existance first. if not os.path.exists(ftc): continue for line in runner.outs(['file', ftc]).splitlines(): if 'ARM' in line: qemu_emulator = misc.setup_qemu_emulator(chrootdir, "arm") architecture_found = True break if 'Intel' in line: architecture_found = True break if architecture_found: break os.close(dev_null) if not architecture_found: raise errors.CreatorError("Failed to get architecture from any of the " "following files %s from chroot." \ % files_to_check) try: msger.info("Launching shell. Exit to continue.\n" "----------------------------------") globalmounts = setup_chrootenv(chrootdir, bindmounts) subprocess.call(execute, preexec_fn = mychroot, shell=True) except OSError, err: raise errors.CreatorError("chroot err: %s" % str(err))
def get_cow_used(self): if not self.__created: return 0 # # dmsetup status on a snapshot returns e.g. # "0 8388608 snapshot 416/1048576" # or, more generally: # "A B snapshot C/D" # where C is the number of 512 byte sectors in use # out = runner.outs([self.dmsetupcmd, "status", self.__name]) try: return int((out.split()[3]).split('/')[0]) * 512 except ValueError: raise SnapshotError("Failed to parse dmsetup status: " + out)
def my_fuser(fp): fuser = find_binary_path("fuser") if not os.path.exists(fp): return False rc = runner.quiet([fuser, "-s", fp]) if rc == 0: for pid in runner.outs([fuser, fp]).split(): fd = open("/proc/%s/cmdline" % pid, "r") cmdline = fd.read() fd.close() if cmdline[:-1] == "/bin/bash": return True # not found return False
def chroot(chrootdir, bindmounts=None, execute="/bin/bash"): def mychroot(): os.chroot(chrootdir) os.chdir("/") dev_null = os.open("/dev/null", os.O_WRONLY) files_to_check = ["/bin/bash", "/sbin/init"] architecture_found = False """ Register statically-linked qemu-arm if it is an ARM fs """ qemu_emulator = None for ftc in files_to_check: ftc = "%s/%s" % (chrootdir, ftc) # Return code of 'file' is "almost always" 0 based on some man pages # so we need to check the file existance first. if not os.path.exists(ftc): continue for line in runner.outs(['file', ftc]).splitlines(): if 'ARM' in line: qemu_emulator = misc.setup_qemu_emulator(chrootdir, "arm") architecture_found = True break if 'Intel' in line: architecture_found = True break if architecture_found: break os.close(dev_null) if not architecture_found: raise errors.CreatorError("Failed to get architecture from any of the " "following files %s from chroot." \ % files_to_check) try: msger.info("Launching shell. Exit to continue.\n" "----------------------------------") globalmounts = setup_chrootenv(chrootdir, bindmounts) subprocess.call(execute, preexec_fn=mychroot, shell=True) except OSError, err: raise errors.CreatorError("chroot err: %s" % str(err))
def _get_metadata_from_repo(baseurl, proxies, cachedir, reponame, filename, sumtype=None, checksum=None): url = os.path.join(baseurl, filename) filename_tmp = str("%s/%s/%s" % (cachedir, reponame, os.path.basename(filename))) if os.path.splitext(filename_tmp)[1] in (".gz", ".bz2"): filename = os.path.splitext(filename_tmp)[0] else: filename = filename_tmp if sumtype and checksum and os.path.exists(filename): try: sumcmd = find_binary_path("%ssum" % sumtype) except: file_checksum = None else: file_checksum = runner.outs([sumcmd, filename]).split()[0] if file_checksum and file_checksum == checksum: return filename return _get_uncompressed_data_from_url(url,filename_tmp,proxies)
def ELF_arch(chrootdir): """ detect the architecture of an ELF file """ #FIXME: if chkfiles are symlink, it will be complex chkfiles = ('/bin/bash', '/sbin/init') # regular expression to arch mapping mapping = { r"Intel 80[0-9]86": "i686", r"x86-64": "x86_64", r"ARM": "arm", } for path in chkfiles: cpath = os.path.join(chrootdir, path.lstrip('/')) if not os.path.exists(cpath): continue outs = runner.outs(['file', cpath]) for ptn in mapping.keys(): if re.search(ptn, outs): return mapping[ptn] raise errors.CreatorError("Failed to detect architecture of chroot: %s" % chrootdir)
def __get_size_from_filesystem(self): return int(self.__parse_field(runner.outs([self.dumpe2fs, '-h', self.disk.lofile]), "Block count")) * self.blocksize
def is_statically_linked(binary): return ", statically linked, " in runner.outs(['file', binary])
def chroot(chrootdir, bindmounts=None, execute="/bin/bash"): def mychroot(): os.chroot(chrootdir) os.chdir("/") if configmgr.chroot['saveto']: savefs = True saveto = configmgr.chroot['saveto'] wrnmsg = "Can't save chroot fs for dir %s exists" % saveto if saveto == chrootdir: savefs = False wrnmsg = "Dir %s is being used to chroot" % saveto elif os.path.exists(saveto): if msger.ask("Dir %s already exists, cleanup and continue?" % saveto): shutil.rmtree(saveto, ignore_errors=True) savefs = True else: savefs = False if savefs: msger.info("Saving image to directory %s" % saveto) runner.quiet("cp -af %s %s" % (chrootdir, saveto)) devs = [ 'dev/fd', 'dev/stdin', 'dev/stdout', 'dev/stderr', 'etc/mtab' ] ignlst = [os.path.join(saveto, x) for x in devs] map(os.unlink, filter(os.path.exists, ignlst)) else: msger.warning(wrnmsg) dev_null = os.open("/dev/null", os.O_WRONLY) files_to_check = ["/bin/bash", "/sbin/init"] architecture_found = False """ Register statically-linked qemu-arm if it is an ARM fs """ qemu_emulator = None for ftc in files_to_check: ftc = "%s/%s" % (chrootdir, ftc) # Return code of 'file' is "almost always" 0 based on some man pages # so we need to check the file existance first. if not os.path.exists(ftc): continue for line in runner.outs(['file', ftc]).splitlines(): if 'ARM' in line: qemu_emulator = misc.setup_qemu_emulator(chrootdir, "arm") architecture_found = True break if 'Intel' in line: architecture_found = True break if architecture_found: break os.close(dev_null) if not architecture_found: raise errors.CreatorError("Failed to get architecture from any of the " "following files %s from chroot." \ % files_to_check) try: msger.info("Launching shell. Exit to continue.\n" "----------------------------------") globalmounts = setup_chrootenv(chrootdir, bindmounts) subprocess.call(execute, preexec_fn=mychroot, shell=True) except OSError, err: raise errors.CreatorError("chroot err: %s" % str(err))
def do_chroot(cls, target, cmd=[]): img = target imgsize = misc.get_file_size(img) * 1024L * 1024L partedcmd = fs_related.find_binary_path("parted") disk = fs_related.SparseLoopbackDisk(img, imgsize) imgmnt = misc.mkdtemp() imgloop = PartitionedMount(imgmnt, skipformat = True) imgloop.add_disk('/dev/sdb', disk) img_fstype = "ext3" msger.info("Partition Table:") partnum = [] for line in runner.outs([partedcmd, "-s", img, "print"]).splitlines(): # no use strip to keep line output here if "Number" in line: msger.raw(line) if line.strip() and line.strip()[0].isdigit(): partnum.append(line.strip()[0]) msger.raw(line) rootpart = None if len(partnum) > 1: rootpart = msger.choice("please choose root partition", partnum) # Check the partitions from raw disk. # if choose root part, the mark it as mounted if rootpart: root_mounted = True else: root_mounted = False partition_mounts = 0 for line in runner.outs([partedcmd,"-s",img,"unit","B","print"]).splitlines(): line = line.strip() # Lines that start with number are the partitions, # because parted can be translated we can't refer to any text lines. if not line or not line[0].isdigit(): continue # Some vars have extra , as list seperator. line = line.replace(",","") # Example of parted output lines that are handled: # Number Start End Size Type File system Flags # 1 512B 3400000511B 3400000000B primary # 2 3400531968B 3656384511B 255852544B primary linux-swap(v1) # 3 3656384512B 3720347647B 63963136B primary fat16 boot, lba partition_info = re.split("\s+",line) size = partition_info[3].split("B")[0] if len(partition_info) < 6 or partition_info[5] in ["boot"]: # No filesystem can be found from partition line. Assuming # btrfs, because that is the only MeeGo fs that parted does # not recognize properly. # TODO: Can we make better assumption? fstype = "btrfs" elif partition_info[5] in ["ext2","ext3","ext4","btrfs"]: fstype = partition_info[5] elif partition_info[5] in ["fat16","fat32"]: fstype = "vfat" elif "swap" in partition_info[5]: fstype = "swap" else: raise errors.CreatorError("Could not recognize partition fs type '%s'." % partition_info[5]) if rootpart and rootpart == line[0]: mountpoint = '/' elif not root_mounted and fstype in ["ext2","ext3","ext4","btrfs"]: # TODO: Check that this is actually the valid root partition from /etc/fstab mountpoint = "/" root_mounted = True elif fstype == "swap": mountpoint = "swap" else: # TODO: Assing better mount points for the rest of the partitions. partition_mounts += 1 mountpoint = "/media/partition_%d" % partition_mounts if "boot" in partition_info: boot = True else: boot = False msger.verbose("Size: %s Bytes, fstype: %s, mountpoint: %s, boot: %s" % (size, fstype, mountpoint, boot)) # TODO: add_partition should take bytes as size parameter. imgloop.add_partition((int)(size)/1024/1024, "/dev/sdb", mountpoint, fstype = fstype, boot = boot) try: imgloop.mount() except errors.MountError: imgloop.cleanup() raise try: if len(cmd) != 0: cmdline = ' '.join(cmd) else: cmdline = "/bin/bash" envcmd = fs_related.find_binary_inchroot("env", imgmnt) if envcmd: cmdline = "%s HOME=/root %s" % (envcmd, cmdline) chroot.chroot(imgmnt, None, cmdline) except: raise errors.CreatorError("Failed to chroot to %s." %img) finally: chroot.cleanup_after_chroot("img", imgloop, None, imgmnt)
def __get_size_from_filesystem(self): return int( self.__parse_field( runner.outs([self.dumpe2fs, '-h', self.disk.lofile]), "Block count")) * self.blocksize
def do_chroot(cls, target): img = target imgsize = misc.get_file_size(img) * 1024L * 1024L partedcmd = fs_related.find_binary_path("parted") disk = fs_related.SparseLoopbackDisk(img, imgsize) imgmnt = misc.mkdtemp() imgloop = PartitionedMount({'/dev/sdb': disk}, imgmnt, skipformat=True) img_fstype = "ext3" # Check the partitions from raw disk. root_mounted = False partition_mounts = 0 for line in runner.outs([partedcmd, "-s", img, "unit", "B", "print"]).splitlines(): line = line.strip() # Lines that start with number are the partitions, # because parted can be translated we can't refer to any text lines. if not line or not line[0].isdigit(): continue # Some vars have extra , as list seperator. line = line.replace(",", "") # Example of parted output lines that are handled: # Number Start End Size Type File system Flags # 1 512B 3400000511B 3400000000B primary # 2 3400531968B 3656384511B 255852544B primary linux-swap(v1) # 3 3656384512B 3720347647B 63963136B primary fat16 boot, lba partition_info = re.split("\s+", line) size = partition_info[3].split("B")[0] if len(partition_info) < 6 or partition_info[5] in ["boot"]: # No filesystem can be found from partition line. Assuming # btrfs, because that is the only MeeGo fs that parted does # not recognize properly. # TODO: Can we make better assumption? fstype = "btrfs" elif partition_info[5] in ["ext2", "ext3", "ext4", "btrfs"]: fstype = partition_info[5] elif partition_info[5] in ["fat16", "fat32"]: fstype = "vfat" elif "swap" in partition_info[5]: fstype = "swap" else: raise errors.CreatorError( "Could not recognize partition fs type '%s'." % partition_info[5]) if not root_mounted and fstype in [ "ext2", "ext3", "ext4", "btrfs" ]: # TODO: Check that this is actually the valid root partition from /etc/fstab mountpoint = "/" root_mounted = True elif fstype == "swap": mountpoint = "swap" else: # TODO: Assing better mount points for the rest of the partitions. partition_mounts += 1 mountpoint = "/media/partition_%d" % partition_mounts if "boot" in partition_info: boot = True else: boot = False msger.verbose( "Size: %s Bytes, fstype: %s, mountpoint: %s, boot: %s" % (size, fstype, mountpoint, boot)) # TODO: add_partition should take bytes as size parameter. imgloop.add_partition((int)(size) / 1024 / 1024, "/dev/sdb", mountpoint, fstype=fstype, boot=boot) try: imgloop.mount() except errors.MountError: imgloop.cleanup() raise try: chroot.chroot(imgmnt, None, "/bin/env HOME=/root /bin/bash") except: raise errors.CreatorError("Failed to chroot to %s." % img) finally: chroot.cleanup_after_chroot("img", imgloop, None, imgmnt)
def chroot(chrootdir, bindmounts = None, execute = "/bin/bash"): def mychroot(): os.chroot(chrootdir) os.chdir("/") if configmgr.chroot['saveto']: savefs = True saveto = configmgr.chroot['saveto'] wrnmsg = "Can't save chroot fs for dir %s exists" % saveto if saveto == chrootdir: savefs = False wrnmsg = "Dir %s is being used to chroot" % saveto elif os.path.exists(saveto): if msger.ask("Dir %s already exists, cleanup and continue?" % saveto): shutil.rmtree(saveto, ignore_errors = True) savefs = True else: savefs = False if savefs: msger.info("Saving image to directory %s" % saveto) fs_related.makedirs(os.path.dirname(os.path.abspath(saveto))) runner.quiet("cp -af %s %s" % (chrootdir, saveto)) devs = ['dev/fd', 'dev/stdin', 'dev/stdout', 'dev/stderr', 'etc/mtab'] ignlst = [os.path.join(saveto, x) for x in devs] map(os.unlink, filter(os.path.exists, ignlst)) else: msger.warning(wrnmsg) dev_null = os.open("/dev/null", os.O_WRONLY) files_to_check = ["/bin/bash", "/sbin/init"] architecture_found = False """ Register statically-linked qemu-arm if it is an ARM fs """ qemu_emulator = None for ftc in files_to_check: ftc = "%s/%s" % (chrootdir,ftc) # Return code of 'file' is "almost always" 0 based on some man pages # so we need to check the file existance first. if not os.path.exists(ftc): continue for line in runner.outs(['file', ftc]).splitlines(): if 'ARM' in line: qemu_emulator = misc.setup_qemu_emulator(chrootdir, "arm") architecture_found = True break if 'Intel' in line: architecture_found = True break if architecture_found: break os.close(dev_null) if not architecture_found: raise errors.CreatorError("Failed to get architecture from any of the " "following files %s from chroot." \ % files_to_check) try: msger.info("Launching shell. Exit to continue.\n" "----------------------------------") globalmounts = setup_chrootenv(chrootdir, bindmounts) subprocess.call(execute, preexec_fn = mychroot, shell=True) except OSError, err: raise errors.CreatorError("chroot err: %s" % str(err))