Statistics
| Branch: | Tag: | Revision:

root / lib / tools / ensure_dirs.py @ a30b473c

History | View | Annotate | Download (8 kB)

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

20 0d2bf835 René Nussbaumer
"""
21 0d2bf835 René Nussbaumer
22 0d2bf835 René Nussbaumer
import errno
23 0d2bf835 René Nussbaumer
import os
24 0d2bf835 René Nussbaumer
import os.path
25 0d2bf835 René Nussbaumer
import optparse
26 0d2bf835 René Nussbaumer
import sys
27 0d2bf835 René Nussbaumer
import stat
28 0d2bf835 René Nussbaumer
29 0d2bf835 René Nussbaumer
from ganeti import constants
30 0d2bf835 René Nussbaumer
from ganeti import errors
31 0d2bf835 René Nussbaumer
from ganeti import runtime
32 0d2bf835 René Nussbaumer
from ganeti import ssconf
33 0d2bf835 René Nussbaumer
34 0d2bf835 René Nussbaumer
35 0d2bf835 René Nussbaumer
(DIR, FILE) = range(2)
36 0d2bf835 René Nussbaumer
ALL_TYPES = frozenset([DIR, FILE])
37 0d2bf835 René Nussbaumer
38 0d2bf835 René Nussbaumer
39 0d2bf835 René Nussbaumer
class EnsureError(errors.GenericError):
40 0d2bf835 René Nussbaumer
  """Top-level error class related to this script.
41 0d2bf835 René Nussbaumer

42 0d2bf835 René Nussbaumer
  """
43 0d2bf835 René Nussbaumer
44 0d2bf835 René Nussbaumer
45 0d2bf835 René Nussbaumer
def EnsurePermission(path, mode, uid=-1, gid=-1, must_exist=True,
46 0d2bf835 René Nussbaumer
                     _chmod_fn=os.chmod, _chown_fn=os.chown):
47 0d2bf835 René Nussbaumer
  """Ensures that given path has given mode.
48 0d2bf835 René Nussbaumer

49 0d2bf835 René Nussbaumer
  @param path: The path to the file
50 0d2bf835 René Nussbaumer
  @param mode: The mode of the file
51 0d2bf835 René Nussbaumer
  @param uid: The uid of the owner of this file
52 0d2bf835 René Nussbaumer
  @param gid: The gid of the owner of this file
53 0d2bf835 René Nussbaumer
  @param must_exist: Specifies if non-existance of path will be an error
54 0d2bf835 René Nussbaumer
  @param _chmod_fn: chmod function to use (unittest only)
55 0d2bf835 René Nussbaumer
  @param _chown_fn: chown function to use (unittest only)
56 0d2bf835 René Nussbaumer

57 0d2bf835 René Nussbaumer
  """
58 0d2bf835 René Nussbaumer
  try:
59 0d2bf835 René Nussbaumer
    _chmod_fn(path, mode)
60 0d2bf835 René Nussbaumer
61 0d2bf835 René Nussbaumer
    if max(uid, gid) > -1:
62 0d2bf835 René Nussbaumer
      _chown_fn(path, uid, gid)
63 0d2bf835 René Nussbaumer
  except EnvironmentError, err:
64 0d2bf835 René Nussbaumer
    if err.errno == errno.ENOENT:
65 0d2bf835 René Nussbaumer
      if must_exist:
66 0d2bf835 René Nussbaumer
        raise EnsureError("Path %s does not exists, but should" % path)
67 0d2bf835 René Nussbaumer
    else:
68 0d2bf835 René Nussbaumer
      raise EnsureError("Error while changing permission on %s: %s" %
69 0d2bf835 René Nussbaumer
                        (path, err))
70 0d2bf835 René Nussbaumer
71 0d2bf835 René Nussbaumer
72 0d2bf835 René Nussbaumer
def EnsureDir(path, mode, uid, gid, _stat_fn=os.lstat, _mkdir_fn=os.mkdir,
73 0d2bf835 René Nussbaumer
              _ensure_fn=EnsurePermission):
74 0d2bf835 René Nussbaumer
  """Ensures that given path is a dir and has given mode, uid and gid set.
75 0d2bf835 René Nussbaumer

76 0d2bf835 René Nussbaumer
  @param path: The path to the file
77 0d2bf835 René Nussbaumer
  @param mode: The mode of the file
78 0d2bf835 René Nussbaumer
  @param uid: The uid of the owner of this file
79 0d2bf835 René Nussbaumer
  @param gid: The gid of the owner of this file
80 0d2bf835 René Nussbaumer
  @param _stat_fn: Stat function to use (unittest only)
81 0d2bf835 René Nussbaumer
  @param _mkdir_fn: mkdir function to use (unittest only)
82 0d2bf835 René Nussbaumer
  @param _ensure_fn: ensure function to use (unittest only)
83 0d2bf835 René Nussbaumer

84 0d2bf835 René Nussbaumer
  """
85 0d2bf835 René Nussbaumer
  try:
86 0d2bf835 René Nussbaumer
    # We don't want to follow symlinks
87 0d2bf835 René Nussbaumer
    st_mode = _stat_fn(path)[stat.ST_MODE]
88 0d2bf835 René Nussbaumer
89 0d2bf835 René Nussbaumer
    if not stat.S_ISDIR(st_mode):
90 0d2bf835 René Nussbaumer
      raise EnsureError("Path %s is expected to be a directory, but it's not" %
91 0d2bf835 René Nussbaumer
                        path)
92 0d2bf835 René Nussbaumer
  except EnvironmentError, err:
93 0d2bf835 René Nussbaumer
    if err.errno == errno.ENOENT:
94 0d2bf835 René Nussbaumer
      _mkdir_fn(path)
95 0d2bf835 René Nussbaumer
    else:
96 0d2bf835 René Nussbaumer
      raise EnsureError("Error while do a stat() on %s: %s" % (path, err))
97 0d2bf835 René Nussbaumer
98 0d2bf835 René Nussbaumer
  _ensure_fn(path, mode, uid=uid, gid=gid)
99 0d2bf835 René Nussbaumer
100 0d2bf835 René Nussbaumer
101 0d2bf835 René Nussbaumer
def RecursiveEnsure(path, uid, gid, dir_perm, file_perm):
102 0d2bf835 René Nussbaumer
  """Ensures permissions recursively down a directory.
103 0d2bf835 René Nussbaumer

104 0d2bf835 René Nussbaumer
  This functions walks the path and sets permissions accordingly.
105 0d2bf835 René Nussbaumer

106 0d2bf835 René Nussbaumer
  @param path: The absolute path to walk
107 0d2bf835 René Nussbaumer
  @param uid: The uid used as owner
108 0d2bf835 René Nussbaumer
  @param gid: The gid used as group
109 0d2bf835 René Nussbaumer
  @param dir_perm: The permission bits set for directories
110 0d2bf835 René Nussbaumer
  @param file_perm: The permission bits set for files
111 0d2bf835 René Nussbaumer

112 0d2bf835 René Nussbaumer
  """
113 0d2bf835 René Nussbaumer
  assert os.path.isabs(path), "Path %s is not absolute" % path
114 0d2bf835 René Nussbaumer
  assert os.path.isdir(path), "Path %s is not a dir" % path
115 0d2bf835 René Nussbaumer
116 0d2bf835 René Nussbaumer
  for root, dirs, files in os.walk(path):
117 0d2bf835 René Nussbaumer
    for subdir in dirs:
118 0d2bf835 René Nussbaumer
      EnsurePermission(os.path.join(root, subdir), dir_perm, uid=uid, gid=gid)
119 0d2bf835 René Nussbaumer
120 0d2bf835 René Nussbaumer
    for filename in files:
121 0d2bf835 René Nussbaumer
      EnsurePermission(os.path.join(root, filename), file_perm, uid=uid,
122 0d2bf835 René Nussbaumer
                       gid=gid)
123 0d2bf835 René Nussbaumer
124 0d2bf835 René Nussbaumer
125 0d2bf835 René Nussbaumer
def ProcessPath(path):
126 0d2bf835 René Nussbaumer
  """Processes a path component.
127 0d2bf835 René Nussbaumer

128 0d2bf835 René Nussbaumer
  @param path: A tuple of the path component to process
129 0d2bf835 René Nussbaumer

130 0d2bf835 René Nussbaumer
  """
131 0d2bf835 René Nussbaumer
  (pathname, pathtype, mode, uid, gid) = path[0:5]
132 0d2bf835 René Nussbaumer
133 0d2bf835 René Nussbaumer
  assert pathtype in ALL_TYPES
134 0d2bf835 René Nussbaumer
135 0d2bf835 René Nussbaumer
  if pathtype == DIR:
136 0d2bf835 René Nussbaumer
    # No additional parameters
137 0d2bf835 René Nussbaumer
    assert len(path[5:]) == 0
138 0d2bf835 René Nussbaumer
    EnsureDir(pathname, mode, uid, gid)
139 0d2bf835 René Nussbaumer
  elif pathtype == FILE:
140 0d2bf835 René Nussbaumer
    (must_exist, ) = path[5:]
141 0d2bf835 René Nussbaumer
    EnsurePermission(pathname, mode, uid=uid, gid=gid, must_exist=must_exist)
142 0d2bf835 René Nussbaumer
143 0d2bf835 René Nussbaumer
144 0d2bf835 René Nussbaumer
def GetPaths():
145 0d2bf835 René Nussbaumer
  """Returns a tuple of path objects to process.
146 0d2bf835 René Nussbaumer

147 0d2bf835 René Nussbaumer
  """
148 0d2bf835 René Nussbaumer
  getent = runtime.GetEnts()
149 0d2bf835 René Nussbaumer
  masterd_log = constants.DAEMONS_LOGFILES[constants.MASTERD]
150 0d2bf835 René Nussbaumer
  noded_log = constants.DAEMONS_LOGFILES[constants.NODED]
151 0d2bf835 René Nussbaumer
  confd_log = constants.DAEMONS_LOGFILES[constants.CONFD]
152 0d2bf835 René Nussbaumer
  rapi_log = constants.DAEMONS_LOGFILES[constants.RAPI]
153 0d2bf835 René Nussbaumer
154 0d2bf835 René Nussbaumer
  rapi_dir = os.path.join(constants.DATA_DIR, "rapi")
155 0d2bf835 René Nussbaumer
156 0d2bf835 René Nussbaumer
  paths = [
157 0d2bf835 René Nussbaumer
    (constants.DATA_DIR, DIR, 0755, getent.masterd_uid,
158 0d2bf835 René Nussbaumer
     getent.masterd_gid),
159 0d2bf835 René Nussbaumer
    (constants.CLUSTER_DOMAIN_SECRET_FILE, FILE, 0640,
160 0d2bf835 René Nussbaumer
     getent.masterd_uid, getent.masterd_gid, False),
161 0d2bf835 René Nussbaumer
    (constants.CLUSTER_CONF_FILE, FILE, 0640, getent.masterd_uid,
162 0d2bf835 René Nussbaumer
     getent.confd_gid, False),
163 0d2bf835 René Nussbaumer
    (constants.CONFD_HMAC_KEY, FILE, 0440, getent.confd_uid,
164 0d2bf835 René Nussbaumer
     getent.masterd_gid, False),
165 0d2bf835 René Nussbaumer
    (constants.SSH_KNOWN_HOSTS_FILE, FILE, 0644, getent.masterd_uid,
166 0d2bf835 René Nussbaumer
     getent.masterd_gid, False),
167 0d2bf835 René Nussbaumer
    (constants.RAPI_CERT_FILE, FILE, 0440, getent.rapi_uid,
168 0d2bf835 René Nussbaumer
     getent.masterd_gid, False),
169 0d2bf835 René Nussbaumer
    (constants.NODED_CERT_FILE, FILE, 0440, getent.masterd_uid,
170 0d2bf835 René Nussbaumer
     getent.masterd_gid, False),
171 0d2bf835 René Nussbaumer
    ]
172 0d2bf835 René Nussbaumer
173 0d2bf835 René Nussbaumer
  ss = ssconf.SimpleStore()
174 0d2bf835 René Nussbaumer
  for ss_path in ss.GetFileList():
175 0d2bf835 René Nussbaumer
    paths.append((ss_path, FILE, 0400, getent.noded_uid, 0, False))
176 0d2bf835 René Nussbaumer
177 0d2bf835 René Nussbaumer
  paths.extend([
178 0d2bf835 René Nussbaumer
    (constants.QUEUE_DIR, DIR, 0700, getent.masterd_uid,
179 0d2bf835 René Nussbaumer
     getent.masterd_gid),
180 0d2bf835 René Nussbaumer
    (constants.JOB_QUEUE_SERIAL_FILE, FILE, 0600,
181 0d2bf835 René Nussbaumer
     getent.masterd_uid, getent.masterd_gid, False),
182 0d2bf835 René Nussbaumer
    (constants.JOB_QUEUE_ARCHIVE_DIR, DIR, 0700,
183 0d2bf835 René Nussbaumer
     getent.masterd_uid, getent.masterd_gid),
184 0d2bf835 René Nussbaumer
    (rapi_dir, DIR, 0750, getent.rapi_uid, getent.masterd_gid),
185 0d2bf835 René Nussbaumer
    (constants.RAPI_USERS_FILE, FILE, 0640, getent.rapi_uid,
186 0d2bf835 René Nussbaumer
     getent.masterd_gid, False),
187 0d2bf835 René Nussbaumer
    (constants.RUN_GANETI_DIR, DIR, 0775, getent.masterd_uid,
188 0d2bf835 René Nussbaumer
     getent.daemons_gid),
189 0d2bf835 René Nussbaumer
    (constants.SOCKET_DIR, DIR, 0750, getent.masterd_uid,
190 0d2bf835 René Nussbaumer
     getent.daemons_gid),
191 0d2bf835 René Nussbaumer
    (constants.MASTER_SOCKET, FILE, 0770, getent.masterd_uid,
192 0d2bf835 René Nussbaumer
     getent.daemons_gid, False),
193 0d2bf835 René Nussbaumer
    (constants.BDEV_CACHE_DIR, DIR, 0755, getent.noded_uid,
194 0d2bf835 René Nussbaumer
     getent.masterd_gid),
195 0d2bf835 René Nussbaumer
    (constants.UIDPOOL_LOCKDIR, DIR, 0750, getent.noded_uid,
196 0d2bf835 René Nussbaumer
     getent.masterd_gid),
197 0d2bf835 René Nussbaumer
    (constants.DISK_LINKS_DIR, DIR, 0755, getent.noded_uid,
198 0d2bf835 René Nussbaumer
     getent.masterd_gid),
199 0d2bf835 René Nussbaumer
    (constants.CRYPTO_KEYS_DIR, DIR, 0700, getent.noded_uid,
200 0d2bf835 René Nussbaumer
     getent.masterd_gid),
201 0d2bf835 René Nussbaumer
    (constants.IMPORT_EXPORT_DIR, DIR, 0755, getent.noded_uid,
202 0d2bf835 René Nussbaumer
     getent.masterd_gid),
203 0d2bf835 René Nussbaumer
    (constants.LOG_DIR, DIR, 0770, getent.masterd_uid,
204 0d2bf835 René Nussbaumer
     getent.daemons_gid),
205 0d2bf835 René Nussbaumer
    (masterd_log, FILE, 0600, getent.masterd_uid, getent.masterd_gid,
206 0d2bf835 René Nussbaumer
     False),
207 0d2bf835 René Nussbaumer
    (confd_log, FILE, 0600, getent.confd_uid, getent.masterd_gid, False),
208 0d2bf835 René Nussbaumer
    (noded_log, FILE, 0600, getent.noded_uid, getent.masterd_gid, False),
209 0d2bf835 René Nussbaumer
    (rapi_log, FILE, 0600, getent.rapi_uid, getent.masterd_gid, False),
210 0d2bf835 René Nussbaumer
    (constants.LOG_OS_DIR, DIR, 0750, getent.masterd_uid,
211 0d2bf835 René Nussbaumer
     getent.daemons_gid),
212 0d2bf835 René Nussbaumer
    ])
213 0d2bf835 René Nussbaumer
214 0d2bf835 René Nussbaumer
  return tuple(paths)
215 0d2bf835 René Nussbaumer
216 0d2bf835 René Nussbaumer
217 0d2bf835 René Nussbaumer
def ParseOptions():
218 0d2bf835 René Nussbaumer
  """Parses the options passed to the program.
219 0d2bf835 René Nussbaumer

220 0d2bf835 René Nussbaumer
  @return: Options and arguments
221 0d2bf835 René Nussbaumer

222 0d2bf835 René Nussbaumer
  """
223 0d2bf835 René Nussbaumer
  program = os.path.basename(sys.argv[0])
224 0d2bf835 René Nussbaumer
225 0d2bf835 René Nussbaumer
  parser = optparse.OptionParser(usage="%%prog [--full-run]",
226 0d2bf835 René Nussbaumer
                                 prog=program)
227 0d2bf835 René Nussbaumer
  parser.add_option("--full-run", "-f", dest="full_run", action="store_true",
228 0d2bf835 René Nussbaumer
                    default=False, help=("Make a full run and collect"
229 0d2bf835 René Nussbaumer
                                         " additional files (time consuming)"))
230 0d2bf835 René Nussbaumer
231 0d2bf835 René Nussbaumer
  return parser.parse_args()
232 0d2bf835 René Nussbaumer
233 0d2bf835 René Nussbaumer
234 0d2bf835 René Nussbaumer
def Main():
235 0d2bf835 René Nussbaumer
  """Main routine.
236 0d2bf835 René Nussbaumer

237 0d2bf835 René Nussbaumer
  """
238 0d2bf835 René Nussbaumer
  getent = runtime.GetEnts()
239 0d2bf835 René Nussbaumer
  (opts, _) = ParseOptions()
240 0d2bf835 René Nussbaumer
241 0d2bf835 René Nussbaumer
  try:
242 0d2bf835 René Nussbaumer
    for path in GetPaths():
243 0d2bf835 René Nussbaumer
      ProcessPath(path)
244 0d2bf835 René Nussbaumer
245 0d2bf835 René Nussbaumer
    if opts.full_run:
246 0d2bf835 René Nussbaumer
      RecursiveEnsure(constants.JOB_QUEUE_ARCHIVE_DIR, getent.masterd_uid,
247 0d2bf835 René Nussbaumer
                      getent.masterd_gid, 0700, 0600)
248 0d2bf835 René Nussbaumer
  except EnsureError, err:
249 0d2bf835 René Nussbaumer
    print >> sys.stderr, "An error occurred while ensure permissions:", err
250 0d2bf835 René Nussbaumer
    return constants.EXIT_FAILURE
251 0d2bf835 René Nussbaumer
252 0d2bf835 René Nussbaumer
  return constants.EXIT_SUCCESS