ensure_dirs.py 8.77 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
from ganeti import compat
39
40


41
42
43
44
(DIR,
 FILE,
 QUEUE_DIR) = range(1, 4)

45
ALL_TYPES = compat.UniqueFrozenset([
46
47
48
49
  DIR,
  FILE,
  QUEUE_DIR,
  ])
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66


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

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

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

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


79
80
81
82
83
84
85
86
87
88
89
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):
90
91
      utils.EnforcePermission(utils.PathJoin(path, filename), mode, uid=uid,
                              gid=gid)
92
93


94
95
96
97
98
99
100
101
102
103
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

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


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

  """
  getent = runtime.GetEnts()
122
123
124
125
  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]
126

127
  rapi_dir = os.path.join(pathutils.DATA_DIR, "rapi")
128
129
  cleaner_log_dir = os.path.join(pathutils.LOG_DIR, "cleaner")
  master_cleaner_log_dir = os.path.join(pathutils.LOG_DIR, "master-cleaner")
130

131
132
133
  # A note on the ordering: The parent directory (type C{DIR}) must always be
  # listed before files (type C{FILE}) in that directory. Once the directory is
  # set, only files directly in that directory can be listed.
134
  paths = [
135
    (pathutils.DATA_DIR, DIR, 0755, getent.masterd_uid, getent.masterd_gid),
136
    (pathutils.CLUSTER_DOMAIN_SECRET_FILE, FILE, 0640,
137
     getent.masterd_uid, getent.masterd_gid, False),
138
139
140
141
142
143
144
145
146
147
148
149
    (pathutils.CLUSTER_CONF_FILE, FILE, 0640,
     getent.masterd_uid, getent.confd_gid, False),
    (pathutils.CONFD_HMAC_KEY, FILE, 0440,
     getent.confd_uid, getent.masterd_gid, False),
    (pathutils.SSH_KNOWN_HOSTS_FILE, FILE, 0644,
     getent.masterd_uid, getent.masterd_gid, False),
    (pathutils.RAPI_CERT_FILE, FILE, 0440,
     getent.rapi_uid, getent.masterd_gid, False),
    (pathutils.SPICE_CERT_FILE, FILE, 0440,
     getent.noded_uid, getent.masterd_gid, False),
    (pathutils.SPICE_CACERT_FILE, FILE, 0440,
     getent.noded_uid, getent.masterd_gid, False),
150
151
    (pathutils.NODED_CERT_FILE, FILE, pathutils.NODED_CERT_MODE,
     getent.masterd_uid, getent.masterd_gid, False),
152
153
    (pathutils.WATCHER_PAUSEFILE, FILE, 0644,
     getent.masterd_uid, getent.masterd_gid, False),
154
155
156
157
    ]

  ss = ssconf.SimpleStore()
  for ss_path in ss.GetFileList():
158
    paths.append((ss_path, FILE, constants.SS_FILE_PERMS,
159
                  getent.noded_uid, getent.noded_gid, False))
160
161

  paths.extend([
162
163
164
    (pathutils.QUEUE_DIR, DIR, 0750, getent.masterd_uid, getent.daemons_gid),
    (pathutils.QUEUE_DIR, QUEUE_DIR, constants.JOB_QUEUE_FILES_PERMS,
     getent.masterd_uid, getent.daemons_gid),
165
    (pathutils.JOB_QUEUE_DRAIN_FILE, FILE, 0644,
166
167
168
169
170
171
172
     getent.masterd_uid, getent.daemons_gid, False),
    (pathutils.JOB_QUEUE_LOCK_FILE, FILE, constants.JOB_QUEUE_FILES_PERMS,
     getent.masterd_uid, getent.daemons_gid, False),
    (pathutils.JOB_QUEUE_SERIAL_FILE, FILE, constants.JOB_QUEUE_FILES_PERMS,
     getent.masterd_uid, getent.daemons_gid, False),
    (pathutils.JOB_QUEUE_VERSION_FILE, FILE, constants.JOB_QUEUE_FILES_PERMS,
     getent.masterd_uid, getent.daemons_gid, False),
173
    (pathutils.JOB_QUEUE_ARCHIVE_DIR, DIR, 0750,
174
     getent.masterd_uid, getent.daemons_gid),
175
    (rapi_dir, DIR, 0750, getent.rapi_uid, getent.masterd_gid),
176
177
178
179
180
181
    (pathutils.RAPI_USERS_FILE, FILE, 0640,
     getent.rapi_uid, getent.masterd_gid, False),
    (pathutils.RUN_DIR, DIR, 0775, getent.masterd_uid, getent.daemons_gid),
    (pathutils.SOCKET_DIR, DIR, 0770, getent.masterd_uid, getent.daemons_gid),
    (pathutils.MASTER_SOCKET, FILE, 0660,
     getent.masterd_uid, getent.daemons_gid, False),
182
    (pathutils.QUERY_SOCKET, FILE, 0660,
183
     getent.queryd_uid, getent.daemons_gid, False),
184
185
186
187
188
189
190
191
192
193
194
195
    (pathutils.BDEV_CACHE_DIR, DIR, 0755,
     getent.noded_uid, getent.masterd_gid),
    (pathutils.UIDPOOL_LOCKDIR, DIR, 0750,
     getent.noded_uid, getent.masterd_gid),
    (pathutils.DISK_LINKS_DIR, DIR, 0755,
     getent.noded_uid, getent.masterd_gid),
    (pathutils.CRYPTO_KEYS_DIR, DIR, 0700,
     getent.noded_uid, getent.masterd_gid),
    (pathutils.IMPORT_EXPORT_DIR, DIR, 0755,
     getent.noded_uid, getent.masterd_gid),
    (pathutils.LOG_DIR, DIR, 0770, getent.masterd_uid, getent.daemons_gid),
    (masterd_log, FILE, 0600, getent.masterd_uid, getent.masterd_gid, False),
196
197
198
    (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),
Balazs Lecz's avatar
Balazs Lecz committed
199
    (pathutils.LOG_OS_DIR, DIR, 0750, getent.noded_uid, getent.daemons_gid),
200
    (pathutils.LOG_XEN_DIR, DIR, 0750, getent.noded_uid, getent.daemons_gid),
201
202
    (cleaner_log_dir, DIR, 0750, getent.noded_uid, getent.noded_gid),
    (master_cleaner_log_dir, DIR, 0750, getent.masterd_uid, getent.masterd_gid),
203
204
    (pathutils.INSTANCE_REASON_DIR, DIR, 0755, getent.noded_uid,
     getent.noded_gid),
205
206
    ])

207
  return paths
208
209
210
211
212
213
214
215
216
217


def ParseOptions():
  """Parses the options passed to the program.

  @return: Options and arguments

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

218
  parser = optparse.OptionParser(usage="%prog [--full-run]",
219
                                 prog=program)
220
221
  parser.add_option(cli.DEBUG_OPT)
  parser.add_option(cli.VERBOSE_OPT)
222
  parser.add_option("--full-run", "-f", dest="full_run", action="store_true",
223
224
                    default=False, help=("Make a full run and set permissions"
                                         " on archived jobs (time consuming)"))
225
226
227
228
229
230
231
232

  return parser.parse_args()


def Main():
  """Main routine.

  """
233
  (opts, args) = ParseOptions()
234

235
  utils.SetupToolLogging(opts.debug, opts.verbose)
236

237
238
239
240
  if args:
    logging.error("No arguments are expected")
    return constants.EXIT_FAILURE

241
242
243
244
245
  if opts.full_run:
    logging.info("Running in full mode")

  getent = runtime.GetEnts()

246
247
248
249
250
  try:
    for path in GetPaths():
      ProcessPath(path)

    if opts.full_run:
251
      RecursiveEnsure(pathutils.JOB_QUEUE_ARCHIVE_DIR, getent.masterd_uid,
252
                      getent.daemons_gid, 0750, constants.JOB_QUEUE_FILES_PERMS)
253
  except errors.GenericError, err:
254
    logging.error("An error occurred while setting permissions: %s", err)
255
256
257
    return constants.EXIT_FAILURE

  return constants.EXIT_SUCCESS