| # |
| # |
| |
| # Copyright (C) 2011 Google Inc. |
| # All rights reserved. |
| # |
| # Redistribution and use in source and binary forms, with or without |
| # modification, are permitted provided that the following conditions are |
| # met: |
| # |
| # 1. Redistributions of source code must retain the above copyright notice, |
| # this list of conditions and the following disclaimer. |
| # |
| # 2. Redistributions in binary form must reproduce the above copyright |
| # notice, this list of conditions and the following disclaimer in the |
| # documentation and/or other materials provided with the distribution. |
| # |
| # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS |
| # IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
| # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR |
| # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
| # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
| # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| |
| """Script to ensure permissions on files/dirs are accurate. |
| |
| """ |
| |
| import os |
| import os.path |
| import optparse |
| import sys |
| import logging |
| |
| from ganeti import constants |
| from ganeti import errors |
| from ganeti import runtime |
| from ganeti import ssconf |
| from ganeti import utils |
| from ganeti import cli |
| from ganeti import pathutils |
| from ganeti import compat |
| |
| |
| (DIR, |
| FILE, |
| QUEUE_DIR) = range(1, 4) |
| |
| ALL_TYPES = compat.UniqueFrozenset([ |
| DIR, |
| FILE, |
| QUEUE_DIR, |
| ]) |
| |
| |
| 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 |
| |
| logging.debug("Recursively processing %s", path) |
| |
| for root, dirs, files in os.walk(path): |
| for subdir in dirs: |
| utils.EnforcePermission(os.path.join(root, subdir), dir_perm, uid=uid, |
| gid=gid) |
| |
| for filename in files: |
| utils.EnforcePermission(os.path.join(root, filename), file_perm, uid=uid, |
| gid=gid) |
| |
| |
| 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): |
| utils.EnforcePermission(utils.PathJoin(path, filename), mode, uid=uid, |
| gid=gid) |
| |
| |
| 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 |
| |
| if pathtype in (DIR, QUEUE_DIR): |
| # No additional parameters |
| assert len(path) == 5 |
| if pathtype == DIR: |
| utils.MakeDirWithPerm(pathname, mode, uid, gid) |
| elif pathtype == QUEUE_DIR: |
| EnsureQueueDir(pathname, mode, uid, gid) |
| elif pathtype == FILE: |
| (must_exist, ) = path[5:] |
| utils.EnforcePermission(pathname, mode, uid=uid, gid=gid, |
| must_exist=must_exist) |
| |
| |
| def GetPaths(): |
| """Returns a tuple of path objects to process. |
| |
| """ |
| getent = runtime.GetEnts() |
| masterd_log = constants.DAEMONS_LOGFILES[constants.MASTERD] |
| noded_log = constants.DAEMONS_LOGFILES[constants.NODED] |
| confd_log = constants.DAEMONS_LOGFILES[constants.CONFD] |
| luxid_log = constants.DAEMONS_LOGFILES[constants.LUXID] |
| rapi_log = constants.DAEMONS_LOGFILES[constants.RAPI] |
| mond_log = constants.DAEMONS_LOGFILES[constants.MOND] |
| |
| rapi_dir = os.path.join(pathutils.DATA_DIR, "rapi") |
| cleaner_log_dir = os.path.join(pathutils.LOG_DIR, "cleaner") |
| master_cleaner_log_dir = os.path.join(pathutils.LOG_DIR, "master-cleaner") |
| |
| # 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. |
| paths = [ |
| (pathutils.DATA_DIR, DIR, 0755, getent.masterd_uid, getent.masterd_gid), |
| (pathutils.CLUSTER_DOMAIN_SECRET_FILE, FILE, 0640, |
| getent.masterd_uid, getent.masterd_gid, False), |
| (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), |
| (pathutils.NODED_CERT_FILE, FILE, pathutils.NODED_CERT_MODE, |
| getent.masterd_uid, getent.masterd_gid, False), |
| (pathutils.NODED_CLIENT_CERT_FILE, FILE, pathutils.NODED_CERT_MODE, |
| getent.masterd_uid, getent.masterd_gid, False), |
| (pathutils.WATCHER_PAUSEFILE, FILE, 0644, |
| getent.masterd_uid, getent.masterd_gid, False), |
| ] |
| |
| ss = ssconf.SimpleStore() |
| for ss_path in ss.GetFileList(): |
| paths.append((ss_path, FILE, constants.SS_FILE_PERMS, |
| getent.noded_uid, getent.noded_gid, False)) |
| |
| paths.extend([ |
| (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), |
| (pathutils.JOB_QUEUE_DRAIN_FILE, FILE, 0644, |
| 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), |
| (pathutils.JOB_QUEUE_ARCHIVE_DIR, DIR, 0750, |
| getent.masterd_uid, getent.daemons_gid), |
| (rapi_dir, DIR, 0750, getent.rapi_uid, getent.masterd_gid), |
| (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), |
| (pathutils.QUERY_SOCKET, FILE, 0660, |
| getent.luxid_uid, getent.daemons_gid, False), |
| (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), |
| (confd_log, FILE, 0600, getent.confd_uid, getent.masterd_gid, False), |
| (luxid_log, FILE, 0600, getent.luxid_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), |
| (mond_log, FILE, 0600, getent.mond_uid, getent.masterd_gid, False), |
| (pathutils.LOG_OS_DIR, DIR, 0750, getent.noded_uid, getent.daemons_gid), |
| (pathutils.LOG_XEN_DIR, DIR, 0750, getent.noded_uid, getent.daemons_gid), |
| (cleaner_log_dir, DIR, 0750, getent.noded_uid, getent.noded_gid), |
| (master_cleaner_log_dir, DIR, 0750, getent.masterd_uid, getent.masterd_gid), |
| (pathutils.INSTANCE_REASON_DIR, DIR, 0755, getent.noded_uid, |
| getent.noded_gid), |
| (pathutils.LIVELOCK_DIR, DIR, 0750, getent.masterd_uid, getent.daemons_gid), |
| (pathutils.LUXID_MESSAGE_DIR, DIR, 0750, getent.masterd_uid, |
| getent.daemons_gid), |
| ]) |
| |
| return paths |
| |
| |
| def ParseOptions(): |
| """Parses the options passed to the program. |
| |
| @return: Options and arguments |
| |
| """ |
| program = os.path.basename(sys.argv[0]) |
| |
| parser = optparse.OptionParser(usage="%prog [--full-run]", |
| prog=program) |
| parser.add_option(cli.DEBUG_OPT) |
| parser.add_option(cli.VERBOSE_OPT) |
| parser.add_option("--full-run", "-f", dest="full_run", action="store_true", |
| default=False, help=("Make a full run and set permissions" |
| " on archived jobs (time consuming)")) |
| |
| return parser.parse_args() |
| |
| |
| def Main(): |
| """Main routine. |
| |
| """ |
| (opts, args) = ParseOptions() |
| |
| utils.SetupToolLogging( |
| opts.debug, opts.verbose, |
| toolname=os.path.splitext(os.path.basename(__file__))[0]) |
| |
| if args: |
| logging.error("No arguments are expected") |
| return constants.EXIT_FAILURE |
| |
| if opts.full_run: |
| logging.info("Running in full mode") |
| |
| getent = runtime.GetEnts() |
| |
| try: |
| for path in GetPaths(): |
| ProcessPath(path) |
| |
| if opts.full_run: |
| RecursiveEnsure(pathutils.JOB_QUEUE_ARCHIVE_DIR, getent.masterd_uid, |
| getent.daemons_gid, 0750, constants.JOB_QUEUE_FILES_PERMS) |
| except errors.GenericError, err: |
| logging.error("An error occurred while setting permissions: %s", err) |
| return constants.EXIT_FAILURE |
| |
| return constants.EXIT_SUCCESS |