[node-patches] Change in ovirt-node[master]: utils_fs: make unpersist support symlinks

asegurap at redhat.com asegurap at redhat.com
Mon Jun 23 14:52:41 UTC 2014


Antoni Segura Puimedon has uploaded a new change for review.

Change subject: utils_fs: make unpersist support symlinks
......................................................................

utils_fs: make unpersist support symlinks

Substitute the usage of src/ovirtnode/ovirtfunctions remove_config
in the src/ovirt/node package with its own implementation that is
able to deal with symlinks.

Change-Id: I719304b37a17dfc47427fe1c0bb9a4e14cb88a9b
Signed-off-by: Antoni S. Puimedon <asegurap at redhat.com>
---
M scripts/unpersist
M src/ovirt/node/utils/fs/__init__.py
2 files changed, 86 insertions(+), 19 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/ovirt-node refs/changes/75/29075/1

diff --git a/scripts/unpersist b/scripts/unpersist
index 62ed87d..047000a 100755
--- a/scripts/unpersist
+++ b/scripts/unpersist
@@ -1,7 +1,7 @@
-#!/bin/bash
+#!/usr/bin/env python2
 #
-# Copyright (C) 2009, Red Hat, Inc.
-# Written by Darryl L. Pierce <dpierce at redhat.com>
+# Copyright (C) 2014, Red Hat, Inc.
+# Written by Antoni Segura Puimedon <asegurap at redhat.com>
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -18,20 +18,24 @@
 # MA  02110-1301, USA.  A copy of the GNU General Public License is
 # also available at http://www.gnu.org/copyleft/gpl.html.
 #
-# Convenience wrapper to give access to the ovirt_store_config
-# function in /usr/libexec/ovirt-functions
+# Convenience wrapper to give access to ovirt/node/utils/fs persistence
+# facilities
+import argparse
+import sys
 
-. /usr/libexec/ovirt-functions
+from ovirt.node.utils import fs
 
-ME=$(basename "$0")
-warn() { printf '%s: %s\n' "$ME" "$*" >&2; }
-help() { printf "Usage: $ME FILE ...\n
-Unpersists a previous persisted file, removing it from /config.
-The file is restored to its original location.\n\n" >&2; exit 1;
-}
-die() { warn "$*"; help; exit 1; }
 
-if [ $# -eq 0 ]; then die "You need to specify at least one file."; fi
+def unpersist():
+    parser = argparse.ArgumentParser(
+        description="Unpersists a previously persisted path, removing it from "
+        "/config. The persisted path is restored to its original location.")
+    parser.add_argument('PATH', nargs='+')
+    arguments = parser.parse_args(sys.argv[1:])
 
-remove_config $*
+    conf = fs.Config()
+    for path in arguments.PATH:
+        conf.unpersist(path)
 
+if __name__ == '__main__':
+    sys.exit(unpersist())
diff --git a/src/ovirt/node/utils/fs/__init__.py b/src/ovirt/node/utils/fs/__init__.py
index b30278f..5deb791 100644
--- a/src/ovirt/node/utils/fs/__init__.py
+++ b/src/ovirt/node/utils/fs/__init__.py
@@ -516,12 +516,75 @@
             with open(self.path_entries, 'a') as path_entries:
                 print(abspath, file=path_entries)
 
-    def unpersist(self, filename):
+    def _del_path_entry(self, abspath):
+        """Removes a path entry from the /config/files entries
+        """
+        matches = [entry for entry in self._persisted_path_entries if
+                   entry != abspath]
+        with open(self.path_entries, 'w') as path_entries:
+            print('\n'.join(matches), file=path_entries)
+
+    def unpersist(self, path):
         """Remove the persistent version of a file and remove the bind mount
         """
-        if filename and self.is_enabled():
-            from ovirtnode import ovirtfunctions
-            return ovirtfunctions.remove_config(filename)
+        if not self.is_enabled():
+            return
+        abspath = os.path.abspath(path)
+        if os.path.exists(abspath):
+            # Check first for symlinks as os.path file type detection follows
+            # links and will give the type of the target
+            try:
+                if os.path.islink(abspath):
+                    self._unpersist_symlink(abspath)
+                elif os.path.isdir(abspath):
+                    self._unpersist_dir(abspath)
+                elif os.path.isfile(abspath):
+                    self._unpersist_file(abspath)
+            except Exception:
+                self._logger.error('Failed to unpersist "%s"' % path,
+                                   exc_info=True)
+                return -1
+
+    def _unpersist_dir(self, abspath):
+        """Remove the persistent version of a directory and refresh the version
+        in the live filesystem with what was persisted"""
+        persisted_path = os.path.join(self.basedir, abspath)
+        if not os.path.ismount(persisted_path):
+            self._loggeiwarn('The directory "%s" is not a persisted element')
+            return
+        mount.umount(abspath)
+        shutil.copytree(persisted_path, abspath, symlinks=True)
+        shutil.rmtree(persisted_path)
+        os.remove_entry(abspath)
+        self._logger.info('Successfully unpersisted directory "%s"' % abspath)
+
+    def _unpersist_file(self, abspath):
+        """Remove the persistent version of a file and refresh the version in
+        the live filesystem with what was persisted"""
+        persisted_path = os.path.join(self.basedir, abspath)
+        if not os.path.ismount(persisted_path):
+            self._loggeiwarn('The file "%s" is not a persisted element')
+            return
+        mount.umount(abspath)
+        shutil.copy2(persisted_path, abspath)
+        os.unlink(persisted_path)
+
+    def _unpersist_symlink(self, abspath):
+        """Remove the persistent version of a symlink. Symlinks are not bind
+        mounted so that won't be necessary"""
+        persisted_path = os.path.join(self.basedir, abspath)
+        try:
+            stored_target = os.readlink(persisted_path)
+        except OSError as ose:
+            if ose.errno == errno.ENOENT:
+                self._loggeiwarn('The symlink "%s" is not a persisted element')
+                return
+
+        # Update the link with the current persisted version
+        os.symlink(stored_target, abspath)
+        os.unlink(persisted_path)
+        os.remove_entry(abspath)
+        self._logger.info('Successfully unpersisted symlink "%s"' % abspath)
 
     def delete(self, filename):
         """Remove the persiste version and the file


-- 
To view, visit http://gerrit.ovirt.org/29075
To unsubscribe, visit http://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I719304b37a17dfc47427fe1c0bb9a4e14cb88a9b
Gerrit-PatchSet: 1
Gerrit-Project: ovirt-node
Gerrit-Branch: master
Gerrit-Owner: Antoni Segura Puimedon <asegurap at redhat.com>



More information about the node-patches mailing list