ensure_dirs.py 8.03 KB
Newer Older
1
2
3
#
#

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

"""Script to ensure permissions on files/dirs are accurate.

"""

import os
import os.path
import optparse
import sys
29
import logging
30
31
32
33
34

from ganeti import constants
from ganeti import errors
from ganeti import runtime
from ganeti import ssconf
35
from ganeti import utils
36
from ganeti import cli
37
from ganeti import pathutils
38
39


40
41
42
43
44
45
46
47
48
(DIR,
 FILE,
 QUEUE_DIR) = range(1, 4)

ALL_TYPES = frozenset([
  DIR,
  FILE,
  QUEUE_DIR,
  ])
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65


def RecursiveEnsure(path, uid, gid, dir_perm, file_perm):
  """Ensures permissions recursively down a directory.

  This functions walks the path and sets permissions accordingly.

  @param path: The absolute path to walk
  @param uid: The uid used as owner
  @param gid: The gid used as group
  @param dir_perm: The permission bits set for directories
  @param file_perm: The permission bits set for files

  """
  assert os.path.isabs(path), "Path %s is not absolute" % path
  assert os.path.isdir(path), "Path %s is not a dir" % path

66
67
  logging.debug("Recursively processing %s", path)

68
69
  for root, dirs, files in os.walk(path):
    for subdir in dirs:
70
71
      utils.EnforcePermission(os.path.join(root, subdir), dir_perm, uid=uid,
                              gid=gid)
72
73

    for filename in files:
74
75
      utils.EnforcePermission(os.path.join(root, filename), file_perm, uid=uid,
                              gid=gid)
76
77


78
79
80
81
82
83
84
85
86
87
88
def EnsureQueueDir(path, mode, uid, gid):
  """Sets the correct permissions on all job files in the queue.

  @param path: Directory path
  @param mode: Wanted file mode
  @param uid: Wanted user ID
  @param gid: Wanted group ID

  """
  for filename in utils.ListVisibleFiles(path):
    if constants.JOB_FILE_RE.match(filename):
89
90
      utils.EnforcePermission(utils.PathJoin(path, filename), mode, uid=uid,
                              gid=gid)
91
92


93
94
95
96
97
98
99
100
101
102
def ProcessPath(path):
  """Processes a path component.

  @param path: A tuple of the path component to process

  """
  (pathname, pathtype, mode, uid, gid) = path[0:5]

  assert pathtype in ALL_TYPES

103
  if pathtype in (DIR, QUEUE_DIR):
104
105
    # No additional parameters
    assert len(path[5:]) == 0
106
    if pathtype == DIR:
107
      utils.MakeDirWithPerm(pathname, mode, uid, gid)
108
109
    elif pathtype == QUEUE_DIR:
      EnsureQueueDir(pathname, mode, uid, gid)
110
111
  elif pathtype == FILE:
    (must_exist, ) = path[5:]
112
113
    utils.EnforcePermission(pathname, mode, uid=uid, gid=gid,
                            must_exist=must_exist)
114
115
116
117
118
119
120


def GetPaths():
  """Returns a tuple of path objects to process.

  """
  getent = runtime.GetEnts()
121
122
123
124
  masterd_log = constants.DAEMONS_LOGFILES[constants.MASTERD]
  noded_log = constants.DAEMONS_LOGFILES[constants.NODED]
  confd_log = constants.DAEMONS_LOGFILES[constants.CONFD]
  rapi_log = constants.DAEMONS_LOGFILES[constants.RAPI]
125

126
  rapi_dir = os.path.join(pathutils.DATA_DIR, "rapi")
127
128

  paths = [
129
    (pathutils.DATA_DIR, DIR, 0755, getent.masterd_uid,
130
     getent.masterd_gid),
131
    (pathutils.CLUSTER_DOMAIN_SECRET_FILE, FILE, 0640,
132
     getent.masterd_uid, getent.masterd_gid, False),
133
    (pathutils.CLUSTER_CONF_FILE, FILE, 0640, getent.masterd_uid,
134
     getent.confd_gid, False),
135
    (pathutils.CONFD_HMAC_KEY, FILE, 0440, getent.confd_uid,
136
     getent.masterd_gid, False),
137
    (pathutils.SSH_KNOWN_HOSTS_FILE, FILE, 0644, getent.masterd_uid,
138
     getent.masterd_gid, False),
139
    (pathutils.RAPI_CERT_FILE, FILE, 0440, getent.rapi_uid,
140
     getent.masterd_gid, False),
141
    (pathutils.SPICE_CERT_FILE, FILE, 0440, getent.noded_uid,
142
     getent.masterd_gid, False),
143
    (pathutils.SPICE_CACERT_FILE, FILE, 0440, getent.noded_uid,
144
     getent.masterd_gid, False),
145
    (pathutils.NODED_CERT_FILE, FILE, 0440, getent.masterd_uid,
146
147
148
149
150
     getent.masterd_gid, False),
    ]

  ss = ssconf.SimpleStore()
  for ss_path in ss.GetFileList():
151
152
    paths.append((ss_path, FILE, constants.SS_FILE_PERMS,
                  getent.noded_uid, 0, False))
153
154

  paths.extend([
155
    (pathutils.QUEUE_DIR, DIR, 0700, getent.masterd_uid,
156
     getent.masterd_gid),
157
    (pathutils.QUEUE_DIR, QUEUE_DIR, 0600, getent.masterd_uid,
158
     getent.masterd_gid),
159
    (pathutils.JOB_QUEUE_LOCK_FILE, FILE, 0600,
160
     getent.masterd_uid, getent.masterd_gid, False),
161
    (pathutils.JOB_QUEUE_SERIAL_FILE, FILE, 0600,
162
     getent.masterd_uid, getent.masterd_gid, False),
163
    (pathutils.JOB_QUEUE_VERSION_FILE, FILE, 0600,
164
     getent.masterd_uid, getent.masterd_gid, False),
165
    (pathutils.JOB_QUEUE_ARCHIVE_DIR, DIR, 0700,
166
167
     getent.masterd_uid, getent.masterd_gid),
    (rapi_dir, DIR, 0750, getent.rapi_uid, getent.masterd_gid),
168
    (pathutils.RAPI_USERS_FILE, FILE, 0640, getent.rapi_uid,
169
     getent.masterd_gid, False),
170
    (pathutils.RUN_DIR, DIR, 0775, getent.masterd_uid,
171
     getent.daemons_gid),
172
    (pathutils.SOCKET_DIR, DIR, 0750, getent.masterd_uid,
173
     getent.daemons_gid),
174
    (pathutils.MASTER_SOCKET, FILE, 0770, getent.masterd_uid,
175
     getent.daemons_gid, False),
176
    (pathutils.BDEV_CACHE_DIR, DIR, 0755, getent.noded_uid,
177
     getent.masterd_gid),
178
    (pathutils.UIDPOOL_LOCKDIR, DIR, 0750, getent.noded_uid,
179
     getent.masterd_gid),
180
    (pathutils.DISK_LINKS_DIR, DIR, 0755, getent.noded_uid,
181
     getent.masterd_gid),
182
    (pathutils.CRYPTO_KEYS_DIR, DIR, 0700, getent.noded_uid,
183
     getent.masterd_gid),
184
    (pathutils.IMPORT_EXPORT_DIR, DIR, 0755, getent.noded_uid,
185
     getent.masterd_gid),
186
    (pathutils.LOG_DIR, DIR, 0770, getent.masterd_uid,
187
188
189
190
191
192
     getent.daemons_gid),
    (masterd_log, FILE, 0600, getent.masterd_uid, getent.masterd_gid,
     False),
    (confd_log, FILE, 0600, getent.confd_uid, getent.masterd_gid, False),
    (noded_log, FILE, 0600, getent.noded_uid, getent.masterd_gid, False),
    (rapi_log, FILE, 0600, getent.rapi_uid, getent.masterd_gid, False),
193
    (pathutils.LOG_OS_DIR, DIR, 0750, getent.masterd_uid,
194
195
196
     getent.daemons_gid),
    ])

197
  return paths
198
199


200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
def SetupLogging(opts):
  """Configures the logging module.

  """
  formatter = logging.Formatter("%(asctime)s: %(message)s")

  stderr_handler = logging.StreamHandler()
  stderr_handler.setFormatter(formatter)
  if opts.debug:
    stderr_handler.setLevel(logging.NOTSET)
  elif opts.verbose:
    stderr_handler.setLevel(logging.INFO)
  else:
    stderr_handler.setLevel(logging.WARNING)

  root_logger = logging.getLogger("")
  root_logger.setLevel(logging.NOTSET)
  root_logger.addHandler(stderr_handler)


220
221
222
223
224
225
226
227
228
229
def ParseOptions():
  """Parses the options passed to the program.

  @return: Options and arguments

  """
  program = os.path.basename(sys.argv[0])

  parser = optparse.OptionParser(usage="%%prog [--full-run]",
                                 prog=program)
230
231
  parser.add_option(cli.DEBUG_OPT)
  parser.add_option(cli.VERBOSE_OPT)
232
  parser.add_option("--full-run", "-f", dest="full_run", action="store_true",
233
234
                    default=False, help=("Make a full run and set permissions"
                                         " on archived jobs (time consuming)"))
235
236
237
238
239
240
241
242
243
244

  return parser.parse_args()


def Main():
  """Main routine.

  """
  (opts, _) = ParseOptions()

245
246
247
248
249
250
251
  SetupLogging(opts)

  if opts.full_run:
    logging.info("Running in full mode")

  getent = runtime.GetEnts()

252
253
254
255
256
  try:
    for path in GetPaths():
      ProcessPath(path)

    if opts.full_run:
257
      RecursiveEnsure(pathutils.JOB_QUEUE_ARCHIVE_DIR, getent.masterd_uid,
258
                      getent.masterd_gid, 0700, 0600)
259
  except errors.GenericError, err:
260
    logging.error("An error occurred while setting permissions: %s", err)
261
262
263
    return constants.EXIT_FAILURE

  return constants.EXIT_SUCCESS