# contact: eduardo.sousa@canonical.com
##
+import errno
+from http import HTTPStatus
from io import BytesIO, StringIO
-from pymongo import MongoClient
-from gridfs import GridFSBucket, errors
import logging
-from http import HTTPStatus
import os
+
+from gridfs import GridFSBucket, errors
from osm_common.fsbase import FsBase, FsException
+from pymongo import MongoClient
+
__author__ = "Eduardo Sousa <eduardo.sousa@canonical.com>"
self.client = None
self.fs = None
- def __update_local_fs(self):
+ def __update_local_fs(self, from_path=None):
dir_cursor = self.fs.find({"metadata.type": "dir"}, no_cursor_timeout=True)
for directory in dir_cursor:
+ if from_path and not directory.filename.startswith(from_path):
+ continue
os.makedirs(self.path + directory.filename, exist_ok=True)
file_cursor = self.fs.find({"metadata.type": {"$in": ["file", "sym"]}}, no_cursor_timeout=True)
for writing_file in file_cursor:
+ if from_path and not writing_file.filename.startswith(from_path):
+ continue
file_path = self.path + writing_file.filename
if writing_file.metadata["type"] == "sym":
self.fs.download_to_stream(writing_file._id, b)
b.seek(0)
link = b.read().decode("utf-8")
+
+ try:
+ os.remove(file_path)
+ except OSError as e:
+ if e.errno != errno.ENOENT:
+ # This is probably permission denied or worse
+ raise
os.symlink(link, file_path)
else:
with open(file_path, 'wb+') as file_stream:
if requested_file.metadata["type"] == mode:
return True
-
+
if requested_file.metadata["type"] == "sym" and mode == "file":
return True
else:
self.fs.delete(requested_file._id)
if not found and not ignore_non_exist:
- raise FsException("File {} does not exist".format(storage), http_code=HTTPStatus.NOT_FOUND)
+ raise FsException("File {} does not exist".format(storage), http_code=HTTPStatus.NOT_FOUND)
except IOError as e:
raise FsException("File {} cannot be deleted: {}".format(f, e), http_code=HTTPStatus.INTERNAL_SERVER_ERROR)
- def sync(self):
+ def sync(self, from_path=None):
"""
Sync from FSMongo to local storage
+ :param from_path: if supplied, only copy content from this path, not all
+ :return: None
"""
- self.__update_local_fs()
+ self.__update_local_fs(from_path=from_path)