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])
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 ShowLogicalNVDIMMDrivesCommand(RdmcCommandBase): """ Main showbackupdevices command class """ def __init__(self, rdmcObj): RdmcCommandBase.__init__(self, \ name='showbackupdevices', \ usage='showbackupdevices\n\n\tDisplay the devices supported for use '\ 'as Scalable Persistent Memory\n\tbackup storage.\n\n\texample: '\ 'showbackupdevices', \ summary='Display backup storage devices.', \ aliases=['spmem-showdrives', 'spmemsd', 'showscalablepmemdrives'], \ optparser=OptionParser()) self._rdmc = rdmcObj self._helpers = Helpers() self._chif_lib = self._helpers.gethprestchifhandle() 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") def run(self, line): """ Wrapper function for showlogicalnvdimmdrives command main function :param line: command line input :type line: string. """ LOGGER.info("Scalable PMEM: {}".format(self.name)) try: (options, args) = self._parse_arglist(line) except: if ("-h" in line) or ("--help" in line): return ReturnCodes.SUCCESS else: raise InvalidCommandLineErrorOPTS("") if args: raise InvalidCommandLineError("No argument is required.") LOGGER.info("Options: {}".format(options)) if not self._chif_lib: self._helpers.failNoChifLibrary() self.showDriveData() #Return code return ReturnCodes.SUCCESS