From 7cc8531b03f5391f8c2fa1208c4f6b6e7b030b66 Mon Sep 17 00:00:00 2001
From: Maurizio Lombardi <mlombard@redhat.com>
Date: Tue, 10 Apr 2018 15:18:37 +0200
Subject: [PATCH] save_to_file: support saveconfig at storage object level
Added an option to update configuration for single storage object at a time.
As of today changes done for one storage object needs the whole configuration
update. This option will enable us to save changes done to a give storage object.
$ 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 <prasanna.kalever@redhat.com>
Signed-off-by: Maurizio Lombardi <mlombard@redhat.com>
---
rtslib/root.py | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 84 insertions(+), 2 deletions(-)
diff --git a/rtslib/root.py b/rtslib/root.py
index 99a25b7..c6697cf 100644
--- a/rtslib/root.py
+++ b/rtslib/root.py
@@ -148,6 +148,83 @@ class RTSRoot(CFSNode):
def __str__(self):
return "rtslib"
+ def _get_saveconf(self, so_path, save_file):
+ '''
+ Fetch the configuration of all the blocks and return conf with
+ updated storageObject info and its related target configuraion of
+ given storage object path
+ '''
+ current = self.dump()
+
+ with open(save_file, "r") as f:
+ saveconf = json.loads(f.read())
+ f.close()
+
+ fetch_cur_so = False
+ fetch_cur_tg = False
+ # Get the given block current storageObj configuration
+ for sidx, sobj in enumerate(current.get('storage_objects', [])):
+ if '/backstores/' + sobj['plugin'] + '/' + sobj['name'] == so_path:
+ current_so = current['storage_objects'][sidx]
+ fetch_cur_so = True
+ break
+
+ # Get the given block current target configuration
+ if fetch_cur_so:
+ for tidx, tobj in enumerate(current.get('targets', [])):
+ if fetch_cur_tg:
+ break
+ for luns in tobj.get('tpgs', []):
+ if fetch_cur_tg:
+ break
+ for lun in luns.get('luns', []):
+ if lun['storage_object'] == so_path:
+ current_tg = current['targets'][tidx]
+ fetch_cur_tg = True
+ break
+
+ fetch_sav_so = False
+ fetch_sav_tg = False
+ # Get the given block storageObj from saved configuration
+ for sidx, sobj in enumerate(saveconf.get('storage_objects', [])):
+ if '/backstores/' + sobj['plugin'] + '/' + sobj['name'] == so_path:
+ # Merge StorageObj
+ if fetch_cur_so:
+ saveconf['storage_objects'][sidx] = current_so;
+ # Remove StorageObj
+ else:
+ saveconf['storage_objects'].remove(saveconf['storage_objects'][sidx])
+ fetch_sav_so = True
+ break
+
+ # Get the given block target from saved configuration
+ if fetch_sav_so:
+ for tidx, tobj in enumerate(saveconf.get('targets', [])):
+ if fetch_sav_tg:
+ break
+ for luns in tobj.get('tpgs', []):
+ if fetch_sav_tg:
+ break
+ for lun in luns.get('luns', []):
+ if lun['storage_object'] == so_path:
+ # Merge target
+ if fetch_cur_tg:
+ saveconf['targets'][tidx] = current_tg;
+ # Remove target
+ else:
+ saveconf['targets'].remove(saveconf['targets'][tidx])
+ fetch_sav_tg = True
+ break
+
+ # Insert storageObj
+ if fetch_cur_so and not fetch_sav_so:
+ saveconf['storage_objects'].append(current_so)
+ # Insert target
+ if fetch_cur_tg and not fetch_sav_tg:
+ saveconf['targets'].append(current_tg)
+
+ return saveconf
+
# RTSRoot public stuff
def dump(self):
@@ -257,7 +334,7 @@ class RTSRoot(CFSNode):
return errors
- def save_to_file(self, save_file=None):
+ def save_to_file(self, save_file=None, so_path=None):
'''
Write the configuration in json format to a file.
Save file defaults to '/etc/targets/saveconfig.json'.
@@ -265,9 +342,14 @@ class RTSRoot(CFSNode):
if not save_file:
save_file = default_save_file
+ if so_path:
+ saveconf = self._get_saveconf(so_path, save_file)
+ else:
+ saveconf = self.dump()
+
with open(save_file+".temp", "w+") as f:
os.fchmod(f.fileno(), stat.S_IRUSR | stat.S_IWUSR)
- f.write(json.dumps(self.dump(), sort_keys=True, indent=2))
+ f.write(json.dumps(saveconf, sort_keys=True, indent=2))
f.write("\n")
f.flush()
os.fsync(f.fileno())
--
1.8.3.1