Statistics
| Branch: | Tag: | Revision:

root / lib / tools / ensure_dirs.py @ b81b3c96

History | View | Annotate | Download (7.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.NODED_CERT_FILE, FILE, 0440, getent.masterd_uid,
141
     getent.masterd_gid, False),
142
    ]
143

    
144
  ss = ssconf.SimpleStore()
145
  for ss_path in ss.GetFileList():
146
    paths.append((ss_path, FILE, constants.SS_FILE_PERMS,
147
                  getent.noded_uid, 0, False))
148

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

    
192
  return tuple(paths)
193

    
194

    
195
def SetupLogging(opts):
196
  """Configures the logging module.
197

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

    
201
  stderr_handler = logging.StreamHandler()
202
  stderr_handler.setFormatter(formatter)
203
  if opts.debug:
204
    stderr_handler.setLevel(logging.NOTSET)
205
  elif opts.verbose:
206
    stderr_handler.setLevel(logging.INFO)
207
  else:
208
    stderr_handler.setLevel(logging.WARNING)
209

    
210
  root_logger = logging.getLogger("")
211
  root_logger.setLevel(logging.NOTSET)
212
  root_logger.addHandler(stderr_handler)
213

    
214

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

218
  @return: Options and arguments
219

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

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

    
231
  return parser.parse_args()
232

    
233

    
234
def Main():
235
  """Main routine.
236

237
  """
238
  (opts, _) = ParseOptions()
239

    
240
  SetupLogging(opts)
241

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

    
245
  getent = runtime.GetEnts()
246

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

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

    
258
  return constants.EXIT_SUCCESS