def generate_bmap(self): """ Generate block map file for an image. The idea is that while disk images we generate may be large (e.g., 4GiB), they may actually contain only little real data, e.g., 512MiB. This data are files, directories, file-system meta-data, partition table, etc. In other words, when flashing the image to the target device, you do not have to copy all the 4GiB of data, you can copy only 512MiB of it, which is 4 times faster. This function generates the block map file for an arbitrary image that mic has generated. The block map file is basically an XML file which contains a list of blocks which have to be copied to the target device. The other blocks are not used and there is no need to copy them. This function assumes the image file was originally created as a sparse file. To generate the block map we use the FIBMAP ioctl. """ if self.bmap_needed is None: return msger.info("Generating the map file(s)") for name in self.__disks.keys(): image = self._full_path(self.__imgdir, name, self.__disk_format) bmap_file = self._full_path(self.__imgdir, name, "bmap") msger.debug("Generating block map file '%s'" % bmap_file) image_size = os.path.getsize(image) with open(bmap_file, "w") as f_bmap: with open(image, "rb") as f_image: # Get the block size of the host file-system for the image # file by calling the FIGETBSZ ioctl (number 2). block_size = unpack('I', ioctl(f_image, 2, pack('I', 0)))[0] blocks_cnt = (image_size + block_size - 1) / block_size # Write general information to the block map file, without # block map itself, which will be written next. xml = self._bmap_file_start(block_size, image_size, blocks_cnt) f_bmap.write(xml) # Generate the block map and write it to the XML block map # file as we go. mapped_cnt = 0 for first, last in self._get_ranges(f_image, blocks_cnt): mapped_cnt += last - first + 1 sha1 = misc.calc_hashes(image, ('sha1', ), first * block_size, (last + 1) * block_size) f_bmap.write("\t\t<Range sha1=\"%s\"> %s-%s " \ "</Range>\n" % (sha1[0], first, last)) # Finish the block map file xml = self._bmap_file_end(mapped_cnt, block_size, blocks_cnt) f_bmap.write(xml)
def _write_image_xml(self): imgarch = "i686" if self.target_arch and self.target_arch.startswith("arm"): imgarch = "arm" xml = "<image>\n" name_attributes = "" if self.appliance_version: name_attributes += " version='%s'" % self.appliance_version if self.appliance_release: name_attributes += " release='%s'" % self.appliance_release xml += " <name%s>%s</name>\n" % (name_attributes, self.name) xml += " <domain>\n" # XXX don't hardcode - determine based on the kernel we installed for # grub baremetal vs xen xml += " <boot type='hvm'>\n" xml += " <guest>\n" xml += " <arch>%s</arch>\n" % imgarch xml += " </guest>\n" xml += " <os>\n" xml += " <loader dev='hd'/>\n" xml += " </os>\n" i = 0 for name in self.__disks.keys(): full_name = self._full_name(name, self.__disk_format) xml += " <drive disk='%s' target='hd%s'/>\n" \ % (full_name, chr(ord('a') + i)) i = i + 1 xml += " </boot>\n" xml += " <devices>\n" xml += " <vcpu>%s</vcpu>\n" % self.vcpu xml += " <memory>%d</memory>\n" %(self.vmem * 1024) for network in self.ks.handler.network.network: xml += " <interface/>\n" xml += " <graphics/>\n" xml += " </devices>\n" xml += " </domain>\n" xml += " <storage>\n" if self.checksum is True: for name in self.__disks.keys(): diskpath = self._full_path(self._outdir, name, \ self.__disk_format) full_name = self._full_name(name, self.__disk_format) msger.debug("Generating disk signature for %s" % full_name) xml += " <disk file='%s' use='system' format='%s'>\n" \ % (full_name, self.__disk_format) hashes = misc.calc_hashes(diskpath, ('sha1', 'sha256')) xml += " <checksum type='sha1'>%s</checksum>\n" \ % hashes[0] xml += " <checksum type='sha256'>%s</checksum>\n" \ % hashes[1] xml += " </disk>\n" else: for name in self.__disks.keys(): full_name = self._full_name(name, self.__disk_format) xml += " <disk file='%s' use='system' format='%s'/>\n" \ % (full_name, self.__disk_format) xml += " </storage>\n" xml += "</image>\n" msger.debug("writing image XML to %s/%s.xml" %(self._outdir, self.name)) cfg = open("%s/%s.xml" % (self._outdir, self.name), "w") cfg.write(xml) cfg.close()