[node-patches] Change in ovirt-node[master]: [WIP] utils_fs: Add symlink support
asegurap at redhat.com
asegurap at redhat.com
Fri Jun 20 23:04:23 UTC 2014
Antoni Segura Puimedon has uploaded a new change for review.
Change subject: [WIP] utils_fs: Add symlink support
......................................................................
[WIP] utils_fs: Add symlink support
Change-Id: Ibcc52e9e5cd99bb7f342bb024d1aae12831ddc60
Signed-off-by: Antoni S. Puimedon <asegurap at redhat.com>
---
M src/ovirt/node/utils/fs/__init__.py
1 file changed, 110 insertions(+), 6 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/ovirt-node refs/changes/13/29013/1
diff --git a/src/ovirt/node/utils/fs/__init__.py b/src/ovirt/node/utils/fs/__init__.py
index a02ad08..b3e7539 100644
--- a/src/ovirt/node/utils/fs/__init__.py
+++ b/src/ovirt/node/utils/fs/__init__.py
@@ -22,12 +22,15 @@
"""
Some convenience functions realted to the filesystem
"""
+from __future__ import print_function
import shutil
+import errno
import os
import re
import StringIO
+from . import mount
from .. import process, parse_varfile
from ... import base, log
@@ -382,17 +385,118 @@
class Config(base.Base):
"""oVirt Node specififc way to persist files
"""
- basedir = "/config"
+ basedir = '/config'
+ path_entries = '/config/files'
def _config_path(self, fn=""):
return os.path.join(self.basedir, fn.strip("/"))
- def persist(self, filename):
- """Persist a file and bind mount it
+ def persist(self, path):
+ """Persist path and bind mount it back to its current location
"""
- if filename and self.is_enabled():
- from ovirtnode import ovirtfunctions
- return ovirtfunctions.ovirt_store_config(filename)
+ # TODO: Abort if it is stateless
+ 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
+ if os.path.islink(abspath):
+ self._persist_symlink(abspath)
+ elif os.path.isdir(abspath):
+ self._persist_dir(abspath)
+ elif os.path.isfile(abspath):
+ self._persist_file(abspath)
+
+ def _persist_dir(self, abspath):
+ """Persist directory and bind mount it back to its current location
+ """
+ persisted_path = os.path.join(self.basedir, abspath)
+ if os.path.exists(persisted_path):
+ logger.warn('Directory "%s" had already been persisted' % abspath)
+ return
+
+ shutil.copytree(abspath, persisted_path, symlinks=True)
+ mount.mount(persisted_path, abspath, flags=mount.MS_BIND)
+ logger.info('Directory "%s" successfully persisted' % abspath)
+ self._add_path_entry(abspath)
+
+ def _persist_file(self, abspath):
+ """Persist file and bind mount it back to its current location
+ """
+ from ovirtnode import ovirtfunctions
+ persisted_path = os.path.join(self.basedir, abspath)
+ if os.path.exists(persisted_path):
+ current_checksum = ovirtfunctions.cksum(abspath)
+ stored_checksum = ovirtfunctions.cksum(persisted_path)
+ if stored_checksum == current_checksum:
+ logger.warn('File "%s" had already been persisted' % abspath)
+ return
+ else: # Refresh
+ try:
+ mount.umount(abspath)
+ os.unlink(persisted_path)
+ except OSError as ose:
+ logger.error('Failed to refresh persisted file "%s": %s' %
+ (abspath, ose.message))
+ self._prepare_dir(persisted_path)
+ shutil.copy2(abspath, persisted_path)
+ mount.mount(persisted_path, abspath, flags=mount.MS_BIND)
+ logger.info('File "%s" successfully persisted' % abspath)
+ self._add_path_entry(abspath)
+
+ def _persist_symlink(self, abspath):
+ """Persist symbolic link and bind mount it back to its current location
+ """
+ persisted_path = os.path.join(self.basedir, abspath)
+ current_target = os.readlink(abspath)
+ if os.path.exists(persisted_path):
+ stored_target = os.readlink(persisted_path)
+ if stored_target == current_target:
+ logger.warn('Symlink "%s" had already been persisted' %
+ abspath)
+ return
+ else:
+ # Write the new symlink to an alternate location and atomically
+ # rename
+ self._prepare_dir(persisted_path)
+ tmp_path = persisted_path + '.ovirtnode.atom'
+ try:
+ os.symlink(current_target, tmp_path)
+ except Exception:
+ raise
+ else:
+ os.rename(tmp_path, persisted_path)
+ else:
+ self._prepare_dir(persisted_path)
+ os.symlink(current_target, persisted_path)
+
+ logger.info('Symbolic link "%s" successfully persisted' % abspath)
+ self._add_path_entry(abspath)
+
+ def _prepare_dir(self, abspath, persisted_path):
+ dir_path = os.path.dirname(persisted_path)
+ try:
+ os.makedirs(dir_path)
+ except OSError as ose:
+ if OSError.errno != errno.EEXIST:
+ logger.error('Failed to create the directories necessary to '
+ 'persist %s: %s' % (abspath, ose))
+ raise
+
+ def _persisted_path_entries(self):
+ with open(self.path_entries) as path_entries:
+ for entry in path_entries:
+ yield entry
+
+ def _add_path_entry(self, abspath):
+ matches = (entry for entry in self._persisted_path_entries if
+ entry == abspath)
+ if any(matches):
+ pass # Entry already present
+ else:
+ with open(self.path_entries, 'a') as path_entries:
+ print(abspath, file=path_entries)
def unpersist(self, filename):
"""Remove the persistent version of a file and remove the bind mount
--
To view, visit http://gerrit.ovirt.org/29013
To unsubscribe, visit http://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ibcc52e9e5cd99bb7f342bb024d1aae12831ddc60
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