diff --git a/rpc_deployment/inventory/group_vars/swift_all.yml b/rpc_deployment/inventory/group_vars/swift_all.yml index b39689e513..d6979fbab3 100644 --- a/rpc_deployment/inventory/group_vars/swift_all.yml +++ b/rpc_deployment/inventory/group_vars/swift_all.yml @@ -90,6 +90,7 @@ container_directories: - /tmp/swift - /var/lock/swift - /etc/swift + - /etc/swift/rings/ container_packages: - curl @@ -100,3 +101,4 @@ container_packages: - python-setuptools - python-dev - gcc + - libffi-dev diff --git a/rpc_deployment/playbooks/build_swift_rings.yml b/rpc_deployment/playbooks/build_swift_rings.yml deleted file mode 100644 index 0fa4f4806f..0000000000 --- a/rpc_deployment/playbooks/build_swift_rings.yml +++ /dev/null @@ -1,23 +0,0 @@ ---- -- hosts: local - user: root - roles: - - swift_common - -- hosts: local - user: root - tasks: - - name: "make sure rings directory exists" - file: state=directory path=/etc/swift/rings/ owner=root group=root mode=0755 - - name: "build rings" - command: /usr/bin/python /etc/ansible/scripts/swift_rings.py -s /etc/ansible/swift_setup.yml - args: - chdir: /etc/swift/rings/ - -- hosts: swift - user: root - tasks: - - name: "Make sure /etc/swift exists" - file: state=directory path=/etc/swift/ mode=0755 - - name: "Copy the rings over" - copy: src=/etc/swift/rings/ dest=/etc/swift/ mode=644 diff --git a/rpc_deployment/playbooks/openstack/swift-all.yml b/rpc_deployment/playbooks/openstack/swift-all.yml new file mode 100644 index 0000000000..4937c69a10 --- /dev/null +++ b/rpc_deployment/playbooks/openstack/swift-all.yml @@ -0,0 +1,18 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +- include: swift-proxy.yml +- include: swift-storage.yml +- include: swift-build-rings.yml diff --git a/rpc_deployment/playbooks/openstack/swift-build-rings.yml b/rpc_deployment/playbooks/openstack/swift-build-rings.yml new file mode 100644 index 0000000000..66b35597e5 --- /dev/null +++ b/rpc_deployment/playbooks/openstack/swift-build-rings.yml @@ -0,0 +1,10 @@ +--- +- hosts: swift_all[0] + user: root + roles: + - swift_ring_builder + +- hosts: swift_all:!swift_all[0] + user: root + roles: + - swift_ring_distribute diff --git a/rpc_deployment/roles/swift_ring_builder/files/swift_rings.py b/rpc_deployment/roles/swift_ring_builder/files/swift_rings.py new file mode 100644 index 0000000000..3c32845ae1 --- /dev/null +++ b/rpc_deployment/roles/swift_ring_builder/files/swift_rings.py @@ -0,0 +1,158 @@ +#!/usr/bin/env python +from __future__ import print_function +from optparse import OptionParser +from os.path import exists +from swift.cli.ringbuilder import main as rb_main + +import sys +import threading +import yaml + +USAGE = "usage: %prog -s " + +DEFAULT_PART_POWER = 10 +DEFAULT_REPL = 3 +DEFAULT_MIN_PART_HOURS = 1 +DEFAULT_HOST_DRIVES = '/srv/drive/' +DEFAULT_HOST_DRIVE = '/sdb' +DEFAULT_HOST_ZONE = 0 +DEFAULT_HOST_WEIGHT = 1 +DEFAULT_ACCOUNT_PORT = 6002 +DEFAULT_CONTAINER_PORT = 6001 +DEFAULT_OBJECT_PORT = 6000 +DEFAULT_SECTION_PORT = { + 'account': DEFAULT_ACCOUNT_PORT, + 'container': DEFAULT_CONTAINER_PORT, + 'object': DEFAULT_OBJECT_PORT, +} + + +def create_buildfile(build_file, part_power, repl, min_part_hours): + run_and_wait(rb_main, ["swift-ring-builder", build_file, "create", + part_power, repl, min_part_hours]) + + +def add_host_to_ring(build_file, host): + host_str = "" + if host.get('region') is not None: + host_str += 'r%(region)d' % host + host_str += "z%d" % (host.get('zone', DEFAULT_HOST_ZONE)) + host_str += "-%(host)s:%(port)d" % host + if host.get('repl_port'): + r_ip = host.get('repl_ip', host['host']) + host_str += "R%s:%d" % (r_ip, host['repl_port']) + host_str += "/%(drive)s" % host + + weight = host.get('weight', DEFAULT_HOST_WEIGHT) + run_and_wait(rb_main, ["swift-ring-builder", build_file, 'add', + host_str, str(weight)]) + + +def run_and_wait(func, *args): + t = threading.Thread(target=func, args=args) + t.start() + return t.join() + + +def has_section(conf, section): + return True if conf.get(section) else False + + +def check_section(conf, section): + if not has_section(conf, section): + print("Section %s doesn't exist" % (section)) + sys.exit(2) + + +def build_ring(section, conf, part_power, hosts): + # Create the build file + build_file = "%s.builder" % (section) + repl = conf.get('repl_number', DEFAULT_REPL) + min_part_hours = conf.get('min_part_hours', + DEFAULT_MIN_PART_HOURS) + create_buildfile(build_file, part_power, repl, min_part_hours) + + # Add the hosts + if not has_section(conf, 'hosts') or len(conf.get('hosts')) == 0: + print("No hosts/drives assigned to the %s ring" % section) + sys.exit(3) + + section_key = section.split('-')[0] + service_port = conf.get('port', DEFAULT_SECTION_PORT[section_key]) + for host in conf['hosts']: + if 'name' in host: + if host['name'] not in hosts: + print("Host %(name) reference not found." % host) + sys.exit(3) + host = hosts[host['name']] + else: + if 'drive' not in host: + host['drive'] = DEFAULT_HOST_DRIVE + host['port'] = service_port + add_host_to_ring(build_file, host) + + # Rebalance ring + run_and_wait(rb_main, ["swift-ring-builder", build_file, "rebalance"]) + # rb_main(("swift-ring-builder", build_file, "rebalance")) + + +def main(setup): + # load the yaml file + try: + with open(setup) as yaml_stream: + _swift = yaml.load(yaml_stream) + except Exception as ex: + print("Failed to load yaml string %s" % (ex)) + return 1 + + _hosts = {} + + if _swift.get("hosts"): + for host in _swift['hosts']: + if not host.get('drive'): + host['drive'] = DEFAULT_HOST_DRIVE + key = "%(host)s/%(drive)s" % host + if key in _hosts: + print("%(host)s already definined" % host) + return 1 + _hosts[key] = host + + check_section(_swift, 'swift') + part_power = _swift['swift'].get('part_power', DEFAULT_PART_POWER) + + # Create account ring + check_section(_swift, 'account') + build_ring('account', _swift['account'], part_power, _hosts) + + # Create container ring + check_section(_swift, 'container') + build_ring('container', _swift['container'], part_power, _hosts) + + # Create object rings (storage policies) + check_section(_swift, 'storage_policies') + check_section(_swift['storage_policies'], 'policies') + indexes = set() + for sp in _swift['storage_policies']['policies']: + if sp['index'] in indexes: + print("Storage Policy index %d already in use" % (sp['index'])) + return 4 + buildfilename = 'object-%d' % (sp['index']) + indexes.add(sp['index']) + if 'port' not in sp: + sp['port'] = _swift['storage_policies'].get('port', + DEFAULT_OBJECT_PORT) + build_ring(buildfilename, sp, part_power, _hosts) + +if __name__ == "__main__": + parser = OptionParser(USAGE) + parser.add_option("-s", "--setup", dest="setup", + help="Specify the swift setup file.", metavar="FILE", + default="/etc/swift/swift_inventory.yml") + + options, args = parser.parse_args(sys.argv[1:]) + if options.setup and not exists(options.setup): + print("Swift setup file not found or doesn't exist") + parser.print_help() + sys.exit(1) + + sys.exit(main(options.setup)) diff --git a/rpc_deployment/roles/swift_ring_builder/tasks/main.yml b/rpc_deployment/roles/swift_ring_builder/tasks/main.yml new file mode 100644 index 0000000000..8b21a832be --- /dev/null +++ b/rpc_deployment/roles/swift_ring_builder/tasks/main.yml @@ -0,0 +1,29 @@ +--- +- name: "make sure scripts directory exists" + file: > + state=directory + path=/etc/swift/scripts/ + owner=root + group=root + mode=0755 + +- name: "Retrieve the swift_rings.py file" + copy: > + src=swift_rings.py + dest="/etc/swift/scripts/swift_rings.py" + +#- name: "build rings" +# command: /usr/bin/python /etc/swift/scripts/swift_rings.py -s /etc/rpc_deploy/rpc_user_config.yml +# args: +# chdir: /etc/swift/rings/ + +- name: "List ring files to copy over" + command: "/bin/ls /etc/swift/rings/" + register: ringfiles + +- name: "Fetch rings to local server" + fetch: > + src="/etc/swift/rings/{{ item }}" + dest=/tmp/swift/rings/ + flat=yes + with_items: ringfiles.stdout_lines diff --git a/rpc_deployment/roles/swift_ring_distribute/tasks/main.yml b/rpc_deployment/roles/swift_ring_distribute/tasks/main.yml new file mode 100644 index 0000000000..93297a53cc --- /dev/null +++ b/rpc_deployment/roles/swift_ring_distribute/tasks/main.yml @@ -0,0 +1,6 @@ +--- +- name: "Copy the rings over" + copy: > + src=/tmp/swift/rings/ + dest=/etc/swift/rings/ + mode=0644