root / lib / storage / filestorage.py @ 18397489
History | View | Annotate | Download (6.4 kB)
1 | 820bade9 | Helga Velroyen | #
|
---|---|---|---|
2 | 820bade9 | Helga Velroyen | #
|
3 | 820bade9 | Helga Velroyen | |
4 | 820bade9 | Helga Velroyen | # Copyright (C) 2013 Google Inc.
|
5 | 820bade9 | Helga Velroyen | #
|
6 | 820bade9 | Helga Velroyen | # This program is free software; you can redistribute it and/or modify
|
7 | 820bade9 | Helga Velroyen | # it under the terms of the GNU General Public License as published by
|
8 | 820bade9 | Helga Velroyen | # the Free Software Foundation; either version 2 of the License, or
|
9 | 820bade9 | Helga Velroyen | # (at your option) any later version.
|
10 | 820bade9 | Helga Velroyen | #
|
11 | 820bade9 | Helga Velroyen | # This program is distributed in the hope that it will be useful, but
|
12 | 820bade9 | Helga Velroyen | # WITHOUT ANY WARRANTY; without even the implied warranty of
|
13 | 820bade9 | Helga Velroyen | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
14 | 820bade9 | Helga Velroyen | # General Public License for more details.
|
15 | 820bade9 | Helga Velroyen | #
|
16 | 820bade9 | Helga Velroyen | # You should have received a copy of the GNU General Public License
|
17 | 820bade9 | Helga Velroyen | # along with this program; if not, write to the Free Software
|
18 | 820bade9 | Helga Velroyen | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
19 | 820bade9 | Helga Velroyen | # 02110-1301, USA.
|
20 | 820bade9 | Helga Velroyen | |
21 | 820bade9 | Helga Velroyen | |
22 | 820bade9 | Helga Velroyen | """File storage functions.
|
23 | 820bade9 | Helga Velroyen |
|
24 | 820bade9 | Helga Velroyen | """
|
25 | 820bade9 | Helga Velroyen | |
26 | 13a6c760 | Helga Velroyen | import logging |
27 | 5d94c034 | Helga Velroyen | import os |
28 | 820bade9 | Helga Velroyen | |
29 | 13a6c760 | Helga Velroyen | from ganeti import compat |
30 | 13669ecd | Helga Velroyen | from ganeti import constants |
31 | 5d94c034 | Helga Velroyen | from ganeti import errors |
32 | 13a6c760 | Helga Velroyen | from ganeti import pathutils |
33 | 13a6c760 | Helga Velroyen | from ganeti import utils |
34 | 820bade9 | Helga Velroyen | |
35 | 820bade9 | Helga Velroyen | |
36 | e798d484 | Helga Velroyen | def GetFileStorageSpaceInfo(path): |
37 | 820bade9 | Helga Velroyen | """Retrieves the free and total space of the device where the file is
|
38 | 820bade9 | Helga Velroyen | located.
|
39 | 820bade9 | Helga Velroyen |
|
40 | 820bade9 | Helga Velroyen | @type path: string
|
41 | 820bade9 | Helga Velroyen | @param path: Path of the file whose embracing device's capacity is
|
42 | 820bade9 | Helga Velroyen | reported.
|
43 | 5d94c034 | Helga Velroyen | @return: a dictionary containing 'vg_size' and 'vg_free' given in MebiBytes
|
44 | 5d94c034 | Helga Velroyen |
|
45 | 820bade9 | Helga Velroyen | """
|
46 | 5d94c034 | Helga Velroyen | try:
|
47 | 5d94c034 | Helga Velroyen | result = os.statvfs(path) |
48 | 5d94c034 | Helga Velroyen | free = (result.f_frsize * result.f_bavail) / (1024 * 1024) |
49 | 5d94c034 | Helga Velroyen | size = (result.f_frsize * result.f_blocks) / (1024 * 1024) |
50 | 13669ecd | Helga Velroyen | return {"type": constants.ST_FILE, |
51 | 13669ecd | Helga Velroyen | "name": path,
|
52 | 32389d91 | Helga Velroyen | "storage_size": size,
|
53 | 32389d91 | Helga Velroyen | "storage_free": free}
|
54 | 5d94c034 | Helga Velroyen | except OSError, e: |
55 | 5d94c034 | Helga Velroyen | raise errors.CommandError("Failed to retrieve file system information about" |
56 | 5d94c034 | Helga Velroyen | " path: %s - %s" % (path, e.strerror))
|
57 | 13a6c760 | Helga Velroyen | |
58 | 13a6c760 | Helga Velroyen | |
59 | 13a6c760 | Helga Velroyen | def _GetForbiddenFileStoragePaths(): |
60 | 13a6c760 | Helga Velroyen | """Builds a list of path prefixes which shouldn't be used for file storage.
|
61 | 13a6c760 | Helga Velroyen |
|
62 | 13a6c760 | Helga Velroyen | @rtype: frozenset
|
63 | 13a6c760 | Helga Velroyen |
|
64 | 13a6c760 | Helga Velroyen | """
|
65 | 13a6c760 | Helga Velroyen | paths = set([
|
66 | 13a6c760 | Helga Velroyen | "/boot",
|
67 | 13a6c760 | Helga Velroyen | "/dev",
|
68 | 13a6c760 | Helga Velroyen | "/etc",
|
69 | 13a6c760 | Helga Velroyen | "/home",
|
70 | 13a6c760 | Helga Velroyen | "/proc",
|
71 | 13a6c760 | Helga Velroyen | "/root",
|
72 | 13a6c760 | Helga Velroyen | "/sys",
|
73 | 13a6c760 | Helga Velroyen | ]) |
74 | 13a6c760 | Helga Velroyen | |
75 | 13a6c760 | Helga Velroyen | for prefix in ["", "/usr", "/usr/local"]: |
76 | 13a6c760 | Helga Velroyen | paths.update(map(lambda s: "%s/%s" % (prefix, s), |
77 | 13a6c760 | Helga Velroyen | ["bin", "lib", "lib32", "lib64", "sbin"])) |
78 | 13a6c760 | Helga Velroyen | |
79 | 13a6c760 | Helga Velroyen | return compat.UniqueFrozenset(map(os.path.normpath, paths)) |
80 | 13a6c760 | Helga Velroyen | |
81 | 13a6c760 | Helga Velroyen | |
82 | 13a6c760 | Helga Velroyen | def _ComputeWrongFileStoragePaths(paths, |
83 | 13a6c760 | Helga Velroyen | _forbidden=_GetForbiddenFileStoragePaths()): |
84 | 13a6c760 | Helga Velroyen | """Cross-checks a list of paths for prefixes considered bad.
|
85 | 13a6c760 | Helga Velroyen |
|
86 | 13a6c760 | Helga Velroyen | Some paths, e.g. "/bin", should not be used for file storage.
|
87 | 13a6c760 | Helga Velroyen |
|
88 | 13a6c760 | Helga Velroyen | @type paths: list
|
89 | 13a6c760 | Helga Velroyen | @param paths: List of paths to be checked
|
90 | 13a6c760 | Helga Velroyen | @rtype: list
|
91 | 13a6c760 | Helga Velroyen | @return: Sorted list of paths for which the user should be warned
|
92 | 13a6c760 | Helga Velroyen |
|
93 | 13a6c760 | Helga Velroyen | """
|
94 | 13a6c760 | Helga Velroyen | def _Check(path): |
95 | 13a6c760 | Helga Velroyen | return (not os.path.isabs(path) or |
96 | 13a6c760 | Helga Velroyen | path in _forbidden or |
97 | 13a6c760 | Helga Velroyen | filter(lambda p: utils.IsBelowDir(p, path), _forbidden)) |
98 | 13a6c760 | Helga Velroyen | |
99 | 13a6c760 | Helga Velroyen | return utils.NiceSort(filter(_Check, map(os.path.normpath, paths))) |
100 | 13a6c760 | Helga Velroyen | |
101 | 13a6c760 | Helga Velroyen | |
102 | 13a6c760 | Helga Velroyen | def ComputeWrongFileStoragePaths(_filename=pathutils.FILE_STORAGE_PATHS_FILE): |
103 | 13a6c760 | Helga Velroyen | """Returns a list of file storage paths whose prefix is considered bad.
|
104 | 13a6c760 | Helga Velroyen |
|
105 | 13a6c760 | Helga Velroyen | See L{_ComputeWrongFileStoragePaths}.
|
106 | 13a6c760 | Helga Velroyen |
|
107 | 13a6c760 | Helga Velroyen | """
|
108 | 13a6c760 | Helga Velroyen | return _ComputeWrongFileStoragePaths(_LoadAllowedFileStoragePaths(_filename))
|
109 | 13a6c760 | Helga Velroyen | |
110 | 13a6c760 | Helga Velroyen | |
111 | 9c1c3c19 | Helga Velroyen | def _CheckFileStoragePath(path, allowed, exact_match_ok=False): |
112 | 13a6c760 | Helga Velroyen | """Checks if a path is in a list of allowed paths for file storage.
|
113 | 13a6c760 | Helga Velroyen |
|
114 | 13a6c760 | Helga Velroyen | @type path: string
|
115 | 13a6c760 | Helga Velroyen | @param path: Path to check
|
116 | 13a6c760 | Helga Velroyen | @type allowed: list
|
117 | 13a6c760 | Helga Velroyen | @param allowed: List of allowed paths
|
118 | 9c1c3c19 | Helga Velroyen | @type exact_match_ok: bool
|
119 | 9c1c3c19 | Helga Velroyen | @param exact_match_ok: whether or not it is okay when the path is exactly
|
120 | 9c1c3c19 | Helga Velroyen | equal to an allowed path and not a subdir of it
|
121 | 13a6c760 | Helga Velroyen | @raise errors.FileStoragePathError: If the path is not allowed
|
122 | 13a6c760 | Helga Velroyen |
|
123 | 13a6c760 | Helga Velroyen | """
|
124 | 13a6c760 | Helga Velroyen | if not os.path.isabs(path): |
125 | 13a6c760 | Helga Velroyen | raise errors.FileStoragePathError("File storage path must be absolute," |
126 | 13a6c760 | Helga Velroyen | " got '%s'" % path)
|
127 | 13a6c760 | Helga Velroyen | |
128 | 13a6c760 | Helga Velroyen | for i in allowed: |
129 | 13a6c760 | Helga Velroyen | if not os.path.isabs(i): |
130 | 13a6c760 | Helga Velroyen | logging.info("Ignoring relative path '%s' for file storage", i)
|
131 | 13a6c760 | Helga Velroyen | continue
|
132 | 13a6c760 | Helga Velroyen | |
133 | 9c1c3c19 | Helga Velroyen | if exact_match_ok:
|
134 | 9c1c3c19 | Helga Velroyen | if os.path.normpath(i) == os.path.normpath(path):
|
135 | 9c1c3c19 | Helga Velroyen | break
|
136 | 9c1c3c19 | Helga Velroyen | |
137 | 13a6c760 | Helga Velroyen | if utils.IsBelowDir(i, path):
|
138 | 13a6c760 | Helga Velroyen | break
|
139 | 13a6c760 | Helga Velroyen | else:
|
140 | 13a6c760 | Helga Velroyen | raise errors.FileStoragePathError("Path '%s' is not acceptable for file" |
141 | 13a6c760 | Helga Velroyen | " storage" % path)
|
142 | 13a6c760 | Helga Velroyen | |
143 | 13a6c760 | Helga Velroyen | |
144 | 13a6c760 | Helga Velroyen | def _LoadAllowedFileStoragePaths(filename): |
145 | 13a6c760 | Helga Velroyen | """Loads file containing allowed file storage paths.
|
146 | 13a6c760 | Helga Velroyen |
|
147 | 13a6c760 | Helga Velroyen | @rtype: list
|
148 | 13a6c760 | Helga Velroyen | @return: List of allowed paths (can be an empty list)
|
149 | 13a6c760 | Helga Velroyen |
|
150 | 13a6c760 | Helga Velroyen | """
|
151 | 13a6c760 | Helga Velroyen | try:
|
152 | 13a6c760 | Helga Velroyen | contents = utils.ReadFile(filename) |
153 | 13a6c760 | Helga Velroyen | except EnvironmentError: |
154 | 13a6c760 | Helga Velroyen | return []
|
155 | 13a6c760 | Helga Velroyen | else:
|
156 | 13a6c760 | Helga Velroyen | return utils.FilterEmptyLinesAndComments(contents)
|
157 | 13a6c760 | Helga Velroyen | |
158 | 13a6c760 | Helga Velroyen | |
159 | 13a6c760 | Helga Velroyen | def CheckFileStoragePathAcceptance( |
160 | 9c1c3c19 | Helga Velroyen | path, _filename=pathutils.FILE_STORAGE_PATHS_FILE, |
161 | 9c1c3c19 | Helga Velroyen | exact_match_ok=False):
|
162 | 13a6c760 | Helga Velroyen | """Checks if a path is allowed for file storage.
|
163 | 13a6c760 | Helga Velroyen |
|
164 | 13a6c760 | Helga Velroyen | @type path: string
|
165 | 13a6c760 | Helga Velroyen | @param path: Path to check
|
166 | 13a6c760 | Helga Velroyen | @raise errors.FileStoragePathError: If the path is not allowed
|
167 | 13a6c760 | Helga Velroyen |
|
168 | 13a6c760 | Helga Velroyen | """
|
169 | 13a6c760 | Helga Velroyen | allowed = _LoadAllowedFileStoragePaths(_filename) |
170 | f3ebe73e | Helga Velroyen | if not allowed: |
171 | f3ebe73e | Helga Velroyen | raise errors.FileStoragePathError("No paths are valid or path file '%s'" |
172 | f3ebe73e | Helga Velroyen | " was not accessible." % _filename)
|
173 | 13a6c760 | Helga Velroyen | |
174 | 13a6c760 | Helga Velroyen | if _ComputeWrongFileStoragePaths([path]):
|
175 | 13a6c760 | Helga Velroyen | raise errors.FileStoragePathError("Path '%s' uses a forbidden prefix" % |
176 | 13a6c760 | Helga Velroyen | path) |
177 | 13a6c760 | Helga Velroyen | |
178 | 9c1c3c19 | Helga Velroyen | _CheckFileStoragePath(path, allowed, exact_match_ok=exact_match_ok) |
179 | 9c1c3c19 | Helga Velroyen | |
180 | 9c1c3c19 | Helga Velroyen | |
181 | 9c1c3c19 | Helga Velroyen | def _CheckFileStoragePathExistance(path): |
182 | 9c1c3c19 | Helga Velroyen | """Checks whether the given path is usable on the file system.
|
183 | 9c1c3c19 | Helga Velroyen |
|
184 | 9c1c3c19 | Helga Velroyen | This checks wether the path is existing, a directory and writable.
|
185 | 9c1c3c19 | Helga Velroyen |
|
186 | 9c1c3c19 | Helga Velroyen | @type path: string
|
187 | 9c1c3c19 | Helga Velroyen | @param path: path to check
|
188 | 9c1c3c19 | Helga Velroyen |
|
189 | 9c1c3c19 | Helga Velroyen | """
|
190 | 9c1c3c19 | Helga Velroyen | if not os.path.isdir(path): |
191 | f3ebe73e | Helga Velroyen | raise errors.FileStoragePathError("Path '%s' is not existing or not a" |
192 | 9c1c3c19 | Helga Velroyen | " directory." % path)
|
193 | 9c1c3c19 | Helga Velroyen | if not os.access(path, os.W_OK): |
194 | 9c1c3c19 | Helga Velroyen | raise errors.FileStoragePathError("Path '%s' is not writable" % path) |
195 | 9c1c3c19 | Helga Velroyen | |
196 | 9c1c3c19 | Helga Velroyen | |
197 | 9c1c3c19 | Helga Velroyen | def CheckFileStoragePath( |
198 | 9c1c3c19 | Helga Velroyen | path, _allowed_paths_file=pathutils.FILE_STORAGE_PATHS_FILE): |
199 | 9c1c3c19 | Helga Velroyen | """Checks whether the path exists and is acceptable to use.
|
200 | 9c1c3c19 | Helga Velroyen |
|
201 | 4b322a76 | Helga Velroyen | Can be used for any file-based storage, for example shared-file storage.
|
202 | 4b322a76 | Helga Velroyen |
|
203 | 9c1c3c19 | Helga Velroyen | @type path: string
|
204 | 9c1c3c19 | Helga Velroyen | @param path: path to check
|
205 | 9c1c3c19 | Helga Velroyen | @rtype: string
|
206 | 9c1c3c19 | Helga Velroyen | @returns: error message if the path is not ready to use
|
207 | 9c1c3c19 | Helga Velroyen |
|
208 | 9c1c3c19 | Helga Velroyen | """
|
209 | 9c1c3c19 | Helga Velroyen | try:
|
210 | 9c1c3c19 | Helga Velroyen | CheckFileStoragePathAcceptance(path, _filename=_allowed_paths_file, |
211 | 9c1c3c19 | Helga Velroyen | exact_match_ok=True)
|
212 | 2650ea6b | Helga Velroyen | except errors.FileStoragePathError as e: |
213 | 2650ea6b | Helga Velroyen | return str(e) |
214 | 9c1c3c19 | Helga Velroyen | if not os.path.isdir(path): |
215 | 9c1c3c19 | Helga Velroyen | return "Path '%s' is not exisiting or not a directory." % path |
216 | 9c1c3c19 | Helga Velroyen | if not os.access(path, os.W_OK): |
217 | 9c1c3c19 | Helga Velroyen | return "Path '%s' is not writable" % path |