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
|