class SetLogicalNVDIMMDrivesCommand(RdmcCommandBase): def __init__(self, rdmcObj): RdmcCommandBase.__init__(self, \ name='setbackupdevices', \ usage='setbackupdevices (--device=ID... | --remove-all)\n\n'\ '\tSelect the devices to use for Scalable Persistent Memory '\ 'backup storage.\n\n\texample: setbackupdevices --device=1@1 '\ '--device=1@2', \ summary='Set backup storage devices.', \ aliases=['spmem-setdrives', 'spmsetd', 'setbackupdrives'], \ optparser=OptionParser()) self.definearguments(self.parser) self._rdmc = rdmcObj self._helpers = Helpers() self._restHelpers = RestHelpers(self._rdmc) self._validator = LogicalNvdimmValidator() self._chif_lib = self._helpers.gethprestchifhandle() def common_setup(self): """ function to get the config setup """ scalable_pmem_config = ScalablePersistentMemoryConfig(self._restHelpers, \ self._validator, self._chif_lib) scalable_pmem_config.refresh() # pre-validation self._helpers.validateAllConfigurationPolicies(scalable_pmem_config) return scalable_pmem_config def removeAllDrives(self): """ setlogicalnvdimmdrives command worker function """ scalable_pmem_config = self.common_setup() if scalable_pmem_config.hasConfiguredRegions: raise NoChangesFoundOrMadeError(u"Backup drives cannot be removed "\ "while logical NVDIMMs are configured") self._restHelpers.setDrives( old_drives=scalable_pmem_config.drives.selectedDrives) #self._restHelpers.enableConfiguration() scalable_pmem_config.refresh() self._helpers.displayDrivesConfiguration(scalable_pmem_config) return ReturnCodes.SUCCESS def setDrives(self, options=None): """ Main setlogicalnvdimmdrives command worker function :param options: command options :type options: options. """ drivesToUse = [] if not options.driveId: raise InvalidCommandLineError(u"No device IDs specified") if len(options.driveId) > len(set(options.driveId)): raise InvalidCommandLineError(u"Duplicate device IDs specified") scalable_pmem_config = self.common_setup() for userProvidedId in options.driveId: matchingDrive = scalable_pmem_config.drives.findDrive( userProvidedId) if not matchingDrive: raise InvalidCommandLineError( u"Invalid device ID: {}".format(userProvidedId)) drivesToUse.append(matchingDrive) if scalable_pmem_config.hasConfiguredRegions: # allow drives to be added but not removed if not set(scalable_pmem_config.drives.selectedDrives).issubset( drivesToUse): raise NoChangesFoundOrMadeError(u"Backup devices cannot be "\ "removed while logical NVDIMMs are configured") # check the configuration policies (isValidDrivePolicies, drivePoliciesMessage) = self._validator.\ checkLogicalNvdimmDrivePolicies(scalable_pmem_config.config_resource,\ drivesToUse) if not isValidDrivePolicies: sys.stdout.write( u"\nThe set of devices specified is not a valid configuration:\n" ) sys.stdout.write(drivePoliciesMessage) sys.stdout.write(u"\n\n") raise NoChangesFoundOrMadeError(u"Unable to continue") # calculate maximum persistent memory supported maxPmem = self._validator.calculateMaxPmemGiB(self._chif_lib, scalable_pmem_config.\ config_resource, drivesToUse) # compare this to the TOTAL of the pmem regions in the current/pending settings totalPmemAllocated = scalable_pmem_config.regions.totalSizeGiB if totalPmemAllocated != 0 and maxPmem < totalPmemAllocated: sys.stdout.write( u"\nThe set of devices specified is not a valid configuration:\n" ) sys.stdout.write( u"\nScalable Persistent Memory supported by requested configuration: {} GiB" \ u"\nAllocated Scalable Persistent Memory: {} GiB.".\ format(maxPmem, totalPmemAllocated)) sys.stdout.write(u"\n\n") raise NoChangesFoundOrMadeError(u"Unable to continue") # if all is valid, configure the related BIOS setting if self._rdmc.interactive: self._helpers.confirmBeforeConfigCausesDataLoss( scalable_pmem_config) self._restHelpers.setDrives(new_drives=drivesToUse, old_drives=scalable_pmem_config.\ drives.selectedDrives) scalable_pmem_config.refresh() self._helpers.displayDrivesConfiguration(scalable_pmem_config) return ReturnCodes.SUCCESS def run(self, line): """ Wrapper function for setbackupdrives command main function :param line: command line input :type line: string. """ LOGGER.info("Scalable PMEM: {}".format(self.name)) try: (options, _) = self._parse_arglist(line) except: if ("-h" in line) or ("--help" in line): return ReturnCodes.SUCCESS else: raise InvalidCommandLineErrorOPTS("") LOGGER.info("Options: {}".format(options)) if not self._chif_lib: self._helpers.failNoChifLibrary() if options.removeAll and options.driveId: raise InvalidCommandLineError(u"--device and --remove-all may not "\ "be used at the same time") if options.removeAll: return self.removeAllDrives() else: return self.setDrives(options) def definearguments(self, customparser): """ Define arguments for the command :param customparser: command line input :type customparser: parser. """ groupDanger = OptionGroup(customparser, "Dangerous Options", \ "Use of these options will alter the backup storage devices configured\n" \ "for use with Scalable Persistent Memory and could cause data loss. " \ " Back up all\ndata first.") groupDanger.add_option( '--device', '--drive', action="append", dest="driveId", metavar="ID", help="ID of the backup device to set, e.g. '1@1'") groupDanger.add_option( '--remove-all', action="store_true", dest="removeAll", help="Remove all currently-configured backup devices") customparser.add_option_group(groupDanger)
class RemoveLogicalNVDIMMRegionCommand(RdmcCommandBase): """ Main removelogicalnvdimm command class """ def __init__(self, rdmcObj): RdmcCommandBase.__init__(self, \ name='removelogicalnvdimm', \ usage='removelogicalnvdimm (--processor=NUMBER --index=INDEX | '\ '--pair=PAIR)\n\n\tRemove a logical NVDIMM. All data will be lost.\n'\ '\n\texample: removelogicalnvdimm --processor=1 --index=1'\ '\n\texample: removelogicalnvdimm --processors=1,2', \ summary='Remove an existing logical NVDIMM.', \ aliases=['lnvdimm-remove', 'lnr'], \ optparser=OptionParser()) self.definearguments(self.parser) self._rdmc = rdmcObj self._helpers = Helpers() self._restHelpers = RestHelpers(self._rdmc) self._chif_lib = self._helpers.gethprestchifhandle() def removeRegion(self, options): """ Removes the Logical NVDIMM specified :param socketIdx: the socket of the NUMA region, or None for Non-NUMA :type socketIdx: string or int :param regionIdx: the index of the region :type regionIdx: string or int """ validator = LogicalNvdimmValidator() scalable_pmem_config = ScalablePersistentMemoryConfig(self._restHelpers,\ validator, self._chif_lib) scalable_pmem_config.refresh() # pre-validation self._helpers.validateAllConfigurationPolicies(scalable_pmem_config) matchingRegion = None if options.processorPair: matchingPair = next((p for _, p in scalable_pmem_config.regions.\ socketPairs.items() if p.labelString == options.\ processorPair), None) if matchingPair: matchingRegion = matchingPair.nonNumaRegion else: matchingSocket = next((s for _, s in scalable_pmem_config.regions.\ sockets.items() if s.labelString == options.\ processorNumber), None) if matchingSocket: matchingRegion = matchingSocket.numaRegions.get(options.index) if matchingRegion and matchingRegion.isConfigured: if self._rdmc.interactive: if matchingRegion.isActivelyConfigured: self._helpers.confirmBeforeConfigCausesDataLoss(scalable_pmem_config) patchAttributes = { matchingRegion.settingName : 0 } _ = self._restHelpers.patchScalablePmemSettingAttributes(patchAttributes) else: self._helpers.displayRegionConfiguration(scalable_pmem_config) raise InvalidCommandLineError(u"Unable to identify an existing logical NVDIMM") # display the new state scalable_pmem_config.refresh() self._helpers.displayRegionConfiguration(scalable_pmem_config) sys.stdout.write(u"\n") def run(self, line): """ Wrapper function for the Remove logical NVDIMM command :param line: command line input :type line: string. """ LOGGER.info("Scalable PMEM: {}".format(self.name)) try: (options, _) = self._parse_arglist(line) except: if ("-h" in line) or ("--help" in line): return ReturnCodes.SUCCESS else: raise InvalidCommandLineErrorOPTS("") LOGGER.info("Options: {}".format(options)) if not self._chif_lib: self._helpers.failNoChifLibrary() if not options.processorNumber and not options.processorPair: self.parser.print_help() raise InvalidCommandLineError(u"One of --processor or --processors"\ " is required") if options.processorNumber and options.processorPair: self.parser.print_help() raise InvalidCommandLineError(u"--processor and --processors may not"\ " be used at the same time") if options.processorNumber: if options.index is None: self.parser.print_help() raise InvalidCommandLineError(u"--index must be specified with "\ "--processor") self.removeRegion(options) if options.processorPair: if not options.index is None: self.parser.print_help() raise InvalidCommandLineError(u"--index is not a valid option to"\ " use with --processors") self.removeRegion(options) #Return code return ReturnCodes.SUCCESS def definearguments(self, customparser): """ Define the arguments in the remove region function :param customparser: command line input :type customparser: parser. """ groupDanger = OptionGroup(customparser, "Dangerous Options", \ "Use of these options will alter the backup storage devices configured\n" \ "for use with Scalable Persistent Memory and could cause data loss. "\ "Back up all\ndata first.") groupDanger.add_option( '--proc', '--processor', action="store", type="string", default=None, dest="processorNumber", metavar="NUMBER", help="Specify the processor number of the logical NVDIMM to remove (1, 2)." ) groupDanger.add_option( '-i', '--index', type="int", default=None, dest="index", help="Specify the index of the logical NVDIMM to remove (use with --processor).") groupDanger.add_option( '--pair', '--processors', action="store", type="string", default=None, dest="processorPair", metavar="PAIR", help="Specify the pair of processors of the spanned logical NVDIMM to remove (1,2)." ) customparser.add_option_group(groupDanger)