From cce0410334dd0666620a6a63480ee8e5b1a16299 Mon Sep 17 00:00:00 2001 From: Andy McCrae Date: Fri, 8 Jul 2016 13:25:20 +0100 Subject: [PATCH] Add pretend_min_part_hours_passed to ring build Expose the "pretend_min_part_hours_passed" option when accessing swift-ring-builder. This PR adds a variable "swift_pretend_min_part_hours_passed" which defaults to False. Change-Id: Ief94f011049b57f1ab0c2c48dfa81659d7ba13f7 --- defaults/main.yml | 8 +++++++ ...t-pretend-mph-passed-7e5c15eeb35861c3.yaml | 17 ++++++++++++++ tasks/swift_rings_build.yml | 4 ++-- templates/swift_rings.py.j2 | 22 +++++++++++++++---- 4 files changed, 45 insertions(+), 6 deletions(-) create mode 100644 releasenotes/notes/swift-pretend-mph-passed-7e5c15eeb35861c3.yaml diff --git a/defaults/main.yml b/defaults/main.yml index 79cd0f85..0bb692b8 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -296,6 +296,14 @@ swift_object_program_names: swift_proxy_program_names: - swift-proxy-server +# Set to True to reset the clock on the last time a rebalance happened, +# circumventing the min_part_hours check. +# USE WITH EXTREME CAUTION +# If you run the swift playbook with this option enabled, before a swift +# replication pass completes, you may introduce unavailability in your +# cluster. This has an end-user impact. +swift_pretend_min_part_hours_passed: False + # Set this option to enable or disable the pypy interpreter for swift swift_pypy_enabled: false swift_pypy_archive: diff --git a/releasenotes/notes/swift-pretend-mph-passed-7e5c15eeb35861c3.yaml b/releasenotes/notes/swift-pretend-mph-passed-7e5c15eeb35861c3.yaml new file mode 100644 index 00000000..0be1bf49 --- /dev/null +++ b/releasenotes/notes/swift-pretend-mph-passed-7e5c15eeb35861c3.yaml @@ -0,0 +1,17 @@ +--- +features: + - The ``pretend_min_part_hours_passed`` option can now be + passed to swift-ring-builder prior to performing a + rebalance. This is set by the + ``swift_pretend_min_part_hours_passed`` boolean variable. + The default for this variable is False. We recommend setting + this by running the os-swift.yml playbook with + ``-e swift_pretend_min_part_hours_passed=True``, to avoid + resetting ``min_part_hours`` unintentionally on every run. + Setting ``swift_pretend_min_part_hours_passed`` to True will + reset the clock on the last time a rebalance happened, thus + circumventing the min_part_hours check. This should only be + used with extreme caution. If you run this command and deploy + rebalanced rings before a replication pass completes, you may + introduce unavailability in your cluster. This has an end-user + imapct. diff --git a/tasks/swift_rings_build.yml b/tasks/swift_rings_build.yml index 3e07848f..b2483287 100644 --- a/tasks/swift_rings_build.yml +++ b/tasks/swift_rings_build.yml @@ -51,7 +51,7 @@ - swift-rings-contents - name: "build rings for account/container from contents files" - command: "/etc/swift/scripts/swift_rings.py -f /etc/swift/scripts/{{ item[0] }}.contents{% if item[1] %} -r {{ item[1] }} {% endif %}" + command: "/etc/swift/scripts/swift_rings.py -f /etc/swift/scripts/{{ item[0] }}.contents{% if item[1] %} -r {{ item[1] }}{% endif %}{{ (swift_pretend_min_part_hours_passed | bool) | ternary(' -p', '')}}" with_nested: - [ 'account', 'container' ] - swift_managed_regions | default([None]) @@ -64,7 +64,7 @@ - swift-rings-build - name: "build rings for storage policies from contents files" - command: "/etc/swift/scripts/swift_rings.py -f /etc/swift/scripts/object-{{ item[0].policy.index }}.contents{% if item[1] %} -r {{ item[1] }} {% endif %}" + command: "/etc/swift/scripts/swift_rings.py -f /etc/swift/scripts/object-{{ item[0].policy.index }}.contents{% if item[1] %} -r {{ item[1] }}{% endif %}{{ (swift_pretend_min_part_hours_passed | bool) | ternary(' -p', '')}}" with_nested: - "{{ swift.storage_policies }}" - swift_managed_regions | default([None]) diff --git a/templates/swift_rings.py.j2 b/templates/swift_rings.py.j2 index 30a9922b..4125ba66 100644 --- a/templates/swift_rings.py.j2 +++ b/templates/swift_rings.py.j2 @@ -150,7 +150,7 @@ def get_build_file_data(build_file): def build_ring(build_name, repl, min_part_hours, part_power, hosts, - region=None, validate=False): + region=None, validate=False, reset_mph_clock=False): # Create the build file build_file = "%s.builder" % build_name build_file_data = get_build_file_data(build_file) @@ -195,12 +195,17 @@ def build_ring(build_name, repl, min_part_hours, part_power, hosts, rb_main, ["swift-ring-builder", build_file, "write_ring"] ) else: + if reset_mph_clock: + run_and_wait( + rb_main, ["swift-ring-builder", build_file, + "pretend_min_part_hours_passed"] + ) run_and_wait( rb_main, ["swift-ring-builder", build_file, "rebalance"] ) -def main(setup, region): +def main(setup, region, reset_mph_clock): # load the json file try: with open(setup) as json_stream: @@ -210,7 +215,8 @@ def main(setup, region): return 1 hosts = _contents_file['drives'] - kargs = {'validate': True, 'hosts': hosts, 'region': region} + kargs = {'validate': True, 'hosts': hosts, 'region': region, + 'reset_mph_clock': reset_mph_clock} ring_call = [ _contents_file['builder_file'], _contents_file['repl_number'], @@ -246,6 +252,14 @@ if __name__ == "__main__": type='int', metavar="REGION" ) + parser.add_option( + "-p", + "--pretend_min_part_hours_passed", + help="Reset the clock on the last time a rebalance happened.", + dest="reset_mph_clock", + action="store_true", + default='False' + ) options, _args = parser.parse_args(sys.argv[1:]) if options.setup and not exists(options.setup): @@ -253,4 +267,4 @@ if __name__ == "__main__": parser.print_help() sys.exit(1) - sys.exit(main(options.setup, options.region)) + sys.exit(main(options.setup, options.region, options.reset_mph_clock))