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