1 |
|
# -*- coding: utf-8 -*- |
2 |
|
|
3 |
|
# Copyright 2018 Telefonica S.A. |
4 |
|
# |
5 |
|
# Licensed under the Apache License, Version 2.0 (the "License"); |
6 |
|
# you may not use this file except in compliance with the License. |
7 |
|
# You may obtain a copy of the License at |
8 |
|
# |
9 |
|
# http://www.apache.org/licenses/LICENSE-2.0 |
10 |
|
# |
11 |
|
# Unless required by applicable law or agreed to in writing, software |
12 |
|
# distributed under the License is distributed on an "AS IS" BASIS, |
13 |
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or |
14 |
|
# implied. |
15 |
|
# See the License for the specific language governing permissions and |
16 |
|
# limitations under the License. |
17 |
|
|
18 |
1 |
import os |
19 |
1 |
import logging |
20 |
|
# import tarfile |
21 |
1 |
from http import HTTPStatus |
22 |
1 |
from shutil import rmtree |
23 |
1 |
from osm_common.fsbase import FsBase, FsException |
24 |
|
|
25 |
1 |
__author__ = "Alfonso Tierno <alfonso.tiernosepulveda@telefonica.com>" |
26 |
|
|
27 |
|
|
28 |
1 |
class FsLocal(FsBase): |
29 |
|
|
30 |
1 |
def __init__(self, logger_name='fs', lock=False): |
31 |
1 |
super().__init__(logger_name, lock) |
32 |
1 |
self.path = None |
33 |
|
|
34 |
1 |
def get_params(self): |
35 |
0 |
return {"fs": "local", "path": self.path} |
36 |
|
|
37 |
1 |
def fs_connect(self, config): |
38 |
0 |
try: |
39 |
0 |
if "logger_name" in config: |
40 |
0 |
self.logger = logging.getLogger(config["logger_name"]) |
41 |
0 |
self.path = config["path"] |
42 |
0 |
if not self.path.endswith("/"): |
43 |
0 |
self.path += "/" |
44 |
0 |
if not os.path.exists(self.path): |
45 |
0 |
raise FsException("Invalid configuration param at '[storage]': path '{}' does not exist".format( |
46 |
|
config["path"])) |
47 |
0 |
except FsException: |
48 |
0 |
raise |
49 |
0 |
except Exception as e: # TODO refine |
50 |
0 |
raise FsException(str(e)) |
51 |
|
|
52 |
1 |
def fs_disconnect(self): |
53 |
0 |
pass # TODO |
54 |
|
|
55 |
1 |
def mkdir(self, folder): |
56 |
|
""" |
57 |
|
Creates a folder or parent object location |
58 |
|
:param folder: |
59 |
|
:return: None or raises and exception |
60 |
|
""" |
61 |
0 |
try: |
62 |
0 |
os.mkdir(self.path + folder) |
63 |
0 |
except FileExistsError: # make it idempotent |
64 |
0 |
pass |
65 |
0 |
except Exception as e: |
66 |
0 |
raise FsException(str(e), http_code=HTTPStatus.INTERNAL_SERVER_ERROR) |
67 |
|
|
68 |
1 |
def dir_rename(self, src, dst): |
69 |
|
""" |
70 |
|
Rename one directory name. If dst exist, it replaces (deletes) existing directory |
71 |
|
:param src: source directory |
72 |
|
:param dst: destination directory |
73 |
|
:return: None or raises and exception |
74 |
|
""" |
75 |
0 |
try: |
76 |
0 |
if os.path.exists(self.path + dst): |
77 |
0 |
rmtree(self.path + dst) |
78 |
|
|
79 |
0 |
os.rename(self.path + src, self.path + dst) |
80 |
|
|
81 |
0 |
except Exception as e: |
82 |
0 |
raise FsException(str(e), http_code=HTTPStatus.INTERNAL_SERVER_ERROR) |
83 |
|
|
84 |
1 |
def file_exists(self, storage, mode=None): |
85 |
|
""" |
86 |
|
Indicates if "storage" file exist |
87 |
|
:param storage: can be a str or a str list |
88 |
|
:param mode: can be 'file' exist as a regular file; 'dir' exists as a directory or; 'None' just exists |
89 |
|
:return: True, False |
90 |
|
""" |
91 |
0 |
if isinstance(storage, str): |
92 |
0 |
f = storage |
93 |
|
else: |
94 |
0 |
f = "/".join(storage) |
95 |
0 |
if os.path.exists(self.path + f): |
96 |
0 |
if not mode: |
97 |
0 |
return True |
98 |
0 |
if mode == "file" and os.path.isfile(self.path + f): |
99 |
0 |
return True |
100 |
0 |
if mode == "dir" and os.path.isdir(self.path + f): |
101 |
0 |
return True |
102 |
0 |
return False |
103 |
|
|
104 |
1 |
def file_size(self, storage): |
105 |
|
""" |
106 |
|
return file size |
107 |
|
:param storage: can be a str or a str list |
108 |
|
:return: file size |
109 |
|
""" |
110 |
0 |
if isinstance(storage, str): |
111 |
0 |
f = storage |
112 |
|
else: |
113 |
0 |
f = "/".join(storage) |
114 |
0 |
return os.path.getsize(self.path + f) |
115 |
|
|
116 |
1 |
def file_extract(self, tar_object, path): |
117 |
|
""" |
118 |
|
extract a tar file |
119 |
|
:param tar_object: object of type tar |
120 |
|
:param path: can be a str or a str list, or a tar object where to extract the tar_object |
121 |
|
:return: None |
122 |
|
""" |
123 |
0 |
if isinstance(path, str): |
124 |
0 |
f = self.path + path |
125 |
|
else: |
126 |
0 |
f = self.path + "/".join(path) |
127 |
0 |
tar_object.extractall(path=f) |
128 |
|
|
129 |
1 |
def file_open(self, storage, mode): |
130 |
|
""" |
131 |
|
Open a file |
132 |
|
:param storage: can be a str or list of str |
133 |
|
:param mode: file mode |
134 |
|
:return: file object |
135 |
|
""" |
136 |
0 |
try: |
137 |
0 |
if isinstance(storage, str): |
138 |
0 |
f = storage |
139 |
|
else: |
140 |
0 |
f = "/".join(storage) |
141 |
0 |
return open(self.path + f, mode) |
142 |
0 |
except FileNotFoundError: |
143 |
0 |
raise FsException("File {} does not exist".format(f), http_code=HTTPStatus.NOT_FOUND) |
144 |
0 |
except IOError: |
145 |
0 |
raise FsException("File {} cannot be opened".format(f), http_code=HTTPStatus.BAD_REQUEST) |
146 |
|
|
147 |
1 |
def dir_ls(self, storage): |
148 |
|
""" |
149 |
|
return folder content |
150 |
|
:param storage: can be a str or list of str |
151 |
|
:return: folder content |
152 |
|
""" |
153 |
0 |
try: |
154 |
0 |
if isinstance(storage, str): |
155 |
0 |
f = storage |
156 |
|
else: |
157 |
0 |
f = "/".join(storage) |
158 |
0 |
return os.listdir(self.path + f) |
159 |
0 |
except NotADirectoryError: |
160 |
0 |
raise FsException("File {} does not exist".format(f), http_code=HTTPStatus.NOT_FOUND) |
161 |
0 |
except IOError: |
162 |
0 |
raise FsException("File {} cannot be opened".format(f), http_code=HTTPStatus.BAD_REQUEST) |
163 |
|
|
164 |
1 |
def file_delete(self, storage, ignore_non_exist=False): |
165 |
|
""" |
166 |
|
Delete storage content recursively |
167 |
|
:param storage: can be a str or list of str |
168 |
|
:param ignore_non_exist: not raise exception if storage does not exist |
169 |
|
:return: None |
170 |
|
""" |
171 |
0 |
try: |
172 |
0 |
if isinstance(storage, str): |
173 |
0 |
f = self.path + storage |
174 |
|
else: |
175 |
0 |
f = self.path + "/".join(storage) |
176 |
0 |
if os.path.exists(f): |
177 |
0 |
rmtree(f) |
178 |
0 |
elif not ignore_non_exist: |
179 |
0 |
raise FsException("File {} does not exist".format(storage), http_code=HTTPStatus.NOT_FOUND) |
180 |
0 |
except (IOError, PermissionError) as e: |
181 |
0 |
raise FsException("File {} cannot be deleted: {}".format(f, e), http_code=HTTPStatus.INTERNAL_SERVER_ERROR) |
182 |
|
|
183 |
1 |
def sync(self, from_path=None): |
184 |
0 |
pass # Not needed in fslocal |
185 |
|
|
186 |
1 |
def reverse_sync(self, from_path): |
187 |
0 |
pass # Not needed in fslocal |