def __init__(self, rdmcObj): RdmcCommandBase.__init__(self, \ name='enablescalablepmem', \ usage='enablescalablepmem [OPTIONS]\n\n' \ '\tEnables or disables the Scalable Persistent Memory feature.\n'\ '\n\texample: enablescalablepmem', \ summary='Enable or disable the Scalable Persistent Memory feature.', \ aliases=['spmem-enable', 'spmemen'], \ optparser=OptionParser()) self.definearguments(self.parser) self._rdmc = rdmcObj self._helpers = Helpers() self._restHelpers = RestHelpers(self._rdmc) self._chif_lib = self._helpers.gethprestchifhandle()
def __init__(self, rdmcObj): RdmcCommandBase.__init__(self, \ name='revertscalablepmemconfig', \ usage='revertscalablepmemconfig\n\n'\ '\tDiscards any pending Scalable Persistent Memory configuration '\ 'changes.\n\n\texample: revertscalablepmemconfig', \ summary='Discard pending Scalable Persistent Memory configuration changes.',\ aliases=['spmem-revertcfg', 'spmem-undocfg', 'spmemrc'], \ optparser=OptionParser()) self._rdmc = rdmcObj self._helpers = Helpers() self._restHelpers = RestHelpers(self._rdmc) self._validator = LogicalNvdimmValidator() self._chif_lib = self._helpers.gethprestchifhandle()
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 __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 __init__(self, rdmcObj): RdmcCommandBase.__init__(self,\ name='autoselectbackupdevices', \ usage='autoselectbackupdevices --size=SIZE [--confirm]\n\n'\ '\tAutomatically select the devices for use as Scalable '\ 'Persistent Memory backup storage.\n\n'\ "\tDevices selected for backup storage will be initialized.\n"\ "\tBack up all data first.\n" \ '\n\texample: autoselectbackupdevices --size=1024 --confirm\n', \ summary='Automatically select backup storage devices.', \ aliases=['spmem-autosetd', 'spmemautosetd'],\ 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 __init__(self, rdmcObj): RdmcCommandBase.__init__(self, \ name='replacebackupdevice', \ usage="replacebackupdevice OLD-ID NEW-ID\n"\ "\n\tReplace a Scalable Persistent Memory backup storage device.\n"\ "\tSpecify devices by ID, e.g. '1@1' from the show backup device command.\n"\ "\n\tThis operation initializes all backup storage devices."\ "\n\tData on any existing logical NVDIMMs will be lost. Back up all data first.\n"\ "\n\texample: replacebackupdevice 1@1 2@1", \ summary='Replace a backup storage device.', \ aliases=['spmem-replaced', 'spmreplaced'], \ optparser=OptionParser()) self._rdmc = rdmcObj self._helpers = Helpers() self._rest_helpers = RestHelpers(self._rdmc) self._validator = LogicalNvdimmValidator() self._chif_lib = self._helpers.gethprestchifhandle()
def __init__(self, rdmcObj): RdmcCommandBase.__init__(self,\ name='showscalablepmemconfig', \ usage='showscalablepmemconfig [OPTIONS]\n\n'\ '\tDisplay the Scalable Persistent Memory configuration.\n'\ '\tIf system is configured, reports the estimated time to complete a backup boot.\n\n'\ '\texample: showscalablepmemconfig', \ summary='Display the Scalable Persistent Memory configuration.', \ aliases=['spmem-showcfg', 'spmemsc'], \ optparser=OptionParser()) self.definearguments(self.parser) self._rdmc = rdmcObj self._helpers = Helpers() self._chif_lib = self._helpers.gethprestchifhandle() self._restHelpers = RestHelpers(rdmcObject=self._rdmc) self._options = None
def showDriveData(self): """ Main showlogicalnvdimmdrives command worker function :param options: command options :type options: options. """ helpers = Helpers() restHelpers = RestHelpers(self._rdmc) validator = LogicalNvdimmValidator() scalable_pmem_config = ScalablePersistentMemoryConfig(restHelpers, \ validator, self._chif_lib) scalable_pmem_config.refresh() # pre-validation self._helpers.validateFeatureIsSupported(scalable_pmem_config) helpers.writeHeader2( u"Scalable Persistent Memory Backup Storage Devices") helpers.displayDrivesConfiguration(scalable_pmem_config) sys.stdout.write(u"\n")
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 RevertScalablePmemConfigurationCommand(RdmcCommandBase): """ Main revertscalablepmemconfig command class """ def __init__(self, rdmcObj): RdmcCommandBase.__init__(self, \ name='revertscalablepmemconfig', \ usage='revertscalablepmemconfig\n\n'\ '\tDiscards any pending Scalable Persistent Memory configuration '\ 'changes.\n\n\texample: revertscalablepmemconfig', \ summary='Discard pending Scalable Persistent Memory configuration changes.',\ aliases=['spmem-revertcfg', 'spmem-undocfg', 'spmemrc'], \ optparser=OptionParser()) self._rdmc = rdmcObj self._helpers = Helpers() self._restHelpers = RestHelpers(self._rdmc) self._validator = LogicalNvdimmValidator() self._chif_lib = self._helpers.gethprestchifhandle() def revertPendingChanges(self): """ Reverts any pending changes """ scalable_pmem_config = ScalablePersistentMemoryConfig(self._restHelpers,\ self._validator, self._chif_lib) scalable_pmem_config.refresh() self._restHelpers.revertSettings() scalable_pmem_config.refresh() self._helpers.writeHeader2(u"Logical NVDIMMs") self._helpers.displayRegionConfiguration(scalable_pmem_config) self._helpers.writeHeader2( u"Scalable Persistent Memory Backup Storage Devices") self._helpers.displayDrivesConfiguration(scalable_pmem_config) sys.stdout.write("\n\n") def run(self, line): """ Wrapper function for the revert configuration 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() self.revertPendingChanges() #Return code return ReturnCodes.SUCCESS
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)
class AutoSelectBackupDevicesCommand(RdmcCommandBase): """ Main autoselectbackupdevices command class """ def __init__(self, rdmcObj): RdmcCommandBase.__init__(self,\ name='autoselectbackupdevices', \ usage='autoselectbackupdevices --size=SIZE [--confirm]\n\n'\ '\tAutomatically select the devices for use as Scalable '\ 'Persistent Memory backup storage.\n\n'\ "\tDevices selected for backup storage will be initialized.\n"\ "\tBack up all data first.\n" \ '\n\texample: autoselectbackupdevices --size=1024 --confirm\n', \ summary='Automatically select backup storage devices.', \ aliases=['spmem-autosetd', 'spmemautosetd'],\ 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 autoselectdrives(self, pmem_size_GiB, confirm): """ function to perform the automatic selection of backup drives :param pmem_size_GiB: requested scalable persistent memory size :type pmem_size_GiB: int :param confirm: whether or not to automatically confirm the selected drives :type confirm: Boolean """ scalable_pmem_config = ScalablePersistentMemoryConfig(self._restHelpers,\ self._validator, self._chif_lib) scalable_pmem_config.refresh() # pre-validation self._helpers.validateAllConfigurationPolicies(scalable_pmem_config) # make sure this is an un-configured system if scalable_pmem_config.isConfiguredSystem: raise InvalidCommandLineError(u"This operation is not supported on "\ "a configured system") # get policies policies = resolve_pointer(scalable_pmem_config.config_resource, \ "/Attributes/Policy", None) sameModel = False sameSize = False if policies: sameModel = policies.get("SameModelNVMe", False) sameSize = policies.get("SameSizeNVMe", False) # separate the supported drives into supported groups, based on model or size # if same model or size, then order doesn't matter; else the # drives should be sorted largest to smallest supported_drives_groups = self.sort_drives(sameModel, sameSize, \ scalable_pmem_config.drives.supportedDrives) # loop through the group until a valid config is found or all drives # have been tested isValid = False i = 0 num_groups = len(supported_drives_groups) while not isValid and i < num_groups: drive_group = supported_drives_groups[i] drivesToUse = [] for drive in drive_group: drivesToUse.append(drive) # calculate the maximum supported by the new configuration, # which may be different from the requested capacity max_pmem_supported = self._validator.calculateMaxPmemGiB(\ self._chif_lib, scalable_pmem_config.config_resource, \ drivesToUse) if max_pmem_supported >= pmem_size_GiB: # check drive policies (isValidDrivePolicies, _) = self._validator.\ checkLogicalNvdimmDrivePolicies(scalable_pmem_config.\ config_resource, drivesToUse) if isValidDrivePolicies: isValid = True break i += 1 if not isValid: # TODO: more info? maybe build a list of reasons why certain drives will not work raise InvalidCommandLineError(u"Requested size of {} GiB is not "\ "supported by the installed backup "\ "devices".format(pmem_size_GiB)) # get a list of the drives to show to the user summary_drive_list = ["{:15} ({} GB)".format(d.formattedLocation, \ d.sizeGB) for d in drivesToUse] # Make sure the user confirms the changes sys.stdout.write(u"\nThe following backup devices have been "\ "automatically selected for Scalable PMEM:\n") self._helpers.printLimitedMessageList(summary_drive_list, 99) sys.stdout.write(u"\n") if not confirm: if self._rdmc.interactive: # TODO: timeout s = raw_input( u"\nConfirm changes? Y(y) to confirm. N(n) to cancel: ") if s == 'y' or s == 'Y': confirm = True else: raise NoChangesFoundOrMadeError( u"No changes have been made") else: raise NoChangesFoundOrMadeError(u"No changes have been made. "\ "To confirm the changes, specify --confirm") if confirm: # if all is valid, configure the related BIOS setting self._restHelpers.setDrives(new_drives=drivesToUse) #self._restHelpers.enableConfiguration() scalable_pmem_config.refresh() self._helpers.displayDrivesConfiguration(scalable_pmem_config) def sort_drives(self, sameModel, sameSize, supported_drives): """ sort drives into separate groups based on model or size. if same model or size, then order doesn't matter else the drives are sorted largest to smallest size :param sameModel: specifies if drives need to be the same model :type sameModel: Boolean :param sameSize: specifies is drives need to be the same size, model takes precedence :type sameSize: Boolean :param supported_drives: list of all supported drives :type supported_drives: list of Drives :returns: 2D list of supported drives, where a row is a group of """\ """drives based on model or size :rtype: 2D list of Drive """ supported_drives_groups = [] # 2D Array, row=model or size if sameModel: # separate drives by model # for each model, build a list of drives models = set([drive.model for drive in supported_drives]) for model_to_find in models: drive_model_group = [drive for drive in supported_drives if \ drive.model == model_to_find] supported_drives_groups.append(drive_model_group) elif sameSize: # separate drives by size sizes = set([drive.sizeMB for drive in supported_drives]) for size_to_find in sizes: drive_size_group = [drive for drive in supported_drives if \ drive.sizeMB == size_to_find] supported_drives_groups.append(drive_size_group) else: # contains one list of all supported drives, regardless of size or model # sort by the size, descending from largest to smallest sorted_supported_drives = sorted(supported_drives, key=lambda d: d.sizeMB,\ reverse=True) supported_drives_groups.append(sorted_supported_drives) return supported_drives_groups def run(self, line): """ Wrapper function for new 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 options.size <= 0: self.parser.print_help() raise InvalidCommandLineError("Invalid value for --size") self.autoselectdrives(options.size, options.confirm) #Return code return ReturnCodes.SUCCESS def definearguments(self, customparser): """ Wrapper function for new command main function :param customparser: command line input :type customparser: parser. """ customparser.add_option( '--size', '-s', dest='size', default=-1, action="store", help="Amount (in GiB) of Scalable Persistent Memory to be supported"\ " by the new backup storage device configuration.", type="int" ) groupDanger = OptionGroup(customparser, "Dangerous Options", \ "Use of these options will alter the Scalable Persistent Memory " \ "configuration\nand will cause data loss. Back up all data first.") groupDanger.add_option( '--confirm', action="store_true", default=False, dest="confirm", help="Confirm the configuration of the automatically selected backup"\ " devices. If not specified, no changes will occur." ) customparser.add_option_group(groupDanger)
class EnableScalablePmemCommand(RdmcCommandBase): """ Enable Scalable Pmem command """ def __init__(self, rdmcObj): RdmcCommandBase.__init__(self, \ name='enablescalablepmem', \ usage='enablescalablepmem [OPTIONS]\n\n' \ '\tEnables or disables the Scalable Persistent Memory feature.\n'\ '\n\texample: enablescalablepmem', \ summary='Enable or disable the Scalable Persistent Memory feature.', \ aliases=['spmem-enable', 'spmemen'], \ optparser=OptionParser()) self.definearguments(self.parser) self._rdmc = rdmcObj self._helpers = Helpers() self._restHelpers = RestHelpers(self._rdmc) self._chif_lib = self._helpers.gethprestchifhandle() def enableOrDisableFeature(self, enable): """ Enables or disables the feature :param enable: a flag whether to enable or disable the feature :type enable: boolean """ validator = LogicalNvdimmValidator() scalable_pmem_config = ScalablePersistentMemoryConfig(self._restHelpers,\ validator, self._chif_lib) scalable_pmem_config.refresh() # pre-validation self._helpers.validateFeatureIsSupported(scalable_pmem_config) self._helpers.validateFunctionalityIsEnabled(scalable_pmem_config) if enable is False: # If user disables Scalable PMEM, revert any pending changes to # prevent data or configuration loss if self._rdmc.interactive: message = u"Warning: disabling Scalable Persistent Memory will "\ "revert any pending configuration changes.\n" self._helpers.confirmChanges(message=message) self._restHelpers.revertSettings() patchAttributes = { "FeatureEnabled" : enable } _ = self._restHelpers.patchScalablePmemSettingAttributes(patchAttributes) sys.stdout.write(u"\nThe Scalable Persistent Memory feature has been "\ "set to: {}\n".format("Enabled" if enable else "Disabled")) self._helpers.noticeRestartRequired(scalable_pmem_config) sys.stdout.write("\n\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("") if len(args): InvalidCommandLineError("This command takes no parameters.") LOGGER.info("Options: {}".format(options)) if not self._chif_lib: self._helpers.failNoChifLibrary() enable = True if options.enableFeature is False: enable = False self.enableOrDisableFeature(enable) #Return code return ReturnCodes.SUCCESS def definearguments(self, customparser): """ Define arguments for the command :param customparser: command line input :type customparser: parser. """ customparser.add_option( '--disable', action="store_false", dest="enableFeature", help="Disable the Scalable Persistent Memory feature. Warning: "\ "any pending configuration changes will be lost." )
class ReplaceBackupDeviceCommand(RdmcCommandBase): """ Main replacebackupdevice command class """ def __init__(self, rdmcObj): RdmcCommandBase.__init__(self, \ name='replacebackupdevice', \ usage="replacebackupdevice OLD-ID NEW-ID\n"\ "\n\tReplace a Scalable Persistent Memory backup storage device.\n"\ "\tSpecify devices by ID, e.g. '1@1' from the show backup device command.\n"\ "\n\tThis operation initializes all backup storage devices."\ "\n\tData on any existing logical NVDIMMs will be lost. Back up all data first.\n"\ "\n\texample: replacebackupdevice 1@1 2@1", \ summary='Replace a backup storage device.', \ aliases=['spmem-replaced', 'spmreplaced'], \ optparser=OptionParser()) self._rdmc = rdmcObj self._helpers = Helpers() self._rest_helpers = RestHelpers(self._rdmc) self._validator = LogicalNvdimmValidator() self._chif_lib = self._helpers.gethprestchifhandle() def run(self, line): """ Runs the command. :param line: command line input :type line: string """ try: (_, args) = self._parse_arglist(line) except: if ("-h" in line) or ("--help" in line): return ReturnCodes.SUCCESS else: raise InvalidCommandLineErrorOPTS("") if not args or len(args) != 2: self.print_help() sys.stdout.write("\n") raise InvalidCommandLineError(u"OLD-ID and NEW-ID must be specified") if len(args) != len(set(args)): raise InvalidCommandLineError(u"Duplicate device IDs specified") if not self._chif_lib: self._helpers.failNoChifLibrary() scalable_pmem_config = ScalablePersistentMemoryConfig(self._rest_helpers,\ self._validator, self._chif_lib) scalable_pmem_config.refresh() # pre-validation self._helpers.validateFeatureIsSupported(scalable_pmem_config) self._helpers.validateFeatureEnabledByUser(scalable_pmem_config) try: old_drive, new_drive = scalable_pmem_config.drives.findDrives(args) except ValueError as excp: raise InvalidCommandLineError(u"Invalid device ID: {}".format(excp)) self.replace_drive(scalable_pmem_config, old_drive, new_drive) scalable_pmem_config.refresh() self._helpers.displayDrivesConfiguration(scalable_pmem_config) return ReturnCodes.SUCCESS def replace_drive(self, scalable_pmem_config, old_drive, new_drive): """ Replaces a backup storage drive. :param scalable_pmem_config: the Scalable Persistent Memory configuration :param old_drive: the drive to be replaced :param new_drive: the replacement drive """ backup_drives = scalable_pmem_config.drives.selectedDrives if old_drive not in backup_drives: raise NoChangesFoundOrMadeError(u"Device {} is not configured "\ "for backup storage".format(old_drive.generatedId)) if new_drive in backup_drives: raise NoChangesFoundOrMadeError(u"Device {} is already configured " \ "for backup storage".format(new_drive.generatedId)) backup_drives.remove(old_drive) backup_drives.append(new_drive) config_data = scalable_pmem_config.config_resource # new backup storage drives must adhere to the drive policy requirements is_valid, error_msg = self._validator.checkLogicalNvdimmDrivePolicies(\ config_data, backup_drives) if not is_valid: raise NoChangesFoundOrMadeError(error_msg) # new backup storage drives must support the current logical NVDIMM configuration max_pmem = self._validator.calculateMaxPmemGiB(self._chif_lib, \ config_data, backup_drives) allocated_pmem = scalable_pmem_config.regions.totalSizeGiB if allocated_pmem > max_pmem: raise NoChangesFoundOrMadeError(u"The new backup storage devices must support " u"the current logical NVDIMM configuration.") if old_drive.currentMode == Drive.MODE_NVDIMM and scalable_pmem_config.\ hasActiveConfiguredRegions: # actual drive replacement occurring with data at risk if self._rdmc.interactive: sys.stdout.write(u"\nAll backup storage devices will be initialized upon restart." u"\nData on any existing logical NVDIMMs will be lost.\n") uinput = raw_input(u"\nConfirm changes [y/N]? ") if uinput.lower() != 'y': raise NoChangesFoundOrMadeError(u"No changes have been made") self._rest_helpers.setDrives(new_drives=[new_drive], old_drives=[old_drive])