From 9dc85912f6ff2ba77fa8b136478ae3d2776c2b5e Mon Sep 17 00:00:00 2001 From: Prasanna Kumar Kalever Date: Sat, 24 Feb 2018 08:38:35 +0530 Subject: [PATCH] config: add saveconfig command to StorageObject level $ targetcli /backstores/user:glfs/block1 help [...] AVAILABLE COMMANDS [...] - saveconfig [savefile] - set [group] [parameter=value...] - status - version $ targetcli /backstores/user:glfs/block1 saveconfig Storage Object 'user:block1' config saved to /etc/target/saveconfig.json Signed-off-by: Prasanna Kumar Kalever --- targetcli/ui_backstore.py | 22 ++++++++++ targetcli/ui_root.py | 110 ++++++++++++++++++++++++++-------------------- 2 files changed, 85 insertions(+), 47 deletions(-) diff --git a/targetcli/ui_backstore.py b/targetcli/ui_backstore.py index 5af448f..efa532f 100644 --- a/targetcli/ui_backstore.py +++ b/targetcli/ui_backstore.py @@ -36,6 +36,8 @@ from rtslib_fb.utils import get_block_type from .ui_node import UINode, UIRTSLibNode +default_save_file = "/etc/target/saveconfig.json" + alua_rw_params = ['alua_access_state', 'alua_access_status', 'alua_write_metadata', 'alua_access_type', 'preferred', 'nonop_delay_msecs', 'trans_delay_msecs', @@ -702,6 +704,26 @@ class UIStorageObject(UIRTSLibNode): self.shell.con.display("Backstore plugin %s %s" % (self.rtsnode.plugin, self.rtsnode.version)) + def ui_command_saveconfig(self, savefile=None): + ''' + Save configuration of this StorageObject. + ''' + so = self.rtsnode + rn = self.get_root() + + if not savefile: + savefile = default_save_file + + savefile = os.path.expanduser(savefile) + + rn._save_backups(savefile) + + rn.rtsroot.save_to_file(savefile, + '/backstores/' + so.plugin + '/' + so.name) + + self.shell.log.info("Storage Object '%s:%s' config saved to %s." + % (so.plugin, so.name, savefile)) + class UIPSCSIStorageObject(UIStorageObject): def summary(self): diff --git a/targetcli/ui_root.py b/targetcli/ui_root.py index 54d38e3..09f3f1b 100644 --- a/targetcli/ui_root.py +++ b/targetcli/ui_root.py @@ -62,6 +62,65 @@ class UIRoot(UINode): if fm.wwns == None or any(fm.wwns): UIFabricModule(fm, self) + def _save_backups(self, savefile): + ''' + Take backup of config-file if needed. + ''' + # Only save backups if saving to default location + if savefile != default_save_file: + return + + backup_dir = os.path.dirname(savefile) + "/backup/" + backup_name = "saveconfig-" + \ + datetime.now().strftime("%Y%m%d-%H:%M:%S") + ".json" + backupfile = backup_dir + backup_name + backup_error = None + + if not os.path.exists(backup_dir): + try: + os.makedirs(backup_dir); + except OSError as exe: + raise ExecutionError("Cannot create backup directory [%s] %s." + % (backup_dir, exc.strerror)) + + # Only save backups if savefile exits + if not os.path.exists(savefile): + return + + backed_files_list = sorted(glob(os.path.dirname(savefile) + \ + "/backup/*.json")) + + # Save backup if backup dir is empty, or savefile is differnt from recent backup copy + if not backed_files_list or not filecmp.cmp(backed_files_list[-1], savefile): + try: + shutil.copy(savefile, backupfile) + + except IOError as ioe: + backup_error = ioe.strerror or "Unknown error" + + if backup_error == None: + # remove excess backups + max_backup_files = int(self.shell.prefs['max_backup_files']) + + try: + with open(universal_prefs_file) as prefs: + backups = [line for line in prefs.read().splitlines() if re.match('^max_backup_files\s*=', line)] + if max_backup_files < int(backups[0].split('=')[1].strip()): + max_backup_files = int(backups[0].split('=')[1].strip()) + except: + self.shell.log.debug("No universal prefs file '%s'." % universal_prefs_file) + + files_to_unlink = list(reversed(backed_files_list))[max_backup_files:] + for f in files_to_unlink: + with ignored(IOError): + os.unlink(f) + + self.shell.log.info("Last %d configs saved in %s." + % (max_backup_files, backup_dir)) + else: + self.shell.log.warning("Could not create backup file %s: %s." + % (backupfile, backup_error)) + def ui_command_saveconfig(self, savefile=default_save_file): ''' Saves the current configuration to a file so that it can be restored @@ -69,55 +128,12 @@ class UIRoot(UINode): ''' self.assert_root() + if not savefile: + savefile = default_save_file + savefile = os.path.expanduser(savefile) - # Only save backups if saving to default location - if savefile == default_save_file: - backup_dir = os.path.dirname(savefile) + "/backup" - backup_name = "saveconfig-" + \ - datetime.now().strftime("%Y%m%d-%H:%M:%S") + ".json" - backupfile = backup_dir + "/" + backup_name - backup_error = None - - if not os.path.exists(backup_dir): - try: - os.makedirs(backup_dir); - except OSError as exe: - raise ExecutionError("Cannot create backup directory [%s] %s." % (backup_dir, exc.strerror)) - - # Only save backups if savefile exits - if os.path.exists(savefile): - backed_files_list = sorted(glob(os.path.dirname(savefile) + "/backup/*.json")) - # Save backup if 1. backup dir is empty, or 2. savefile is differnt from recent backup copy - if not backed_files_list or not filecmp.cmp(backed_files_list[-1], savefile): - try: - shutil.copy(savefile, backupfile) - - except IOError as ioe: - backup_error = ioe.strerror or "Unknown error" - - if backup_error == None: - # Kill excess backups - max_backup_files = int(self.shell.default_prefs['max_backup_files']) - - try: - with open(universal_prefs_file) as prefs: - backups = [line for line in prefs.read().splitlines() if re.match('^max_backup_files\s*=', line)] - if max_backup_files < int(backups[0].split('=')[1].strip()): - max_backup_files = int(backups[0].split('=')[1].strip()) - except: - self.shell.log.debug("No universal prefs file '%s'." % universal_prefs_file) - - files_to_unlink = list(reversed(backed_files_list))[max_backup_files:] - for f in files_to_unlink: - with ignored(IOError): - os.unlink(f) - - self.shell.log.info("Last %d configs saved in %s." % \ - (max_backup_files, backup_dir)) - else: - self.shell.log.warning("Could not create backup file %s: %s." % \ - (backupfile, backup_error)) + self._save_backups(savefile) self.rtsroot.save_to_file(savefile) -- 1.8.3.1