def hostAction(context): subDict = getStringSubstitutionDict() log.debug('Dumping bootloader variables...') safeDict = subDict.copy() del safeDict['passwordLine'] log.debug(str(safeDict)) makeBackups() if userchoices.getUpgrade(): discoverLocation(subDict) subDict = getStringSubstitutionDict() context.cb.pushStatusGroup(5) context.cb.pushStatus('Copying the GRUB images') copyGrubStageImages() context.cb.popStatus() context.cb.pushStatus('Writing the GRUB config files') writeGrubConfFiles(subDict) context.cb.popStatus() context.cb.pushStatus('Making the initial ramdisk') makeInitialRamdisk(subDict) context.cb.popStatus() context.cb.pushStatus('Writing GRUB to the Master Boot Record') w = MBRWriter() w.write(subDict) context.cb.popStatus() context.cb.popStatusGroup() sanityCheck(subDict)
def doit(context, stepListType='install'): '''Executes the steps needed to do the actual install or upgrade.''' if stepListType == 'install': if userchoices.getUpgrade(): steps = _upgradeSteps() else: steps = _installSteps() elif stepListType == 'loadDrivers': steps = _loadDriverSteps() assert steps try: context.cb.pushStatusGroup(sum([step[0] for step in steps])) for portion, desc, msgID, func in steps: context.cb.pushStatus(desc, portion, msgID=msgID) func(context) context.cb.popStatus() context.cb.popStatusGroup() if stepListType == 'install': log.info("installation complete") elif stepListType == 'loadDrivers': log.info("driver loading complete") except exception.InstallCancelled: pass return
def _runtimeActions(self): errors = [] warnings = [] if userchoices.getActivateNetwork() and userchoices.getCosNICs() and \ not networking.connected() and not userchoices.getUpgrade(): try: networking.cosConnectForInstaller() except Exception, ex: log.exception(str(ex)) warnings.append("warning: could not bring up network -- %s\n" % str(ex))
def hostActionMountFileSystems(context): # XXX - we only use one virtual device for now virtualDevs = userchoices.getVirtualDevices() assert len(virtualDevs) == 1 or len(virtualDevs) == 0 requests = allUserPartitionRequests() requests.sort(sortByMountPoint=True) for request in requests: # skip vmfs partitions since they can't be mounted if not request.mountPoint: continue mountPoint = os.path.normpath(consts.HOST_ROOT + request.mountPoint) if not os.path.exists(mountPoint): os.makedirs(mountPoint) log.debug("Mounting %s -> %s" % \ (request.consoleDevicePath, mountPoint)) request.fsType.mount(request.consoleDevicePath, mountPoint) if request.clearContents: # Clear out the contents of the drive. Removing the files might be # preferable to a reformat since we preserve the UUID. for name in os.listdir(mountPoint): path = os.path.join(mountPoint, name) if os.path.isdir(path): shutil.rmtree(path) else: os.remove(path) if userchoices.getUpgrade(): upgradeMounts = [(consts.ESX3_INSTALLATION, userchoices.getRootUUID()['uuid'])] if userchoices.isCombinedBootAndRootForUpgrade(): log.debug("Linking boot") # No /boot partition, need to create a link to the old one. os.symlink( os.path.join(consts.ESX3_INSTALLATION.lstrip('/'), "boot"), os.path.join(consts.HOST_ROOT, "boot")) else: upgradeMounts.append(("/boot", userchoices.getBootUUID()['uuid'])) for partMountPoint, uuid in upgradeMounts: mountPoint = os.path.normpath(consts.HOST_ROOT + partMountPoint) if not os.path.exists(mountPoint): os.makedirs(mountPoint) log.debug("Mounting %s -> %s" % (uuid, mountPoint)) rc = util.mount(uuid, mountPoint, isUUID=True) assert rc == 0 # TODO: handle errors
class Scui: '''Class used to do a scripted install.''' def __init__(self, script): # Setup error handling stuff first so any errors during driver loading # or the main bits gets handled correctly. global tty6Handler sys.excepthook = lambda type, value, tb: \ exception.handleException(self, (type, value, tb), traceInDetails=False) try: # The scui uses logging to write out user-visible output so we need # another logger for tty6 (which stdout is redirected to by # weasel.py). tty6Handler = logging.StreamHandler(sys.stdout) tty6Handler.setFormatter(formatterForHuman) tty6Handler.setLevel(LOGLEVEL_HUMAN) log.addHandler(tty6Handler) except IOError: #Could not open for writing. Probably not the root user pass self._execute(script) @applychoices.ensureDriversAreLoaded def _execute(self, script): from preparser import ScriptedInstallPreparser from scriptedinstallutil import Result errors = None installCompleted = False try: self.sip = ScriptedInstallPreparser(script) (result, errors, warnings) = self.sip.parseAndValidate() if warnings: log.warn("\n".join(warnings)) if errors: log.error("\n".join(errors)) userchoices.setReboot(False) if result != Result.FAIL: # Bring up whatever is needed for the install to happen. For # example, get the network going for non-local installs. errors, warnings = self._runtimeActions() if warnings: log.warn("\n".join(warnings)) if errors: log.error("\n".join(errors)) userchoices.setReboot(False) if not errors: if userchoices.getDebug(): log.info(userchoices.dumpToString()) if userchoices.getDryrun(): log.log(LOGLEVEL_HUMAN, "dry run specified, stopping.") else: context = applychoices.Context( applychoices.ProgressCallback( applychoices.StdoutProgressDelegate())) applychoices.doit(context) installCompleted = True media.runtimeActionEjectMedia() except IOError, e: log.error("error: cannot open file -- %s\n" % str(e)) if not installCompleted: log.error("installation aborted") if not installCompleted or not userchoices.getReboot(): msg = "Press <enter> to reboot..." if userchoices.getUpgrade(): msg = "The machine will reboot automatically or\n" \ "press <enter> to reboot immediately..." raw_input(msg)
def sanityCheckPartitionRequests(partRequestSetList=None, checkSizing=False): '''Check the partition requests to make sure the expected requests (e.g. "/boot" and "/") are there. The given list of PartitionRequestSets is checked against the following constraints: * There is a "/boot" partition that is on a physical partition and is greater than or equal to 100MB in size. * There is a "/" partition and it greater than or equal to 100MB in size. The return value is a pair containing any error messages and warnings. >>> from devices import DiskSet >>> ds = DiskSet() >>> prs = PartitionRequestSet(ds.values()[0]) >>> prs.append(PartitionRequest("/boot", minimumSize=100)) >>> # There is no root partition, we should get an error. ... sanityCheckPartitionRequests([prs]) (['no root partition found.'], []) >>> prs.append(PartitionRequest("/", minimumSize=100)) >>> sanityCheckPartitionRequests([prs]) ([], []) ''' if partRequestSetList is None: partRequestSetList = _allUserPartitionRequestSets() errors = [] bootRequest = None rootRequest = None if checkSizing and partRequestSetList: # Download the package data so we can figure out the minimum partition # sizes weaselConfig = systemsettings.WeaselConfig() packagesXML = packages.getPackagesXML(weaselConfig.packageGroups) packageData = packages.PackageData(packagesXML.fullInstallDepot) fileSizes = packageData.fileDict else: fileSizes = {} swapSize = 0 for reqSet in partRequestSetList: clearChoice = userchoices.getClearPartitions() if reqSet.device and reqSet.device.deviceExists and \ reqSet.deviceName not in clearChoice.get('drives', []): errors.append( '%s needs to have its partitions cleared before it can be ' 'repartitioned.' % reqSet.device.name) minSize = reqSet.getMinimumSize() if reqSet.device and minSize > reqSet.device.getSizeInMegabytes(): errors.append( 'partition sizes for %s are too large (%d MB > %d MB).' % (reqSet.device.name, minSize, reqSet.device.getSizeInMegabytes())) sizeDict = reqSet.findMinimumRequestSizes(fileSizes) for req in reqSet: if isinstance(req.fsType, fsset.swapFileSystem): swapSize += req.minimumSize continue if not req.mountPoint: continue if req.mountPoint.startswith('/') and \ req.minimumSize < sizeDict[req.mountPoint]: errors.append('The "%s" partition needs to be at least %d ' 'megabytes in size.' % (req.mountPoint, sizeDict[req.mountPoint])) if (not isinstance(reqSet.device, devices.VirtualDiskDev) and req.mountPoint == '/boot'): bootRequest = req if req.mountPoint == '/': rootRequest = req # TODO: Check for anything starting with '/etc' or '/boot'. if req.mountPoint in INVALID_MOUNTPOINTS: errors.append('%s cannot be on a separate partition.' % req.mountPoint) if swapSize == 0: errors.append('A swap partition is required to use ESX.') elif swapSize < 256: errors.append('Swap space must be at least 256MB in size.') if userchoices.getUpgrade(): if not userchoices.getBootUUID(): # TODO: deal with no boot partition, everything in root... errors.append('no "/boot" partition specified for upgrade.') elif not bootRequest: errors.append('no "/boot" partition found.') elif bootRequest.minimumSize < (BOOT_MINIMUM_SIZE - PARTITION_FUDGE_SIZE): errors.append('"/boot" partition must be at least %dMB in size.' % BOOT_MINIMUM_SIZE) if not rootRequest: errors.append("A '/' (root) partition was not specified for the " "Service Console virtual disk. The Service Console " "can not boot without a '/' partition.") return errors
def writeGrubConfFiles(stringSubstitutionDict): '''make grub config files''' # make sure the expected directories exist if not os.path.exists(grub_dir): os.makedirs(grub_dir) if not os.path.exists(os.path.dirname(sysconfig_grub_file)): os.makedirs(os.path.dirname(sysconfig_grub_file)) newEntry = grub_conf_entry % stringSubstitutionDict debugEntrySubstDict = stringSubstitutionDict.copy() debugEntrySubstDict['label'] = "Troubleshooting mode" debugEntrySubstDict['bootDirRelativeToGrub'] += "trouble/" debugEntrySubstDict['kernelOptions'] += " trouble" debugEntry = grub_conf_entry % debugEntrySubstDict choices = userchoices.getBoot() if (os.path.exists(grub_conf_file) and (userchoices.getUpgrade() or choices.get('upgrade', False))): # For an upgrade, we need to preserve all the settings in the file, # not just the titles. Otherwise, we lose things like password. grubFile = open(grub_conf_file) grubContents = grubFile.read() grubFile.close() grubContents = removeTitle(grubContents, newEntry.split('\n')[0]) grubContents = removeTitle(grubContents, debugEntry.split('\n')[0]) grubContents = grubContents.replace('VMware ESX Server', 'VMware ESX Server 3') grubContents = grubContents.replace( 'Service Console only', 'ESX Server 3 Service Console only') else: grubContents = grub_conf_header % stringSubstitutionDict grubContents = insertTitle(grubContents, debugEntry) grubContents = insertTitle(grubContents, newEntry) grubContents = changeSetting(grubContents, "default", "0") if userchoices.getUpgrade(): grubContents = writeUpgradeFiles(grubContents) # Write the whole file out first and then use rename to atomically install # it in the directory, we don't want to put a broken file in there during # an upgrade. tmpPath = os.tempnam(os.path.dirname(grub_conf_file), "grub.conf") fp = open(tmpPath, 'w') fp.write(grubContents) fp.close() os.chmod(tmpPath, 0600) os.rename(tmpPath, grub_conf_file) fp = open(device_map_file, 'w') fp.write(device_map % stringSubstitutionDict) fp.close() fp = open(sysconfig_grub_file, 'w') fp.write(sysconfig_grub % stringSubstitutionDict) fp.close()
def getStringSubstitutionDict(): label, version = getKernelLabelAndVersion() # Get the kernel mem to put in the boot command line. kernelMemInMB = vmkctl.MemoryInfoImpl().GetServiceConsoleReservedMem() upperMemInKB = str(kernelMemInMB*1024) disks = devices.DiskSet() if userchoices.getUpgrade(): # We reuse the boot partition from the old install. bootPath = os.path.join(consts.ESX3_INSTALLATION, "boot") else: bootPath = "/boot" slashBootPartition = disks.findPartitionContaining(bootPath) if not slashBootPartition: raise PartitionNotFound(bootPath) devPartName = slashBootPartition.consoleDevicePath if not devPartName: raise MissingConsoleDevicePath(slashBootPartition) slashBootPartUuid = getUuid(devPartName) diskIndex, partIndex = grubDiskAndPartitionIndicies(slashBootPartition) if diskIndex != 0: log.warn('Installing GRUB to the MBR of a disk that was not the first' ' disk reported by the BIOS. User must change their BIOS' ' settings if they want to boot from this disk') slashBootPartNum = partIndex grubInstallDevice = findGrubInstallDevice(slashBootPartition) # This code protects against instability with the /vmfs partition # going missing. We try to use the canonical path first, however if it # isn't there, use the /dev/sdX path and warn. The variable is used # in device.map. if os.path.exists(grubInstallDevice.path): installerDevDiskName = grubInstallDevice.path elif os.path.exists(grubInstallDevice.consoleDevicePath): log.warn('The normal path to the boot disk did not exist. ' 'Using console device path instead.') installerDevDiskName = grubInstallDevice.consoleDevicePath else: raise RuntimeError, "Couldn't find a place to write GRUB." # decide between installing to the MBR or the first partition bootChoices = userchoices.getBoot() if bootChoices and \ bootChoices['location'] == userchoices.BOOT_LOC_PARTITION: grubInstallLocation = '(hd0,%s)' % slashBootPartNum log.info('Installing GRUB to the first partition of %s ' % installerDevDiskName) else: grubInstallLocation = '(hd0)' log.info('Installing GRUB to the MBR of (%s)' % installerDevDiskName) # need to tell grub.conf where it will find the kernel and initrd # relative to the root of the partition it searches. if slashBootPartition.mountPoint in [ '/boot', os.path.join(consts.ESX3_INSTALLATION, "boot")]: bootDirRelativeToGrub = '/' elif slashBootPartition.mountPoint in ['/', consts.ESX3_INSTALLATION]: bootDirRelativeToGrub = '/boot/' kernelOptions = getKernelOptions(str(kernelMemInMB)) passwordLine = getPasswordLine() substitutes = dict( label = label, version = version, devPartName = devPartName, kernel_file = kernel_file, initrd_file = initrd_file, passwordLine = passwordLine, upperMemInKB = upperMemInKB, kernelMemInMB = kernelMemInMB, kernelOptions = kernelOptions, slashBootPartNum = slashBootPartNum, slashBootPartUuid = slashBootPartUuid, grubInstallLocation = grubInstallLocation, installerDevDiskName = installerDevDiskName, bootDirRelativeToGrub = bootDirRelativeToGrub, ) return substitutes
def getStringSubstitutionDict(): label, version = getKernelLabelAndVersion() # Get the kernel mem to put in the boot command line. kernelMemInMB = vmkctl.MemoryInfoImpl().GetServiceConsoleReservedMem() upperMemInKB = str(kernelMemInMB * 1024) disks = devices.DiskSet() if userchoices.getUpgrade(): # We reuse the boot partition from the old install. bootPath = os.path.join(consts.ESX3_INSTALLATION, "boot") else: bootPath = "/boot" slashBootPartition = disks.findPartitionContaining(bootPath) if not slashBootPartition: raise PartitionNotFound(bootPath) devPartName = slashBootPartition.consoleDevicePath if not devPartName: raise MissingConsoleDevicePath(slashBootPartition) slashBootPartUuid = getUuid(devPartName) diskIndex, partIndex = grubDiskAndPartitionIndicies(slashBootPartition) if diskIndex != 0: log.warn('Installing GRUB to the MBR of a disk that was not the first' ' disk reported by the BIOS. User must change their BIOS' ' settings if they want to boot from this disk') slashBootPartNum = partIndex grubInstallDevice = findGrubInstallDevice(slashBootPartition) # This code protects against instability with the /vmfs partition # going missing. We try to use the canonical path first, however if it # isn't there, use the /dev/sdX path and warn. The variable is used # in device.map. if os.path.exists(grubInstallDevice.path): installerDevDiskName = grubInstallDevice.path elif os.path.exists(grubInstallDevice.consoleDevicePath): log.warn('The normal path to the boot disk did not exist. ' 'Using console device path instead.') installerDevDiskName = grubInstallDevice.consoleDevicePath else: raise RuntimeError, "Couldn't find a place to write GRUB." # decide between installing to the MBR or the first partition bootChoices = userchoices.getBoot() if bootChoices and \ bootChoices['location'] == userchoices.BOOT_LOC_PARTITION: grubInstallLocation = '(hd0,%s)' % slashBootPartNum log.info('Installing GRUB to the first partition of %s ' % installerDevDiskName) else: grubInstallLocation = '(hd0)' log.info('Installing GRUB to the MBR of (%s)' % installerDevDiskName) # need to tell grub.conf where it will find the kernel and initrd # relative to the root of the partition it searches. if slashBootPartition.mountPoint in [ '/boot', os.path.join(consts.ESX3_INSTALLATION, "boot") ]: bootDirRelativeToGrub = '/' elif slashBootPartition.mountPoint in ['/', consts.ESX3_INSTALLATION]: bootDirRelativeToGrub = '/boot/' kernelOptions = getKernelOptions(str(kernelMemInMB)) passwordLine = getPasswordLine() substitutes = dict( label=label, version=version, devPartName=devPartName, kernel_file=kernel_file, initrd_file=initrd_file, passwordLine=passwordLine, upperMemInKB=upperMemInKB, kernelMemInMB=kernelMemInMB, kernelOptions=kernelOptions, slashBootPartNum=slashBootPartNum, slashBootPartUuid=slashBootPartUuid, grubInstallLocation=grubInstallLocation, installerDevDiskName=installerDevDiskName, bootDirRelativeToGrub=bootDirRelativeToGrub, ) return substitutes