# vim: tabstop=4 shiftwidth=4 softtabstop=4 # Copyright (C) 2012 Yahoo! Inc. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import re from devstack import colorizer from devstack import component as comp from devstack import log as logging from devstack import shell as sh from devstack import utils LOG = logging.getLogger("devstack.components.swift") # Swift has alot of config files! SWIFT_CONF = 'swift.conf' PROXY_SERVER_CONF = 'proxy-server.conf' ACCOUNT_SERVER_CONF = 'account-server.conf' CONTAINER_SERVER_CONF = 'container-server.conf' OBJECT_SERVER_CONF = 'object-server.conf' RSYNC_CONF = 'rsyncd.conf' SYSLOG_CONF = 'rsyslog.conf' SWIFT_MAKERINGS = 'swift-remakerings' SWIFT_STARTMAIN = 'swift-startmain' SWIFT_INIT = 'swift-init' SWIFT_IMG = 'drives/images/swift.img' DEVICE_PATH = 'drives/sdb1' CONFIGS = [SWIFT_CONF, PROXY_SERVER_CONF, ACCOUNT_SERVER_CONF, CONTAINER_SERVER_CONF, OBJECT_SERVER_CONF, RSYNC_CONF, SYSLOG_CONF, SWIFT_MAKERINGS, SWIFT_STARTMAIN] SWIFT_RSYNC_LOC = '/etc/rsyslog.d/10-swift.conf' DEF_LOOP_SIZE = 1000000 # Adjustments to rsync/rsyslog RSYNC_CONF_LOC = '/etc/default/rsync' RSYNCD_CONF_LOC = '/etc/rsyncd.conf' RSYNC_SERVICE_RESTART = ['service', 'rsync', 'restart'] RSYSLOG_SERVICE_RESTART = ['service', 'rsyslog', 'restart'] RSYNC_ON_OFF_RE = re.compile(r'^\s*RSYNC_ENABLE\s*=\s*(.*)$', re.I) # FIXME: This should come from the persona, if we really expect # people to change it. # Defines our auth service type AUTH_SERVICE = 'keystone' # Defines what type of loopback filesystem we will make # xfs is preferred due to its extended attributes FS_TYPE = "xfs" # Subdirs of the git checkout BIN_DIR = 'bin' LOG_DIR = 'logs' # Config keys we warm up so u won't be prompted later WARMUP_PWS = [('service_token', 'the service admin token'), ('swift_hash', 'the random unique string for your swift cluster')] class SwiftUninstaller(comp.PythonUninstallComponent): def __init__(self, *args, **kargs): comp.PythonUninstallComponent.__init__(self, *args, **kargs) self.datadir = sh.joinpths(self.app_dir, self.cfg.getdefaulted('swift', 'data_location', 'data')) self.bin_dir = sh.joinpths(self.app_dir, BIN_DIR) self.logdir = sh.joinpths(self.datadir, LOG_DIR) def pre_uninstall(self): sh.umount(sh.joinpths(self.datadir, DEVICE_PATH)) sh.replace_in(RSYNC_CONF_LOC, RSYNC_ON_OFF_RE, 'RSYNC_ENABLE=false', True) def post_uninstall(self): sh.execute(*RSYSLOG_SERVICE_RESTART, run_as_root=True) sh.execute(*RSYNC_SERVICE_RESTART, run_as_root=True) class SwiftInstaller(comp.PythonInstallComponent): def __init__(self, *args, **kargs): comp.PythonInstallComponent.__init__(self, *args, **kargs) self.bin_dir = sh.joinpths(self.app_dir, BIN_DIR) self.datadir = sh.joinpths(self.app_dir, self.cfg.getdefaulted('swift', 'data_location', 'data')) self.logdir = sh.joinpths(self.datadir, LOG_DIR) self.startmain_file = sh.joinpths(self.bin_dir, SWIFT_STARTMAIN) self.makerings_file = sh.joinpths(self.bin_dir, SWIFT_MAKERINGS) self.fs_dev = sh.joinpths(self.datadir, DEVICE_PATH) self.fs_image = sh.joinpths(self.datadir, SWIFT_IMG) self.auth_server = AUTH_SERVICE def _get_download_locations(self): places = list() places.append({ 'uri': ('git', 'swift_repo'), 'branch': ('git', 'swift_branch') }) return places def _get_config_files(self): return list(CONFIGS) def warm_configs(self): for (pw_key, prompt) in WARMUP_PWS: self.pw_gen.get_password(pw_key, prompt) def _get_param_map(self, config_fn): return { 'USER': self.cfg.getdefaulted('swift', 'swift_user', sh.getuser()), 'GROUP': self.cfg.getdefaulted('swift', 'swift_group', sh.getgroupname()), 'SWIFT_DATA_LOCATION': self.datadir, 'SWIFT_CONFIG_LOCATION': self.cfg_dir, 'SERVICE_TOKEN': self.cfg.get('passwords', 'service_token'), 'AUTH_SERVER': self.auth_server, 'SWIFT_HASH': self.cfg.get('passwords', 'swift_hash'), 'SWIFT_LOGDIR': self.logdir, 'SWIFT_PARTITION_POWER_SIZE': self.cfg.getdefaulted('swift', 'partition_power_size', '9'), # Note: leave these alone, will be adjusted later 'NODE_PATH': '%NODE_PATH%', 'BIND_PORT': '%BIND_PORT%', 'LOG_FACILITY': '%LOG_FACILITY%', } def _create_data_location(self): loop_size = self.cfg.get('swift', 'loopback_disk_size') if not loop_size: loop_size = DEF_LOOP_SIZE else: loop_size = utils.to_bytes(loop_size) sh.create_loopback_file(fname=self.fs_image, size=loop_size, fs_type=FS_TYPE) self.tracewriter.file_touched(self.fs_image) sh.mount_loopback_file(self.fs_image, self.fs_dev, FS_TYPE) sh.chown_r(self.fs_dev, sh.geteuid(), sh.getegid()) def _create_node_config(self, node_number, port): for t in ['object', 'container', 'account']: src_fn = sh.joinpths(self.cfg_dir, '%s-server.conf' % t) tgt_fn = sh.joinpths(self.cfg_dir, '%s-server/%d.conf' % (t, node_number)) adjustments = { '%NODE_PATH%': sh.joinpths(self.datadir, str(node_number)), '%BIND_PORT%': str(port), '%LOG_FACILITY%': str(2 + node_number), } sh.copy_replace_file(src_fn, tgt_fn, adjustments) port += 1 def _delete_templates(self): for t in ['object', 'container', 'account']: sh.unlink(sh.joinpths(self.cfg_dir, '%s-server.conf' % t)) def _create_nodes(self): for i in range(1, 5): self.tracewriter.dirs_made(sh.mkdirslist(sh.joinpths(self.fs_dev, '%d/node' % i))) link_tgt = sh.joinpths(self.datadir, str(i)) sh.symlink(sh.joinpths(self.fs_dev, str(i)), link_tgt) self.tracewriter.symlink_made(link_tgt) start_port = (6010 + (i - 1) * 5) self._create_node_config(i, start_port) self._delete_templates() def _turn_on_rsync(self): sh.symlink(sh.joinpths(self.cfg_dir, RSYNC_CONF), RSYNCD_CONF_LOC) self.tracewriter.symlink_made(RSYNCD_CONF_LOC) sh.replace_in(RSYNC_CONF_LOC, RSYNC_ON_OFF_RE, 'RSYNC_ENABLE=true', True) def _create_log_dirs(self): self.tracewriter.dirs_made(*sh.mkdirslist(sh.joinpths(self.logdir, 'hourly'))) sh.symlink(sh.joinpths(self.cfg_dir, SYSLOG_CONF), SWIFT_RSYNC_LOC) self.tracewriter.symlink_made(SWIFT_RSYNC_LOC) def _setup_binaries(self): sh.move(sh.joinpths(self.cfg_dir, SWIFT_MAKERINGS), self.makerings_file) sh.chmod(self.makerings_file, 0777) self.tracewriter.file_touched(self.makerings_file) sh.move(sh.joinpths(self.cfg_dir, SWIFT_STARTMAIN), self.startmain_file) sh.chmod(self.startmain_file, 0777) self.tracewriter.file_touched(self.startmain_file) def _make_rings(self): sh.execute(self.makerings_file, run_as_root=True) def post_install(self): self._create_data_location() self._create_nodes() self._turn_on_rsync() self._create_log_dirs() self._setup_binaries() self._make_rings() class SwiftRuntime(comp.PythonRuntime): def __init__(self, *args, **kargs): comp.PythonRuntime.__init__(self, *args, **kargs) self.datadir = sh.joinpths(self.app_dir, self.cfg.getdefaulted('swift', 'data_location', 'data')) self.bin_dir = sh.joinpths(self.app_dir, BIN_DIR) self.logdir = sh.joinpths(self.datadir, LOG_DIR) def start(self): sh.execute(*RSYSLOG_SERVICE_RESTART, run_as_root=True) sh.execute(*RSYNC_SERVICE_RESTART, run_as_root=True) swift_start_cmd = [sh.joinpths(self.bin_dir, SWIFT_INIT)] + ['all', 'start'] sh.execute(*swift_start_cmd, run_as_root=True) def stop(self): swift_stop_cmd = [sh.joinpths(self.bin_dir, SWIFT_INIT)] + ['all', 'stop'] sh.execute(*swift_stop_cmd, run_as_root=True) def restart(self): swift_restart_cmd = [sh.joinpths(self.bin_dir, SWIFT_INIT)] + ['all', 'restart'] sh.execute(*swift_restart_cmd, run_as_root=True)