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