diff --git a/defaults/main.yml b/defaults/main.yml index 1593d45a..1a09afe2 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -81,6 +81,11 @@ swift_middleware_list: ## Swift default ports swift_proxy_port: "8080" +# You can change the object, container, account ports. +# This will update the ring, on the next playbook run, +# without requiring a rebalance. +# NB: There is service downtime, during the run, between +# the service restart and the ring updating. swift_object_port: "6000" swift_container_port: "6001" swift_account_port: "6002" diff --git a/releasenotes/notes/swift-rings-port-change-4a95bbd9b63fb201.yaml b/releasenotes/notes/swift-rings-port-change-4a95bbd9b63fb201.yaml new file mode 100644 index 00000000..93be2621 --- /dev/null +++ b/releasenotes/notes/swift-rings-port-change-4a95bbd9b63fb201.yaml @@ -0,0 +1,11 @@ +--- +features: + - Change the port for devices in the ring by adjusting + the port value for services, hosts, or devices. This + will not involve a rebalance of the ring. + - Changing the port for a device, or group of devices, + carries a brief period of downtime to the swift + storage services for those devices. The devices will + be unavailable during period between when the + storage service restarts after the port update, and + the ring updates to match the new port. diff --git a/templates/ring.contents.j2 b/templates/ring.contents.j2 index 835fd0f2..03f4a995 100644 --- a/templates/ring.contents.j2 +++ b/templates/ring.contents.j2 @@ -87,8 +87,8 @@ {% set _update = device.update({'weight': weight}) %} {% set _update = device.update({'region': region}) %} {% set _update = device.update({'zone': zone}) %} -{% set _update = device.update({'repl_ip': repl_ip}) %} -{% set _update = device.update({'repl_port': repl_port|int}) %} +{% set _update = device.update({'replication_ip': repl_ip}) %} +{% set _update = device.update({'replication_port': repl_port|int}) %} {% set _update = device.update({'ip': storage_ip}) %} {% set _update = device.update({'port': storage_port|int}) %} {### Append the device to the drives list of the builder dict #} diff --git a/templates/swift_rings.py.j2 b/templates/swift_rings.py.j2 index b9bc0832..180ee14d 100644 --- a/templates/swift_rings.py.j2 +++ b/templates/swift_rings.py.j2 @@ -27,7 +27,9 @@ import threading USAGE = "usage: %prog -f -r " -DEVICE_KEY = "%(ip)s:%(port)d/%(device)s" +DEVICE_KEY = "%(ip)s/%(device)s" +FULL_HOST_KEY = "%(ip)s:%(port)dR%(replication_ip)s:" \ + "%(replication_port)d/%(device)s" class RingValidationError(Exception): @@ -82,28 +84,22 @@ def update_host_in_ring(build_file, new_host, old_host, validate=False): 'be done when the drive is added' % devstr) try: - r_ip = new_host.get('repl_ip', new_host['ip']) - r_port = new_host.get('repl_port', new_host['port']) - weight = new_host.get('weight') + old_host_str = FULL_HOST_KEY % old_host + new_host_str = FULL_HOST_KEY % new_host - old_r_ip = old_host['replication_ip'] - old_r_port = old_host['replication_port'] + new_weight = new_host.get('weight') + old_weight = old_host.get('weight') - if r_ip != old_r_ip or r_port != old_r_port: - host_d = {'r_ip': r_ip, 'r_port': r_port} - host_d.update(new_host) - host_str = ( - "%(ip)s:%(port)dR%(r_ip)s:%(r_port)d/%(device)s" % host_d - ) + if new_host_str != old_host_str: if not validate: run_and_wait(rb_main, ["swift-ring-builder", build_file, - "set_info", DEVICE_KEY % new_host, - host_str]) + "set_info", old_host_str, + new_host_str]) except Exception as ex: raise RingValidationError(ex) - if weight != old_host['weight'] and not validate: - change_host_weight(build_file, DEVICE_KEY % new_host, weight) + if new_weight != old_weight and not validate: + change_host_weight(build_file, FULL_HOST_KEY % new_host, new_weight) def add_host_to_ring(build_file, host, validate=False): @@ -111,17 +107,8 @@ def add_host_to_ring(build_file, host, validate=False): try: if host.get('region') is not None: host_str += 'r%(region)d' % host - host_str += "z%d" % (host.get('zone')) - host_str += "-%(ip)s:%(port)d" % host - if host.get('repl_ip'): - r_ip = host['repl_ip'] - r_port = host.get('repl_port', host['port']) - host_str += "R%s:%d" % (r_ip, r_port) - elif host.get('repl_port'): - r_ip = host.get('repl_ip', host['ip']) - r_port = host['repl_port'] - host_str += "R%s:%d" % (r_ip, r_port) - host_str += "/%(device)s" % host + host_str += "z%(zone)d-" % host + host_str += FULL_HOST_KEY % host weight = host.get('weight') except Exception as ex: raise RingValidationError(ex) @@ -203,6 +190,11 @@ def build_ring(build_name, repl, min_part_hours, part_power, hosts, run_and_wait( rb_main, ["swift-ring-builder", build_file, "rebalance"] ) + # In case no changes that require a rebalance have happened + # We may still need to write the ring for device changes. + run_and_wait( + rb_main, ["swift-ring-builder", build_file, "write_ring"] + ) def main(setup, region, reset_mph_clock): diff --git a/templates/swift_rings_check.py.j2 b/templates/swift_rings_check.py.j2 index 5441a0d7..2c7a7216 100644 --- a/templates/swift_rings_check.py.j2 +++ b/templates/swift_rings_check.py.j2 @@ -24,6 +24,8 @@ import sys USAGE = "usage: %prog -f -r " DEVICE_KEY = "%(ip)s:%(port)d/%(device)s" +FULL_HOST_KEY = "%(ip)s:%(port)dR%(replication_ip)s:" \ + "%(replication_port)d/%(device)s_w%(weight)d" class RingComparisonError(Exception): @@ -69,21 +71,12 @@ def check_host_settings(content_host, ring_host): raise RingComparisonError('Region on device %s differs to the ring.' % devstr) - content_repl_ip = content_host.get('repl_ip', content_host['ip']) - content_repl_port = content_host.get('repl_port', content_host['port']) - content_weight = content_host.get('weight') - ring_repl_ip = ring_host['replication_ip'] - ring_repl_port = ring_host['replication_port'] - ring_weight = ring_host['weight'] - if content_repl_ip != ring_repl_ip: - raise RingComparisonError('Replication IP for device %s differs ' - 'to the ring.' % devstr) - if content_repl_port != ring_repl_port: - raise RingComparisonError('Replication Port for device %s differs ' - 'to the ring.' % devstr) - if content_weight != ring_weight: - raise RingComparisonError('Device weight for device %s differs to the ' - 'ring.' % devstr) + content_host_str = FULL_HOST_KEY % content_host + ring_host_str = FULL_HOST_KEY % ring_host + + if content_host_str != ring_host_str: + raise RingComparisonError('Content device %(content_host_str)s differs' + ' to the ring device %(ring_host_str)s.') def check_ring(build_name, repl, min_part_hours, part_power, content_hosts,