Set out the ring distribution and configuration plays

* Add tasks for building the ring and distributing the play
* Add additional playbook to handle ring building
* Add "overall" playbook for swift-all
This commit is contained in:
Andy McCrae 2014-09-26 14:29:48 +00:00 committed by Andy McCrae
parent 1fa95a2269
commit 0d2f69bc03
7 changed files with 223 additions and 23 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 <swift setup yaml>"
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))

View File

@ -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

View File

@ -0,0 +1,6 @@
---
- name: "Copy the rings over"
copy: >
src=/tmp/swift/rings/
dest=/etc/swift/rings/
mode=0644