Statistics
| Branch: | Tag: | Revision:

root / lib / storage / filestorage.py @ 13a6c760

History | View | Annotate | Download (4.7 kB)

1
#
2
#
3

    
4
# Copyright (C) 2013 Google Inc.
5
#
6
# This program is free software; you can redistribute it and/or modify
7
# it under the terms of the GNU General Public License as published by
8
# the Free Software Foundation; either version 2 of the License, or
9
# (at your option) any later version.
10
#
11
# This program is distributed in the hope that it will be useful, but
12
# WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
# General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License
17
# along with this program; if not, write to the Free Software
18
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
# 02110-1301, USA.
20

    
21

    
22
"""File storage functions.
23

24
"""
25

    
26
import logging
27
import os
28

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

    
35

    
36
def GetFileStorageSpaceInfo(path):
37
  """Retrieves the free and total space of the device where the file is
38
     located.
39

40
     @type path: string
41
     @param path: Path of the file whose embracing device's capacity is
42
       reported.
43
     @return: a dictionary containing 'vg_size' and 'vg_free' given in MebiBytes
44

45
  """
46
  try:
47
    result = os.statvfs(path)
48
    free = (result.f_frsize * result.f_bavail) / (1024 * 1024)
49
    size = (result.f_frsize * result.f_blocks) / (1024 * 1024)
50
    return {"type": constants.ST_FILE,
51
            "name": path,
52
            "storage_size": size,
53
            "storage_free": free}
54
  except OSError, e:
55
    raise errors.CommandError("Failed to retrieve file system information about"
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)