def build(self, destdir, log): """ Create the install root, copy in the release data, write out the bootloader configuration and kernels. @param destdir: Per-release installation data directory. @param log: Open log file. """ try: # Copy the installation data log.write("Copying release files from %s to %s\n" % (os.path.join( self.cdroot, _getCDRelease(self.cdroot)), destdir)) utils.copyRecursive(os.path.join(self.cdroot, _getCDRelease(self.cdroot)), destdir, symlinks=True) # If there are packages, copy those too packagedir = os.path.join(self.pkgroot, RELEASE_PACKAGE_PATH) log.write("Copying packages from %s to %s\n" % (packagedir, os.path.join(destdir, 'packages'))) if (os.path.exists(packagedir)): utils.copyRecursive(packagedir, os.path.join(destdir, 'packages'), symlinks=True) # Copy in any local data if (len(self.localData)): # Create the local directory localdir = os.path.join(destdir, 'local') os.mkdir(localdir) for path in self.localData: log.write( "Copying extra local data from %s to %s\n" % (path, os.path.join(localdir, os.path.basename(path)))) if (os.path.isdir(path)): utils.copyRecursive(path, os.path.join( localdir, os.path.basename(path)), symlinks=True) else: utils.copyWithOwnership(path, localdir) # Add the FarBot package installer script and make it executable log.write("Installing package installer script to %s\n" % destdir) utils.copyWithOwnership(farb.INSTALL_PACKAGE_SH, destdir) os.chmod( os.path.join(destdir, os.path.basename(farb.INSTALL_PACKAGE_SH)), 0755) except exceptions.IOError, e: raise ReleaseAssembleError, "An I/O error occured: %s" % e
def _doConfigureBootLoader(self, destdir): """ Write out the forth for the boot loader installation menu """ subst = {} # Format Strings variableFormat = 'variable %s\n' menuItemFormat = 'printmenuitem ." %s" %s !\n' ifBlockFormat = 'dup %s @ = if\ns" /%s/boot.conf" read-conf\n0 boot-conf exit\nthen\n' # Output variables = cStringIO.StringIO() menuItems = cStringIO.StringIO() ifBlocks = cStringIO.StringIO() # Generate the code blocks for install in self.installAssemblers: # Variable declaration variableName = install.name + '_key' variables.write(variableFormat % (variableName)) # Menu item menuItems.write(menuItemFormat % (install.description, variableName)) # if block ifBlocks.write(ifBlockFormat % (variableName, install.name)) # Write out the netinstall.4th file subst['variables'] = variables.getvalue() subst['menuitems'] = menuItems.getvalue() subst['ifblocks'] = ifBlocks.getvalue() output = open(os.path.join(destdir, 'netinstall.4th'), 'w') template = open(farb.NETINSTALL_FORTH_TMPL, 'r') for line in template: output.write(line % (subst)) output.close() template.close() # Copy in our loader.conf and loader.rc utils.copyWithOwnership(farb.LOADER_CONF, destdir) utils.copyWithOwnership(farb.LOADER_RC, destdir)
def build(self, destdir, log): """ Create the install root, copy in the release data, write out the bootloader configuration and kernels. @param destdir: Per-release installation data directory. @param log: Open log file. """ try: # Copy the installation data log.write("Copying release files from %s to %s\n" % (os.path.join(self.cdroot, _getCDRelease(self.cdroot)), destdir)) utils.copyRecursive(os.path.join(self.cdroot, _getCDRelease(self.cdroot)), destdir, symlinks=True) # If there are packages, copy those too packagedir = os.path.join(self.pkgroot, RELEASE_PACKAGE_PATH) log.write("Copying packages from %s to %s\n" % (packagedir, os.path.join(destdir, 'packages'))) if (os.path.exists(packagedir)): utils.copyRecursive(packagedir, os.path.join(destdir, 'packages'), symlinks=True) # Copy in any local data if (len(self.localData)): # Create the local directory localdir = os.path.join(destdir, 'local') os.mkdir(localdir) for path in self.localData: log.write("Copying extra local data from %s to %s\n" % (path, os.path.join(localdir, os.path.basename(path)))) if (os.path.isdir(path)): utils.copyRecursive(path, os.path.join(localdir, os.path.basename(path)), symlinks=True) else: utils.copyWithOwnership(path, localdir) # Add the FarBot package installer script and make it executable log.write("Installing package installer script to %s\n" % destdir) utils.copyWithOwnership(farb.INSTALL_PACKAGE_SH, destdir) os.chmod(os.path.join(destdir, os.path.basename(farb.INSTALL_PACKAGE_SH)), 0755) except exceptions.IOError, e: raise ReleaseAssembleError, "An I/O error occured: %s" % e
class PackageChrootAssembler(object): """ Extract release binaries into a chroot in which packages can be built. """ def __init__(self, releaseroot, chroot): """ Create a new PackageChrootAssembler instance @param releaseroot: Directory that contains built release in R/ @param chroot: Chroot directory to install to """ self.cdroot = os.path.join(releaseroot, RELEASE_CD_PATH) self.chroot = chroot def _extractDist(self, distdir, distname, target, log): log.write("Extracting dist %s from %s to %s\n" % (distname, distdir, target)) # Create target directory if it isn't already there if (not os.path.exists(target)): os.makedirs(target) # Extract a distribution set into the chroot with tar. We use the # subprocess module directly here rather than the helper function # _runCommand so we will have control over the process' standard input. argv = [TAR_PATH, '--unlink', '-xpvzf', '-', '-C', target] proc = subprocess.Popen(argv, stdout=log, stderr=log, env=ROOT_ENV, stdin=subprocess.PIPE) path = os.path.join(distdir, distname.lower()) files = glob.glob(path + '.??') for filename in files: file = open(filename, 'rb') proc.stdin.write(file.read()) file.close() proc.stdin.close() retval = proc.wait() if retval != 0: raise TarCommandError, "%s returned with exit code %d while extracting dist %s" % ( argv[0], retval, distname) def _extractAll(self, dists, log): # Extract each dist in the chroot for key in dists.iterkeys(): distdir = os.path.join( self.cdroot, os.path.join(self.cdroot, _getCDRelease(self.cdroot)), key) for distname in dists[key]: # Just to make things difficult, not all dists extract # relative to /. TODO: I'd love to handle this without hard # coding. The only place I see the relative path these # distribution sets get extracted to is in the Distribution # structs near the top of /usr/src/usr.sbin/sysinstall/dist.c. # Hopefully this does not change too much from release to # release. if key == 'src': target = os.path.join(self.chroot, 'usr', 'src') elif key == 'kernels': target = os.path.join(self.chroot, 'boot') else: target = self.chroot self._extractDist(distdir, distname, target, log) def extract(self, dists, log): """ Extract the release into a chroot @param dists: Dictionary of distribution sets to extract. The key is a string corresponding to the name of the dist, and the value is an array of the subdists in that directory. For dists that don't have a lot of subdists, this value will just be an array containing the same string as the key. @param log: Open log file """ # Clean out chroot try: cc = ChrootCleaner(self.chroot) cc.clean(log) except ChrootCleanerError, e: raise PackageChrootAssemblerError, "Error cleaning chroot %s: %s" % ( self.chroot, e) # Then extract all dists and add /etc/resolv.conf to chroot try: self._extractAll(dists, log) utils.copyWithOwnership(os.path.join(ROOT_PATH, RESOLV_CONF), os.path.join(self.chroot, RESOLV_CONF)) except Exception, e: raise PackageChrootAssemblerError, "Error populating chroot %s: %s" % ( self.chroot, e)
def test_copyWithOwnership(self): utils.copyWithOwnership(self.copySrc, self.copyDst) # TODO Would need root running this test in order to test # if the ownership copying code works self.assert_(os.path.exists(os.path.join(DATA_DIR, 'testcopy')))