Revision 13a6c760

b/lib/backend.py
1130 1130
                                    for bridge in what[constants.NV_BRIDGES]
1131 1131
                                    if not utils.BridgeExists(bridge)]
1132 1132

  
1133
  if what.get(constants.NV_FILE_STORAGE_PATHS) == my_name:
1134
    result[constants.NV_FILE_STORAGE_PATHS] = \
1135
      bdev.ComputeWrongFileStoragePaths()
1133
  if what.get(constants.NV_ACCEPTED_STORAGE_PATHS) == my_name:
1134
    result[constants.NV_ACCEPTED_STORAGE_PATHS] = \
1135
        filestorage.ComputeWrongFileStoragePaths()
1136 1136

  
1137 1137
  return result
1138 1138

  
......
3195 3195
  @return: the normalized path if valid, None otherwise
3196 3196

  
3197 3197
  """
3198
  bdev.CheckFileStoragePath(fs_dir)
3198
  filestorage.CheckFileStoragePath(fs_dir)
3199 3199

  
3200 3200
  return os.path.normpath(fs_dir)
3201 3201

  
b/lib/cmdlib/cluster.py
2294 2294
                  " but missing on this node: %s",
2295 2295
                  self.cfg.GetNodeName(base.uuid), utils.CommaJoin(missing))
2296 2296

  
2297
  def _VerifyFileStoragePaths(self, ninfo, nresult, is_master,
2298
                              enabled_disk_templates):
2297
  def _VerifyAcceptedFileStoragePaths(self, ninfo, nresult, is_master):
2299 2298
    """Verifies paths in L{pathutils.FILE_STORAGE_PATHS_FILE}.
2300 2299

  
2301 2300
    @type ninfo: L{objects.Node}
......
2305 2304
    @param is_master: Whether node is the master node
2306 2305

  
2307 2306
    """
2307
    cluster = self.cfg.GetClusterInfo()
2308 2308
    if (is_master and
2309
        (utils.storage.IsFileStorageEnabled(enabled_disk_templates) or
2310
         utils.storage.IsSharedFileStorageEnabled(enabled_disk_templates))):
2309
        (cluster.IsFileStorageEnabled() or
2310
         cluster.IsSharedFileStorageEnabled())):
2311 2311
      try:
2312
        fspaths = nresult[constants.NV_FILE_STORAGE_PATHS]
2312
        fspaths = nresult[constants.NV_ACCEPTED_STORAGE_PATHS]
2313 2313
      except KeyError:
2314 2314
        # This should never happen
2315 2315
        self._ErrorIf(True, constants.CV_ENODEFILESTORAGEPATHS, ninfo.name,
......
2319 2319
                      "Found forbidden file storage paths: %s",
2320 2320
                      utils.CommaJoin(fspaths))
2321 2321
    else:
2322
      self._ErrorIf(constants.NV_FILE_STORAGE_PATHS in nresult,
2322
      self._ErrorIf(constants.NV_ACCEPTED_STORAGE_PATHS in nresult,
2323 2323
                    constants.CV_ENODEFILESTORAGEPATHS, ninfo.name,
2324 2324
                    "Node should not have returned forbidden file storage"
2325 2325
                    " paths")
......
2669 2669
    if cluster.IsFileStorageEnabled() or \
2670 2670
        cluster.IsSharedFileStorageEnabled():
2671 2671
      # Load file storage paths only from master node
2672
      node_verify_param[constants.NV_FILE_STORAGE_PATHS] = \
2672
      node_verify_param[constants.NV_ACCEPTED_STORAGE_PATHS] = \
2673 2673
        self.cfg.GetMasterNodeName()
2674
      if cluster.IsFileStorageEnabled():
2675
        node_verify_param[constants.NV_FILE_STORAGE_PATH] = \
2676
          cluster.file_storage_dir
2674 2677

  
2675 2678
    # bridge checks
2676 2679
    # FIXME: this needs to be changed per node-group, not cluster-wide
......
2834 2837
      self._VerifyNodeNetwork(node_i, nresult)
2835 2838
      self._VerifyNodeUserScripts(node_i, nresult)
2836 2839
      self._VerifyOob(node_i, nresult)
2837
      self._VerifyFileStoragePaths(node_i, nresult,
2838
                                   node_i.uuid == master_node_uuid,
2839
                                   cluster.enabled_disk_templates)
2840
      self._VerifyAcceptedFileStoragePaths(node_i, nresult,
2841
                                           node_i.uuid == master_node_uuid)
2840 2842

  
2841 2843
      if nimg.vm_capable:
2842 2844
        self._UpdateVerifyNodeLVM(node_i, nresult, vg_name, nimg)
b/lib/constants.py
1693 1693
NV_DRBDLIST = "drbd-list"
1694 1694
NV_EXCLUSIVEPVS = "exclusive-pvs"
1695 1695
NV_FILELIST = "filelist"
1696
NV_FILE_STORAGE_PATHS = "file-storage-paths"
1696
NV_ACCEPTED_STORAGE_PATHS = "allowed-file-storage-paths"
1697
NV_FILE_STORAGE_PATH = "file-storage-path"
1698
NV_SHARED_FILE_STORAGE_PATH = "shared-file-storage-path"
1697 1699
NV_HVINFO = "hvinfo"
1698 1700
NV_HVPARAMS = "hvparms"
1699 1701
NV_HYPERVISOR = "hypervisor"
b/lib/storage/bdev.py
35 35
from ganeti import compat
36 36
from ganeti import pathutils
37 37
from ganeti import serializer
38
from ganeti.storage import drbd
39 38
from ganeti.storage import base
39
from ganeti.storage import drbd
40
from ganeti.storage import filestorage
40 41

  
41 42

  
42 43
class RbdShowmappedJsonError(Exception):
......
57 58
                    result.cmd, result.fail_reason, result.output)
58 59

  
59 60

  
60
def _GetForbiddenFileStoragePaths():
61
  """Builds a list of path prefixes which shouldn't be used for file storage.
62

  
63
  @rtype: frozenset
64

  
65
  """
66
  paths = set([
67
    "/boot",
68
    "/dev",
69
    "/etc",
70
    "/home",
71
    "/proc",
72
    "/root",
73
    "/sys",
74
    ])
75

  
76
  for prefix in ["", "/usr", "/usr/local"]:
77
    paths.update(map(lambda s: "%s/%s" % (prefix, s),
78
                     ["bin", "lib", "lib32", "lib64", "sbin"]))
79

  
80
  return compat.UniqueFrozenset(map(os.path.normpath, paths))
81

  
82

  
83
def _ComputeWrongFileStoragePaths(paths,
84
                                  _forbidden=_GetForbiddenFileStoragePaths()):
85
  """Cross-checks a list of paths for prefixes considered bad.
86

  
87
  Some paths, e.g. "/bin", should not be used for file storage.
88

  
89
  @type paths: list
90
  @param paths: List of paths to be checked
91
  @rtype: list
92
  @return: Sorted list of paths for which the user should be warned
93

  
94
  """
95
  def _Check(path):
96
    return (not os.path.isabs(path) or
97
            path in _forbidden or
98
            filter(lambda p: utils.IsBelowDir(p, path), _forbidden))
99

  
100
  return utils.NiceSort(filter(_Check, map(os.path.normpath, paths)))
101

  
102

  
103
def ComputeWrongFileStoragePaths(_filename=pathutils.FILE_STORAGE_PATHS_FILE):
104
  """Returns a list of file storage paths whose prefix is considered bad.
105

  
106
  See L{_ComputeWrongFileStoragePaths}.
107

  
108
  """
109
  return _ComputeWrongFileStoragePaths(_LoadAllowedFileStoragePaths(_filename))
110

  
111

  
112
def _CheckFileStoragePath(path, allowed):
113
  """Checks if a path is in a list of allowed paths for file storage.
114

  
115
  @type path: string
116
  @param path: Path to check
117
  @type allowed: list
118
  @param allowed: List of allowed paths
119
  @raise errors.FileStoragePathError: If the path is not allowed
120

  
121
  """
122
  if not os.path.isabs(path):
123
    raise errors.FileStoragePathError("File storage path must be absolute,"
124
                                      " got '%s'" % path)
125

  
126
  for i in allowed:
127
    if not os.path.isabs(i):
128
      logging.info("Ignoring relative path '%s' for file storage", i)
129
      continue
130

  
131
    if utils.IsBelowDir(i, path):
132
      break
133
  else:
134
    raise errors.FileStoragePathError("Path '%s' is not acceptable for file"
135
                                      " storage" % path)
136

  
137

  
138
def _LoadAllowedFileStoragePaths(filename):
139
  """Loads file containing allowed file storage paths.
140

  
141
  @rtype: list
142
  @return: List of allowed paths (can be an empty list)
143

  
144
  """
145
  try:
146
    contents = utils.ReadFile(filename)
147
  except EnvironmentError:
148
    return []
149
  else:
150
    return utils.FilterEmptyLinesAndComments(contents)
151

  
152

  
153
def CheckFileStoragePath(path, _filename=pathutils.FILE_STORAGE_PATHS_FILE):
154
  """Checks if a path is allowed for file storage.
155

  
156
  @type path: string
157
  @param path: Path to check
158
  @raise errors.FileStoragePathError: If the path is not allowed
159

  
160
  """
161
  allowed = _LoadAllowedFileStoragePaths(_filename)
162

  
163
  if _ComputeWrongFileStoragePaths([path]):
164
    raise errors.FileStoragePathError("Path '%s' uses a forbidden prefix" %
165
                                      path)
166

  
167
  _CheckFileStoragePath(path, allowed)
168

  
169

  
170 61
class LogicalVolume(base.BlockDev):
171 62
  """Logical Volume block device.
172 63

  
......
838 729
    self.driver = unique_id[0]
839 730
    self.dev_path = unique_id[1]
840 731

  
841
    CheckFileStoragePath(self.dev_path)
732
    filestorage.CheckFileStoragePathAcceptance(self.dev_path)
842 733

  
843 734
    self.Attach()
844 735

  
......
962 853

  
963 854
    dev_path = unique_id[1]
964 855

  
965
    CheckFileStoragePath(dev_path)
856
    filestorage.CheckFileStoragePathAcceptance(dev_path)
966 857

  
967 858
    try:
968 859
      fd = os.open(dev_path, os.O_RDWR | os.O_CREAT | os.O_EXCL)
b/lib/storage/filestorage.py
23 23

  
24 24
"""
25 25

  
26
import logging
26 27
import os
27 28

  
29
from ganeti import compat
28 30
from ganeti import constants
29 31
from ganeti import errors
32
from ganeti import pathutils
33
from ganeti import utils
30 34

  
31 35

  
32 36
def GetFileStorageSpaceInfo(path):
......
50 54
  except OSError, e:
51 55
    raise errors.CommandError("Failed to retrieve file system information about"
52 56
                              " path: %s - %s" % (path, e.strerror))
57

  
58

  
59
def _GetForbiddenFileStoragePaths():
60
  """Builds a list of path prefixes which shouldn't be used for file storage.
61

  
62
  @rtype: frozenset
63

  
64
  """
65
  paths = set([
66
    "/boot",
67
    "/dev",
68
    "/etc",
69
    "/home",
70
    "/proc",
71
    "/root",
72
    "/sys",
73
    ])
74

  
75
  for prefix in ["", "/usr", "/usr/local"]:
76
    paths.update(map(lambda s: "%s/%s" % (prefix, s),
77
                     ["bin", "lib", "lib32", "lib64", "sbin"]))
78

  
79
  return compat.UniqueFrozenset(map(os.path.normpath, paths))
80

  
81

  
82
def _ComputeWrongFileStoragePaths(paths,
83
                                  _forbidden=_GetForbiddenFileStoragePaths()):
84
  """Cross-checks a list of paths for prefixes considered bad.
85

  
86
  Some paths, e.g. "/bin", should not be used for file storage.
87

  
88
  @type paths: list
89
  @param paths: List of paths to be checked
90
  @rtype: list
91
  @return: Sorted list of paths for which the user should be warned
92

  
93
  """
94
  def _Check(path):
95
    return (not os.path.isabs(path) or
96
            path in _forbidden or
97
            filter(lambda p: utils.IsBelowDir(p, path), _forbidden))
98

  
99
  return utils.NiceSort(filter(_Check, map(os.path.normpath, paths)))
100

  
101

  
102
def ComputeWrongFileStoragePaths(_filename=pathutils.FILE_STORAGE_PATHS_FILE):
103
  """Returns a list of file storage paths whose prefix is considered bad.
104

  
105
  See L{_ComputeWrongFileStoragePaths}.
106

  
107
  """
108
  return _ComputeWrongFileStoragePaths(_LoadAllowedFileStoragePaths(_filename))
109

  
110

  
111
def _CheckFileStoragePath(path, allowed):
112
  """Checks if a path is in a list of allowed paths for file storage.
113

  
114
  @type path: string
115
  @param path: Path to check
116
  @type allowed: list
117
  @param allowed: List of allowed paths
118
  @raise errors.FileStoragePathError: If the path is not allowed
119

  
120
  """
121
  if not os.path.isabs(path):
122
    raise errors.FileStoragePathError("File storage path must be absolute,"
123
                                      " got '%s'" % path)
124

  
125
  for i in allowed:
126
    if not os.path.isabs(i):
127
      logging.info("Ignoring relative path '%s' for file storage", i)
128
      continue
129

  
130
    if utils.IsBelowDir(i, path):
131
      break
132
  else:
133
    raise errors.FileStoragePathError("Path '%s' is not acceptable for file"
134
                                      " storage" % path)
135

  
136

  
137
def _LoadAllowedFileStoragePaths(filename):
138
  """Loads file containing allowed file storage paths.
139

  
140
  @rtype: list
141
  @return: List of allowed paths (can be an empty list)
142

  
143
  """
144
  try:
145
    contents = utils.ReadFile(filename)
146
  except EnvironmentError:
147
    return []
148
  else:
149
    return utils.FilterEmptyLinesAndComments(contents)
150

  
151

  
152
def CheckFileStoragePathAcceptance(
153
    path, _filename=pathutils.FILE_STORAGE_PATHS_FILE):
154
  """Checks if a path is allowed for file storage.
155

  
156
  @type path: string
157
  @param path: Path to check
158
  @raise errors.FileStoragePathError: If the path is not allowed
159

  
160
  """
161
  allowed = _LoadAllowedFileStoragePaths(_filename)
162

  
163
  if _ComputeWrongFileStoragePaths([path]):
164
    raise errors.FileStoragePathError("Path '%s' uses a forbidden prefix" %
165
                                      path)
166

  
167
  _CheckFileStoragePath(path, allowed)

Also available in: Unified diff