Blame SOURCES/0008-save_to_file-support-saveconfig-at-storage-object-le.patch

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