Revision 23e3c9b7
b/lib/backend.py | ||
---|---|---|
800 | 800 |
result[constants.NV_BRIDGES] = [bridge |
801 | 801 |
for bridge in what[constants.NV_BRIDGES] |
802 | 802 |
if not utils.BridgeExists(bridge)] |
803 |
|
|
803 | 804 |
return result |
804 | 805 |
|
805 | 806 |
|
b/lib/bdev.py | ||
---|---|---|
29 | 29 |
import pyparsing as pyp |
30 | 30 |
import os |
31 | 31 |
import logging |
32 |
import itertools |
|
32 | 33 |
|
33 | 34 |
from ganeti import utils |
34 | 35 |
from ganeti import errors |
... | ... | |
100 | 101 |
return False |
101 | 102 |
|
102 | 103 |
|
104 |
def _GetForbiddenFileStoragePaths(): |
|
105 |
"""Builds a list of path prefixes which shouldn't be used for file storage. |
|
106 |
|
|
107 |
@rtype: frozenset |
|
108 |
|
|
109 |
""" |
|
110 |
paths = set([ |
|
111 |
"/boot", |
|
112 |
"/dev", |
|
113 |
"/etc", |
|
114 |
"/home", |
|
115 |
"/proc", |
|
116 |
"/root", |
|
117 |
"/sys", |
|
118 |
]) |
|
119 |
|
|
120 |
for prefix in ["", "/usr", "/usr/local"]: |
|
121 |
paths.update(map(lambda s: "%s/%s" % (prefix, s), |
|
122 |
["bin", "lib", "lib32", "lib64", "sbin"])) |
|
123 |
|
|
124 |
return frozenset(map(os.path.normpath, paths)) |
|
125 |
|
|
126 |
|
|
127 |
def _ComputeWrongFileStoragePaths(paths, |
|
128 |
_forbidden=_GetForbiddenFileStoragePaths()): |
|
129 |
"""Cross-checks a list of paths for prefixes considered bad. |
|
130 |
|
|
131 |
Some paths, e.g. "/bin", should not be used for file storage. |
|
132 |
|
|
133 |
@type paths: list |
|
134 |
@param paths: List of paths to be checked |
|
135 |
@rtype: list |
|
136 |
@return: Sorted list of paths for which the user should be warned |
|
137 |
|
|
138 |
""" |
|
139 |
def _Check(path): |
|
140 |
return (not os.path.isabs(path) or |
|
141 |
path in _forbidden or |
|
142 |
filter(lambda p: utils.IsBelowDir(p, path), _forbidden)) |
|
143 |
|
|
144 |
return utils.NiceSort(filter(_Check, map(os.path.normpath, paths))) |
|
145 |
|
|
146 |
|
|
147 |
def ComputeWrongFileStoragePaths(_filename=pathutils.FILE_STORAGE_PATHS_FILE): |
|
148 |
"""Returns a list of file storage paths whose prefix is considered bad. |
|
149 |
|
|
150 |
See L{_ComputeWrongFileStoragePaths}. |
|
151 |
|
|
152 |
""" |
|
153 |
return _ComputeWrongFileStoragePaths(_LoadAllowedFileStoragePaths(_filename)) |
|
154 |
|
|
155 |
|
|
103 | 156 |
def _CheckFileStoragePath(path, allowed): |
104 | 157 |
"""Checks if a path is in a list of allowed paths for file storage. |
105 | 158 |
|
... | ... | |
126 | 179 |
" storage" % path) |
127 | 180 |
|
128 | 181 |
|
129 |
def LoadAllowedFileStoragePaths(filename): |
|
182 |
def _LoadAllowedFileStoragePaths(filename):
|
|
130 | 183 |
"""Loads file containing allowed file storage paths. |
131 | 184 |
|
132 | 185 |
@rtype: list |
... | ... | |
149 | 202 |
@raise errors.FileStoragePathError: If the path is not allowed |
150 | 203 |
|
151 | 204 |
""" |
152 |
_CheckFileStoragePath(path, LoadAllowedFileStoragePaths(_filename)) |
|
205 |
allowed = _LoadAllowedFileStoragePaths(_filename) |
|
206 |
|
|
207 |
if _ComputeWrongFileStoragePaths([path]): |
|
208 |
raise errors.FileStoragePathError("Path '%s' uses a forbidden prefix" % |
|
209 |
path) |
|
210 |
|
|
211 |
_CheckFileStoragePath(path, allowed) |
|
153 | 212 |
|
154 | 213 |
|
155 | 214 |
class BlockDev(object): |
b/test/ganeti.bdev_unittest.py | ||
---|---|---|
373 | 373 |
output_extra_matches, volume_name) |
374 | 374 |
|
375 | 375 |
|
376 |
class TestCheckFileStoragePath(unittest.TestCase): |
|
376 |
class TestComputeWrongFileStoragePathsInternal(unittest.TestCase): |
|
377 |
def testPaths(self): |
|
378 |
paths = bdev._GetForbiddenFileStoragePaths() |
|
379 |
|
|
380 |
for path in ["/bin", "/usr/local/sbin", "/lib64", "/etc", "/sys"]: |
|
381 |
self.assertTrue(path in paths) |
|
382 |
|
|
383 |
self.assertEqual(set(map(os.path.normpath, paths)), paths) |
|
384 |
|
|
385 |
def test(self): |
|
386 |
vfsp = bdev._ComputeWrongFileStoragePaths |
|
387 |
self.assertEqual(vfsp([]), []) |
|
388 |
self.assertEqual(vfsp(["/tmp"]), []) |
|
389 |
self.assertEqual(vfsp(["/bin/ls"]), ["/bin/ls"]) |
|
390 |
self.assertEqual(vfsp(["/bin"]), ["/bin"]) |
|
391 |
self.assertEqual(vfsp(["/usr/sbin/vim", "/srv/file-storage"]), |
|
392 |
["/usr/sbin/vim"]) |
|
393 |
|
|
394 |
|
|
395 |
class TestComputeWrongFileStoragePaths(testutils.GanetiTestCase): |
|
396 |
def test(self): |
|
397 |
tmpfile = self._CreateTempFile() |
|
398 |
|
|
399 |
utils.WriteFile(tmpfile, data=""" |
|
400 |
/tmp |
|
401 |
x/y///z/relative |
|
402 |
# This is a test file |
|
403 |
/srv/storage |
|
404 |
/bin |
|
405 |
/usr/local/lib32/ |
|
406 |
relative/path |
|
407 |
""") |
|
408 |
|
|
409 |
self.assertEqual(bdev.ComputeWrongFileStoragePaths(_filename=tmpfile), [ |
|
410 |
"/bin", |
|
411 |
"/usr/local/lib32", |
|
412 |
"relative/path", |
|
413 |
"x/y/z/relative", |
|
414 |
]) |
|
415 |
|
|
416 |
|
|
417 |
class TestCheckFileStoragePathInternal(unittest.TestCase): |
|
377 | 418 |
def testNonAbsolute(self): |
378 | 419 |
for i in ["", "tmp", "foo/bar/baz"]: |
379 | 420 |
self.assertRaises(errors.FileStoragePathError, |
... | ... | |
395 | 436 |
bdev._CheckFileStoragePath("/tmp/foo/a/x", ["/tmp/foo"]) |
396 | 437 |
|
397 | 438 |
|
439 |
class TestCheckFileStoragePath(testutils.GanetiTestCase): |
|
440 |
def testNonExistantFile(self): |
|
441 |
filename = "/tmp/this/file/does/not/exist" |
|
442 |
assert not os.path.exists(filename) |
|
443 |
self.assertRaises(errors.FileStoragePathError, |
|
444 |
bdev.CheckFileStoragePath, "/bin/", _filename=filename) |
|
445 |
self.assertRaises(errors.FileStoragePathError, |
|
446 |
bdev.CheckFileStoragePath, "/srv/file-storage", |
|
447 |
_filename=filename) |
|
448 |
|
|
449 |
def testAllowedPath(self): |
|
450 |
tmpfile = self._CreateTempFile() |
|
451 |
|
|
452 |
utils.WriteFile(tmpfile, data=""" |
|
453 |
/srv/storage |
|
454 |
""") |
|
455 |
|
|
456 |
bdev.CheckFileStoragePath("/srv/storage/inst1", _filename=tmpfile) |
|
457 |
|
|
458 |
# No additional path component |
|
459 |
self.assertRaises(errors.FileStoragePathError, |
|
460 |
bdev.CheckFileStoragePath, "/srv/storage", |
|
461 |
_filename=tmpfile) |
|
462 |
|
|
463 |
# Forbidden path |
|
464 |
self.assertRaises(errors.FileStoragePathError, |
|
465 |
bdev.CheckFileStoragePath, "/usr/lib64/xyz", |
|
466 |
_filename=tmpfile) |
|
467 |
|
|
468 |
|
|
398 | 469 |
class TestLoadAllowedFileStoragePaths(testutils.GanetiTestCase): |
399 | 470 |
def testDevNull(self): |
400 |
self.assertEqual(bdev.LoadAllowedFileStoragePaths("/dev/null"), []) |
|
471 |
self.assertEqual(bdev._LoadAllowedFileStoragePaths("/dev/null"), [])
|
|
401 | 472 |
|
402 | 473 |
def testNonExistantFile(self): |
403 | 474 |
filename = "/tmp/this/file/does/not/exist" |
404 | 475 |
assert not os.path.exists(filename) |
405 |
self.assertEqual(bdev.LoadAllowedFileStoragePaths(filename), []) |
|
476 |
self.assertEqual(bdev._LoadAllowedFileStoragePaths(filename), [])
|
|
406 | 477 |
|
407 | 478 |
def test(self): |
408 | 479 |
tmpfile = self._CreateTempFile() |
... | ... | |
414 | 485 |
relative/path |
415 | 486 |
""") |
416 | 487 |
|
417 |
self.assertEqual(bdev.LoadAllowedFileStoragePaths(tmpfile), [ |
|
488 |
self.assertEqual(bdev._LoadAllowedFileStoragePaths(tmpfile), [
|
|
418 | 489 |
"/tmp", |
419 | 490 |
"/srv/storage", |
420 | 491 |
"relative/path", |
Also available in: Unified diff