Statistics
| Branch: | Tag: | Revision:

root / lib / tools / ensure_dirs.py @ 8d77ac10

History | View | Annotate | Download (8 kB)

1
#
2
#
3

    
4
# Copyright (C) 2011 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
"""Script to ensure permissions on files/dirs are accurate.
22

23
"""
24

    
25
import os
26
import os.path
27
import optparse
28
import sys
29
import logging
30

    
31
from ganeti import constants
32
from ganeti import errors
33
from ganeti import runtime
34
from ganeti import ssconf
35
from ganeti import utils
36
from ganeti import cli
37

    
38

    
39
(DIR,
40
 FILE,
41
 QUEUE_DIR) = range(1, 4)
42

    
43
ALL_TYPES = frozenset([
44
  DIR,
45
  FILE,
46
  QUEUE_DIR,
47
  ])
48

    
49

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

53
  This functions walks the path and sets permissions accordingly.
54

55
  @param path: The absolute path to walk
56
  @param uid: The uid used as owner
57
  @param gid: The gid used as group
58
  @param dir_perm: The permission bits set for directories
59
  @param file_perm: The permission bits set for files
60

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

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

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

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

    
76

    
77
def EnsureQueueDir(path, mode, uid, gid):
78
  """Sets the correct permissions on all job files in the queue.
79

80
  @param path: Directory path
81
  @param mode: Wanted file mode
82
  @param uid: Wanted user ID
83
  @param gid: Wanted group ID
84

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

    
91

    
92
def ProcessPath(path):
93
  """Processes a path component.
94

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

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

    
100
  assert pathtype in ALL_TYPES
101

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

    
114

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

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

    
125
  rapi_dir = os.path.join(constants.DATA_DIR, "rapi")
126

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

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

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

    
196
  return tuple(paths)
197

    
198

    
199
def SetupLogging(opts):
200
  """Configures the logging module.
201

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

    
205
  stderr_handler = logging.StreamHandler()
206
  stderr_handler.setFormatter(formatter)
207
  if opts.debug:
208
    stderr_handler.setLevel(logging.NOTSET)
209
  elif opts.verbose:
210
    stderr_handler.setLevel(logging.INFO)
211
  else:
212
    stderr_handler.setLevel(logging.WARNING)
213

    
214
  root_logger = logging.getLogger("")
215
  root_logger.setLevel(logging.NOTSET)
216
  root_logger.addHandler(stderr_handler)
217

    
218

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

222
  @return: Options and arguments
223

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

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

    
235
  return parser.parse_args()
236

    
237

    
238
def Main():
239
  """Main routine.
240

241
  """
242
  (opts, _) = ParseOptions()
243

    
244
  SetupLogging(opts)
245

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

    
249
  getent = runtime.GetEnts()
250

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

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

    
262
  return constants.EXIT_SUCCESS