Statistics
| Branch: | Tag: | Revision:

root / lib / tools / ensure_dirs.py @ 9eac61f8

History | View | Annotate | Download (8.1 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
from ganeti import pathutils
38

    
39

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

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

    
50

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

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

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

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

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

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

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

    
77

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

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

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

    
92

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

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

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

    
101
  assert pathtype in ALL_TYPES
102

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

    
115

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

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

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

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

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

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

    
198
  return paths
199

    
200

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

204
  @return: Options and arguments
205

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

    
209
  parser = optparse.OptionParser(usage="%prog [--full-run]",
210
                                 prog=program)
211
  parser.add_option(cli.DEBUG_OPT)
212
  parser.add_option(cli.VERBOSE_OPT)
213
  parser.add_option("--full-run", "-f", dest="full_run", action="store_true",
214
                    default=False, help=("Make a full run and set permissions"
215
                                         " on archived jobs (time consuming)"))
216

    
217
  return parser.parse_args()
218

    
219

    
220
def Main():
221
  """Main routine.
222

223
  """
224
  (opts, args) = ParseOptions()
225

    
226
  utils.SetupToolLogging(opts.debug, opts.verbose)
227

    
228
  if args:
229
    logging.error("No arguments are expected")
230
    return constants.EXIT_FAILURE
231

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

    
235
  getent = runtime.GetEnts()
236

    
237
  try:
238
    for path in GetPaths():
239
      ProcessPath(path)
240

    
241
    if opts.full_run:
242
      RecursiveEnsure(pathutils.JOB_QUEUE_ARCHIVE_DIR, getent.masterd_uid,
243
                      getent.masterd_gid, 0700, 0600)
244
  except errors.GenericError, err:
245
    logging.error("An error occurred while setting permissions: %s", err)
246
    return constants.EXIT_FAILURE
247

    
248
  return constants.EXIT_SUCCESS