3 # Copyright (c) 2010, 2011 Intel Inc.
5 # This program is free software; you can redistribute it and/or modify it
6 # under the terms of the GNU General Public License as published by the Free
7 # Software Foundation; version 2 of the License
9 # This program is distributed in the hope that it will be useful, but
10 # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 # You should have received a copy of the GNU General Public License along
15 # with this program; if not, write to the Free Software Foundation, Inc., 59
16 # Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 from __future__ import with_statement
33 import sqlite3 as sqlite
38 from xml.etree import cElementTree
41 xmlparse = cElementTree.parse
44 from mic.utils.errors import CreatorError, SquashfsError
45 from mic.utils.fs_related import find_binary_path, makedirs
46 from mic.utils.grabber import myurlgrab
47 from mic.utils.proxy import get_proxy_for
48 from mic.utils import runner
49 from mic.utils import rpmmisc
50 from mic.utils.safeurl import SafeURL
53 RPM_RE = re.compile("(.*)\.(.*) (.*)-(.*)")
54 RPM_FMT = "%(name)s.%(arch)s %(version)s-%(release)s"
55 SRPM_RE = re.compile("(.*)-(\d+.*)-(\d+\.\d+).src.rpm")
58 def build_name(kscfg, release=None, prefix = None, suffix = None):
59 """Construct and return an image name string.
61 This is a utility function to help create sensible name and fslabel
62 strings. The name is constructed using the sans-prefix-and-extension
63 kickstart filename and the supplied prefix and suffix.
65 kscfg -- a path to a kickstart file
66 release -- a replacement to suffix for image release
67 prefix -- a prefix to prepend to the name; defaults to None, which causes
69 suffix -- a suffix to append to the name; defaults to None, which causes
70 a YYYYMMDDHHMM suffix to be used
72 Note, if maxlen is less then the len(suffix), you get to keep both pieces.
75 name = os.path.basename(kscfg)
80 if release is not None:
85 suffix = time.strftime("%Y%m%d%H%M")
87 if name.startswith(prefix):
88 name = name[len(prefix):]
90 prefix = "%s-" % prefix if prefix else ""
91 suffix = "-%s" % suffix if suffix else ""
93 ret = prefix + name + suffix
97 """Detect linux distribution, support "meego"
100 support_dists = ('SuSE',
109 (dist, ver, id) = platform.linux_distribution( \
110 supported_dists = support_dists)
112 (dist, ver, id) = platform.dist( \
113 supported_dists = support_dists)
115 return (dist, ver, id)
120 return platform.node()
122 def get_hostname_distro_str():
123 """Get composited string for current linux distribution
125 (dist, ver, id) = get_distro()
126 hostname = get_hostname()
129 return "%s(Unknown Linux Distribution)" % hostname
131 distro_str = ' '.join(map(str.strip, (hostname, dist, ver, id)))
132 return distro_str.strip()
134 _LOOP_RULE_PTH = None
136 def hide_loopdev_presentation():
137 udev_rules = "80-prevent-loop-present.rules"
139 '/usr/lib/udev/rules.d/',
140 '/lib/udev/rules.d/',
144 global _LOOP_RULE_PTH
146 for rdir in udev_rules_dir:
147 if os.path.exists(rdir):
148 _LOOP_RULE_PTH = os.path.join(rdir, udev_rules)
150 if not _LOOP_RULE_PTH:
154 with open(_LOOP_RULE_PTH, 'w') as wf:
155 wf.write('KERNEL=="loop*", ENV{UDISKS_PRESENTATION_HIDE}="1"')
157 runner.quiet('udevadm trigger')
161 def unhide_loopdev_presentation():
162 global _LOOP_RULE_PTH
164 if not _LOOP_RULE_PTH:
168 os.unlink(_LOOP_RULE_PTH)
169 runner.quiet('udevadm trigger')
173 def extract_rpm(rpmfile, targetdir):
174 rpm2cpio = find_binary_path("rpm2cpio")
175 cpio = find_binary_path("cpio")
180 msger.verbose("Extract rpm file with cpio: %s" % rpmfile)
181 p1 = subprocess.Popen([rpm2cpio, rpmfile], stdout=subprocess.PIPE)
182 p2 = subprocess.Popen([cpio, "-idv"], stdin=p1.stdout,
183 stdout=subprocess.PIPE, stderr=subprocess.PIPE)
185 (sout, serr) = p2.communicate()
186 msger.verbose(sout or serr)
190 def compressing(fpath, method):
192 "gz": ["pgzip", "pigz", "gzip"],
193 "bz2": ["pbzip2", "bzip2"],
195 if method not in comp_map:
196 raise CreatorError("Unsupport compress format: %s, valid values: %s"
197 % (method, ','.join(comp_map.keys())))
199 for cmdname in comp_map[method]:
201 cmd = find_binary_path(cmdname)
203 except CreatorError as err:
206 raise CreatorError("Command %s not available" % cmdname)
207 rc = runner.show([cmd, "-f", fpath])
209 raise CreatorError("Failed to %s file: %s" % (comp_map[method], fpath))
211 def taring(dstfile, target):
213 basen, ext = os.path.splitext(dstfile)
214 comp = {".tar": None,
215 ".gz": "gz", # for .tar.gz
216 ".bz2": "bz2", # for .tar.bz2
220 # specify tarball file path
223 elif basen.endswith(".tar"):
226 tarpath = basen + ".tar"
227 wf = tarfile.open(tarpath, 'w')
229 if os.path.isdir(target):
230 for item in os.listdir(target):
231 wf.add(os.path.join(target, item), item)
233 wf.add(target, os.path.basename(target))
237 compressing(tarpath, comp)
238 # when dstfile ext is ".tgz" and ".tbz", should rename
239 if not basen.endswith(".tar"):
240 shutil.move("%s.%s" % (tarpath, comp), dstfile)
242 def ziping(dstfile, target):
244 wf = zipfile.ZipFile(dstfile, 'w', compression=zipfile.ZIP_DEFLATED)
245 if os.path.isdir(target):
246 for item in os.listdir(target):
247 fpath = os.path.join(target, item)
248 if not os.path.isfile(fpath):
250 wf.write(fpath, item, zipfile.ZIP_DEFLATED)
252 wf.write(target, os.path.basename(target), zipfile.ZIP_DEFLATED)
264 def packing(dstfile, target):
265 (base, ext) = os.path.splitext(dstfile)
266 if ext in (".gz", ".bz2") and base.endswith(".tar"):
268 if ext not in pack_formats:
269 raise CreatorError("Unsupport pack format: %s, valid values: %s"
270 % (ext, ','.join(pack_formats.keys())))
271 func = pack_formats[ext]
272 # func should be callable
273 func(dstfile, target)
275 def human_size(size):
276 """Return human readable string for Bytes size
282 measure = ['B', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y']
283 expo = int(math.log(size, 1024))
284 mant = float(size/math.pow(1024, expo))
285 return "{0:.1f}{1:s}".format(mant, measure[expo])
287 def get_block_size(file_obj):
288 """ Returns block size for file object 'file_obj'. Errors are indicated by
289 the 'IOError' exception. """
291 from fcntl import ioctl
294 # Get the block size of the host file-system for the image file by calling
295 # the FIGETBSZ ioctl (number 2).
296 binary_data = ioctl(file_obj, 2, struct.pack('I', 0))
297 return struct.unpack('I', binary_data)[0]
299 def check_space_pre_cp(src, dst):
300 """Check whether disk space is enough before 'cp' like
301 operations, else exception will be raised.
304 srcsize = get_file_size(src) * 1024 * 1024
305 freesize = get_filesystem_avail(dst)
306 if srcsize > freesize:
307 raise CreatorError("space on %s(%s) is not enough for about %s files"
308 % (dst, human_size(freesize), human_size(srcsize)))
310 def calc_hashes(file_path, hash_names, start = 0, end = None):
311 """ Calculate hashes for a file. The 'file_path' argument is the file
312 to calculate hash functions for, 'start' and 'end' are the starting and
313 ending file offset to calculate the has functions for. The 'hash_names'
314 argument is a list of hash names to calculate. Returns the the list
315 of calculated hash values in the hexadecimal form in the same order
319 end = os.path.getsize(file_path)
322 to_read = end - start
326 for hash_name in hash_names:
327 hashes.append(hashlib.new(hash_name))
329 with open(file_path, "rb") as f:
332 while read < to_read:
333 if read + chunk_size > to_read:
334 chunk_size = to_read - read
335 chunk = f.read(chunk_size)
336 for hash_obj in hashes:
337 hash_obj.update(chunk)
341 for hash_obj in hashes:
342 result.append(hash_obj.hexdigest())
346 def get_md5sum(fpath):
347 return calc_hashes(fpath, ('md5', ))[0]
350 def normalize_ksfile(ksconf, release, arch):
352 Return the name of a normalized ks file in which macro variables
353 @BUILD_ID@ and @ARCH@ are replace with real values.
355 The original ks file is returned if no special macro is used, otherwise
356 a temp file is created and returned, which will be deleted when program
362 if not arch or re.match(r'i.86', arch):
365 with open(ksconf) as f:
368 if "@ARCH@" not in ksc and "@BUILD_ID@" not in ksc:
371 msger.info("Substitute macro variable @BUILD_ID@/@ARCH@ in ks: %s" % ksconf)
372 ksc = ksc.replace("@ARCH@", arch)
373 ksc = ksc.replace("@BUILD_ID@", release)
375 fd, ksconf = tempfile.mkstemp(prefix=os.path.basename(ksconf))
379 msger.debug('normalized ks file:%s' % ksconf)
381 def remove_temp_ks():
385 msger.warning('Failed to remove temp ks file:%s:%s' % (ksconf, err))
388 atexit.register(remove_temp_ks)
393 def _check_mic_chroot(rootdir):
395 return rootdir.rstrip('/') + path
397 release_files = map(_path, [ "/etc/moblin-release",
398 "/etc/meego-release",
399 "/etc/tizen-release"])
401 if not any(map(os.path.exists, release_files)):
402 msger.warning("Dir %s is not a MeeGo/Tizen chroot env" % rootdir)
404 if not glob.glob(rootdir + "/boot/vmlinuz-*"):
405 msger.warning("Failed to find kernel module under %s" % rootdir)
409 def selinux_check(arch, fstypes):
411 getenforce = find_binary_path('getenforce')
415 selinux_status = runner.outs([getenforce])
416 if arch and arch.startswith("arm") and selinux_status == "Enforcing":
417 raise CreatorError("Can't create arm image if selinux is enabled, "
418 "please run 'setenforce 0' to disable selinux")
420 use_btrfs = filter(lambda typ: typ == 'btrfs', fstypes)
421 if use_btrfs and selinux_status == "Enforcing":
422 raise CreatorError("Can't create btrfs image if selinux is enabled,"
423 " please run 'setenforce 0' to disable selinux")
425 def get_image_type(path):
426 def _get_extension_name(path):
427 match = re.search("(?<=\.)\w+$", path)
429 return match.group(0)
433 if os.path.isdir(path):
434 _check_mic_chroot(path)
446 extension = _get_extension_name(path)
447 if extension in maptab:
448 return maptab[extension]
450 fd = open(path, "rb")
451 file_header = fd.read(1024)
453 vdi_flag = "<<< Sun VirtualBox Disk Image >>>"
454 if file_header[0:len(vdi_flag)] == vdi_flag:
457 output = runner.outs(['file', path])
458 isoptn = re.compile(r".*ISO 9660 CD-ROM filesystem.*(bootable).*")
459 usbimgptn = re.compile(r".*x86 boot sector.*active.*")
460 rawptn = re.compile(r".*x86 boot sector.*")
461 vmdkptn = re.compile(r".*VMware. disk image.*")
462 ext3fsimgptn = re.compile(r".*Linux.*ext3 filesystem data.*")
463 ext4fsimgptn = re.compile(r".*Linux.*ext4 filesystem data.*")
464 btrfsimgptn = re.compile(r".*BTRFS.*")
465 if isoptn.match(output):
467 elif usbimgptn.match(output):
468 return maptab["usbimg"]
469 elif rawptn.match(output):
471 elif vmdkptn.match(output):
472 return maptab["vmdk"]
473 elif ext3fsimgptn.match(output):
475 elif ext4fsimgptn.match(output):
477 elif btrfsimgptn.match(output):
480 raise CreatorError("Cannot detect the type of image: %s" % path)
483 def get_file_size(filename):
484 """ Return size in MB unit """
485 cmd = ['du', "-s", "-b", "-B", "1M", filename]
486 rc, duOutput = runner.runtool(cmd)
488 raise CreatorError("Failed to run: %s" % ' '.join(cmd))
489 size1 = int(duOutput.split()[0])
491 cmd = ['du', "-s", "-B", "1M", filename]
492 rc, duOutput = runner.runtool(cmd)
494 raise CreatorError("Failed to run: %s" % ' '.join(cmd))
496 size2 = int(duOutput.split()[0])
497 return max(size1, size2)
500 def get_filesystem_avail(fs):
501 vfstat = os.statvfs(fs)
502 return vfstat.f_bavail * vfstat.f_bsize
504 def convert_image(srcimg, srcfmt, dstimg, dstfmt):
507 raise CreatorError("Invalid destination image format: %s" % dstfmt)
508 msger.debug("converting %s image to %s" % (srcimg, dstimg))
510 path = find_binary_path("qemu-img")
511 argv = [path, "convert", "-f", "vmdk", srcimg, "-O", dstfmt, dstimg]
512 elif srcfmt == "vdi":
513 path = find_binary_path("VBoxManage")
514 argv = [path, "internalcommands", "converttoraw", srcimg, dstimg]
516 raise CreatorError("Invalid soure image format: %s" % srcfmt)
518 rc = runner.show(argv)
520 msger.debug("convert successful")
522 raise CreatorError("Unable to convert disk to %s" % dstfmt)
524 def uncompress_squashfs(squashfsimg, outdir):
525 """Uncompress file system from squshfs image"""
526 unsquashfs = find_binary_path("unsquashfs")
527 args = [ unsquashfs, "-d", outdir, squashfsimg ]
528 rc = runner.show(args)
530 raise SquashfsError("Failed to uncompress %s." % squashfsimg)
532 def mkdtemp(dir = "/var/tmp", prefix = "mic-tmp-"):
533 """ FIXME: use the dir in mic.conf instead """
536 return tempfile.mkdtemp(dir = dir, prefix = prefix)
538 def get_repostrs_from_ks(ks):
539 def _get_temp_reponame(baseurl):
540 md5obj = hashlib.md5(baseurl)
541 tmpreponame = "%s" % md5obj.hexdigest()
546 for repodata in ks.handler.repo.repoList:
551 'includepkgs', # val is list
552 'excludepkgs', # val is list
564 if hasattr(repodata, attr) and getattr(repodata, attr):
565 repo[attr] = getattr(repodata, attr)
567 if 'name' not in repo:
568 repo['name'] = _get_temp_reponame(repodata.baseurl)
569 if hasattr(repodata, 'baseurl') and getattr(repodata, 'baseurl'):
570 repo['baseurl'] = SafeURL(getattr(repodata, 'baseurl'),
571 getattr(repodata, 'user', None),
572 getattr(repodata, 'passwd', None))
574 kickstart_repos.append(repo)
576 return kickstart_repos
578 def _get_uncompressed_data_from_url(url, filename, proxies):
579 filename = myurlgrab(url.full, filename, proxies)
581 if filename.endswith(".gz"):
583 runner.quiet(['gunzip', "-f", filename])
584 elif filename.endswith(".bz2"):
586 runner.quiet(['bunzip2', "-f", filename])
588 filename = filename.replace(suffix, "")
591 def _get_metadata_from_repo(baseurl, proxies, cachedir, reponame, filename,
592 sumtype=None, checksum=None):
593 url = baseurl.join(filename)
594 filename_tmp = str("%s/%s/%s" % (cachedir, reponame, os.path.basename(filename)))
595 if os.path.splitext(filename_tmp)[1] in (".gz", ".bz2"):
596 filename = os.path.splitext(filename_tmp)[0]
598 filename = filename_tmp
599 if sumtype and checksum and os.path.exists(filename):
601 sumcmd = find_binary_path("%ssum" % sumtype)
605 file_checksum = runner.outs([sumcmd, filename]).split()[0]
607 if file_checksum and file_checksum == checksum:
610 return _get_uncompressed_data_from_url(url,filename_tmp,proxies)
612 def get_metadata_from_repos(repos, cachedir):
613 my_repo_metadata = []
616 baseurl = repo.baseurl
618 if hasattr(repo, 'proxy'):
621 proxy = get_proxy_for(baseurl)
625 proxies = {str(baseurl.split(":")[0]): str(proxy)}
627 makedirs(os.path.join(cachedir, reponame))
628 url = baseurl.join("repodata/repomd.xml")
629 filename = os.path.join(cachedir, reponame, 'repomd.xml')
630 repomd = myurlgrab(url.full, filename, proxies)
632 root = xmlparse(repomd)
634 raise CreatorError("repomd.xml syntax error.")
636 ns = root.getroot().tag
637 ns = ns[0:ns.rindex("}")+1]
643 for elm in root.getiterator("%sdata" % ns):
644 if elm.attrib["type"] == "patterns":
645 filepaths['patterns'] = elm.find("%slocation" % ns).attrib['href']
646 checksums['patterns'] = elm.find("%sopen-checksum" % ns).text
647 sumtypes['patterns'] = elm.find("%sopen-checksum" % ns).attrib['type']
650 for elm in root.getiterator("%sdata" % ns):
651 if elm.attrib["type"] in ("group_gz", "group"):
652 filepaths['comps'] = elm.find("%slocation" % ns).attrib['href']
653 checksums['comps'] = elm.find("%sopen-checksum" % ns).text
654 sumtypes['comps'] = elm.find("%sopen-checksum" % ns).attrib['type']
658 for elm in root.getiterator("%sdata" % ns):
659 if elm.attrib["type"] in ("primary_db", "primary"):
660 primary_type = elm.attrib["type"]
661 filepaths['primary'] = elm.find("%slocation" % ns).attrib['href']
662 checksums['primary'] = elm.find("%sopen-checksum" % ns).text
663 sumtypes['primary'] = elm.find("%sopen-checksum" % ns).attrib['type']
669 for item in ("primary", "patterns", "comps"):
670 if item not in filepaths:
671 filepaths[item] = None
673 if not filepaths[item]:
675 filepaths[item] = _get_metadata_from_repo(baseurl,
685 repokey = _get_metadata_from_repo(baseurl,
689 "repodata/repomd.xml.key")
692 msger.debug("\ncan't get %s/%s" % (baseurl, "repodata/repomd.xml.key"))
694 my_repo_metadata.append({"name":reponame,
697 "primary":filepaths['primary'],
700 "patterns":filepaths['patterns'],
701 "comps":filepaths['comps'],
704 return my_repo_metadata
706 def get_rpmver_in_repo(repometadata):
707 for repo in repometadata:
708 if repo["primary"].endswith(".xml"):
709 root = xmlparse(repo["primary"])
710 ns = root.getroot().tag
711 ns = ns[0:ns.rindex("}")+1]
714 for elm in root.getiterator("%spackage" % ns):
715 if elm.find("%sname" % ns).text == 'rpm':
716 for node in elm.getchildren():
717 if node.tag == "%sversion" % ns:
718 versionlist.append(node.attrib['ver'])
724 key = lambda ver: map(int, ver.split('.')))).next()
726 elif repo["primary"].endswith(".sqlite"):
727 con = sqlite.connect(repo["primary"])
728 for row in con.execute("select version from packages where "
729 "name=\"rpm\" ORDER by version DESC"):
735 def get_arch(repometadata):
737 for repo in repometadata:
738 if repo["primary"].endswith(".xml"):
739 root = xmlparse(repo["primary"])
740 ns = root.getroot().tag
741 ns = ns[0:ns.rindex("}")+1]
742 for elm in root.getiterator("%spackage" % ns):
743 if elm.find("%sarch" % ns).text not in ("noarch", "src"):
744 arch = elm.find("%sarch" % ns).text
745 if arch not in archlist:
746 archlist.append(arch)
747 elif repo["primary"].endswith(".sqlite"):
748 con = sqlite.connect(repo["primary"])
749 for row in con.execute("select arch from packages where arch not in (\"src\", \"noarch\")"):
750 if row[0] not in archlist:
751 archlist.append(row[0])
756 for i in range(len(archlist)):
757 if archlist[i] not in rpmmisc.archPolicies.keys():
761 while j < len(uniq_arch):
762 if archlist[i] in rpmmisc.archPolicies[uniq_arch[j]].split(':'):
765 if uniq_arch[j] in rpmmisc.archPolicies[archlist[i]].split(':'):
767 uniq_arch[j] = archlist[i]
770 uniq_arch.remove(uniq_arch[j])
774 uniq_arch.append(archlist[i])
776 return uniq_arch, archlist
778 def get_package(pkg, repometadata, arch = None):
783 elif arch not in rpmmisc.archPolicies:
786 arches = rpmmisc.archPolicies[arch].split(':')
787 arches.append('noarch')
789 for repo in repometadata:
790 if repo["primary"].endswith(".xml"):
791 root = xmlparse(repo["primary"])
792 ns = root.getroot().tag
793 ns = ns[0:ns.rindex("}")+1]
794 for elm in root.getiterator("%spackage" % ns):
795 if elm.find("%sname" % ns).text == pkg:
796 if elm.find("%sarch" % ns).text in arches:
797 version = elm.find("%sversion" % ns)
798 tmpver = "%s-%s" % (version.attrib['ver'], version.attrib['rel'])
801 location = elm.find("%slocation" % ns)
802 pkgpath = "%s" % location.attrib['href']
805 if repo["primary"].endswith(".sqlite"):
806 con = sqlite.connect(repo["primary"])
808 sql = 'select version, release, location_href from packages ' \
809 'where name = "%s" and arch IN ("%s")' % \
810 (pkg, '","'.join(arches))
811 for row in con.execute(sql):
812 tmpver = "%s-%s" % (row[0], row[1])
815 pkgpath = "%s" % row[2]
819 sql = 'select version, release, location_href from packages ' \
820 'where name = "%s"' % pkg
821 for row in con.execute(sql):
822 tmpver = "%s-%s" % (row[0], row[1])
825 pkgpath = "%s" % row[2]
830 makedirs("%s/packages/%s" % (target_repo["cachedir"], target_repo["name"]))
831 url = target_repo["baseurl"].join(pkgpath)
832 filename = str("%s/packages/%s/%s" % (target_repo["cachedir"], target_repo["name"], os.path.basename(pkgpath)))
833 if os.path.exists(filename):
834 ret = rpmmisc.checkRpmIntegrity('rpm', filename)
838 msger.warning("package %s is damaged: %s" %
839 (os.path.basename(filename), filename))
842 pkg = myurlgrab(url.full, filename, target_repo["proxies"])
847 def get_source_name(pkg, repometadata):
849 def get_bin_name(pkg):
850 m = RPM_RE.match(pkg)
855 def get_src_name(srpm):
856 m = SRPM_RE.match(srpm)
864 pkg_name = get_bin_name(pkg)
868 for repo in repometadata:
869 if repo["primary"].endswith(".xml"):
870 root = xmlparse(repo["primary"])
871 ns = root.getroot().tag
872 ns = ns[0:ns.rindex("}")+1]
873 for elm in root.getiterator("%spackage" % ns):
874 if elm.find("%sname" % ns).text == pkg_name:
875 if elm.find("%sarch" % ns).text != "src":
876 version = elm.find("%sversion" % ns)
877 tmpver = "%s-%s" % (version.attrib['ver'], version.attrib['rel'])
880 fmt = elm.find("%sformat" % ns)
882 fns = fmt.getchildren()[0].tag
883 fns = fns[0:fns.rindex("}")+1]
884 pkgpath = fmt.find("%ssourcerpm" % fns).text
888 if repo["primary"].endswith(".sqlite"):
889 con = sqlite.connect(repo["primary"])
890 for row in con.execute("select version, release, rpm_sourcerpm from packages where name = \"%s\" and arch != \"src\"" % pkg_name):
891 tmpver = "%s-%s" % (row[0], row[1])
893 pkgpath = "%s" % row[2]
898 return get_src_name(pkgpath)
902 def get_pkglist_in_patterns(group, patterns):
906 root = xmlparse(patterns)
908 raise SyntaxError("%s syntax error." % patterns)
910 for elm in list(root.getroot()):
912 ns = ns[0:ns.rindex("}")+1]
913 name = elm.find("%sname" % ns)
914 summary = elm.find("%ssummary" % ns)
915 if name.text == group or summary.text == group:
923 for requires in list(elm):
924 if requires.tag.endswith("requires"):
931 for pkg in list(requires):
932 pkgname = pkg.attrib["name"]
933 if pkgname not in pkglist:
934 pkglist.append(pkgname)
938 def get_pkglist_in_comps(group, comps):
942 root = xmlparse(comps)
944 raise SyntaxError("%s syntax error." % comps)
946 for elm in root.getiterator("group"):
948 name = elm.find("name")
949 if id.text == group or name.text == group:
950 packagelist = elm.find("packagelist")
957 for require in elm.getiterator("packagereq"):
958 if require.tag.endswith("packagereq"):
959 pkgname = require.text
960 if pkgname not in pkglist:
961 pkglist.append(pkgname)
965 def is_statically_linked(binary):
966 return ", statically linked, " in runner.outs(['file', binary])
968 def setup_qemu_emulator(rootdir, arch):
969 # mount binfmt_misc if it doesn't exist
970 if not os.path.exists("/proc/sys/fs/binfmt_misc"):
971 modprobecmd = find_binary_path("modprobe")
972 runner.show([modprobecmd, "binfmt_misc"])
973 if not os.path.exists("/proc/sys/fs/binfmt_misc/register"):
974 mountcmd = find_binary_path("mount")
975 runner.show([mountcmd, "-t", "binfmt_misc", "none", "/proc/sys/fs/binfmt_misc"])
977 # qemu_emulator is a special case, we can't use find_binary_path
978 # qemu emulator should be a statically-linked executable file
979 if arch == "aarch64":
980 node = "/proc/sys/fs/binfmt_misc/aarch64"
981 if os.path.exists("/usr/bin/qemu-arm64") and is_statically_linked("/usr/bin/qemu-arm64"):
982 arm_binary = "qemu-arm64"
983 elif os.path.exists("/usr/bin/qemu-aarch64") and is_statically_linked("/usr/bin/qemu-aarch64"):
984 arm_binary = "qemu-aarch64"
985 elif os.path.exists("/usr/bin/qemu-arm64-static"):
986 arm_binary = "qemu-arm64-static"
987 elif os.path.exists("/usr/bin/qemu-aarch64-static"):
988 arm_binary = "qemu-aarch64-static"
990 raise CreatorError("Please install a statically-linked %s" % arm_binary)
992 node = "/proc/sys/fs/binfmt_misc/arm"
993 arm_binary = "qemu-arm"
994 if not os.path.exists("/usr/bin/qemu-arm") or not is_statically_linked("/usr/bin/qemu-arm"):
995 arm_binary = "qemu-arm-static"
996 if not os.path.exists("/usr/bin/%s" % arm_binary):
997 raise CreatorError("Please install a statically-linked %s" % arm_binary)
999 qemu_emulator = "/usr/bin/%s" % arm_binary
1001 if not os.path.exists(rootdir + "/usr/bin"):
1002 makedirs(rootdir + "/usr/bin")
1003 shutil.copy(qemu_emulator, rootdir + qemu_emulator)
1005 # disable selinux, selinux will block qemu emulator to run
1006 if os.path.exists("/usr/sbin/setenforce"):
1007 msger.info('Try to disable selinux')
1008 runner.show(["/usr/sbin/setenforce", "0"])
1010 # unregister it if it has been registered and is a dynamically-linked executable
1011 if os.path.exists(node):
1012 qemu_unregister_string = "-1\n"
1013 with open(node, "w") as fd:
1014 fd.write(qemu_unregister_string)
1016 # register qemu emulator for interpreting other arch executable file
1017 if not os.path.exists(node):
1018 if arch == "aarch64":
1019 qemu_arm_string = ":aarch64:M::\\x7fELF\\x02\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x02\\x00\\xb7:\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x00\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xfe\\xff\\xff:%s:\n" % qemu_emulator
1021 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
1022 with open("/proc/sys/fs/binfmt_misc/register", "w") as fd:
1023 fd.write(qemu_arm_string)
1025 return qemu_emulator
1027 def SrcpkgsDownload(pkgs, repometadata, instroot, cachedir):
1028 def get_source_repometadata(repometadata):
1030 for repo in repometadata:
1031 if repo["name"].endswith("-source"):
1032 src_repometadata.append(repo)
1033 if src_repometadata:
1034 return src_repometadata
1037 def get_src_name(srpm):
1038 m = SRPM_RE.match(srpm)
1043 src_repometadata = get_source_repometadata(repometadata)
1045 if not src_repometadata:
1046 msger.warning("No source repo found")
1052 for repo in src_repometadata:
1053 cachepath = "%s/%s/packages/*.src.rpm" %(cachedir, repo["name"])
1054 lpkgs_path += glob.glob(cachepath)
1056 for lpkg in lpkgs_path:
1057 lpkg_name = get_src_name(os.path.basename(lpkg))
1058 lpkgs_dict[lpkg_name] = lpkg
1059 localpkgs = lpkgs_dict.keys()
1062 destdir = instroot+'/usr/src/SRPMS'
1063 if not os.path.exists(destdir):
1064 os.makedirs(destdir)
1068 srcpkg_name = get_source_name(_pkg, repometadata)
1071 srcpkgset.add(srcpkg_name)
1073 for pkg in list(srcpkgset):
1074 if pkg in localpkgs:
1076 shutil.copy(lpkgs_dict[pkg], destdir)
1077 src_pkgs.append(os.path.basename(lpkgs_dict[pkg]))
1079 src_pkg = get_package(pkg, src_repometadata, 'src')
1081 shutil.copy(src_pkg, destdir)
1082 src_pkgs.append(src_pkg)
1083 msger.info("%d source packages gotten from cache" % cached_count)
1087 def strip_end(text, suffix):
1088 if not text.endswith(suffix):
1090 return text[:-len(suffix)]