Add 'set-weight' action.

This patchset adds the 'set-weight' action which can be used to set
weight of device(s) based on the search pattern.

Change-Id: I6bbc71f66d948e97d2dd6a5174dedb3212503a3f
Closes-Bug: 1821697
This commit is contained in:
Tytus Kurek 2019-06-13 10:55:23 +00:00
parent 3c8a676f3b
commit 3809df73fb
6 changed files with 110 additions and 1 deletions

View File

@ -58,3 +58,28 @@ remove-devices:
required:
- ring
- search-value
set-weight:
description: Sets the device's weight.
params:
ring:
type: string
description: |
Swift ring to set the weight for. Valid options are 'account',
'container', 'object' or 'all'.
search-value:
type: string
description: |
The search-value can be of the form:
.
d<device_id>r<region>z<zone>-<ip>:<port>R<r_ip>:<r_port>/
<device_name>_<meta>
.
Where <r_ip> and <r_port> are replication ip and port. Any part is
optional, but you must include at least one part.
weight:
type: number
description: The device's weight
required:
- ring
- search-value
- weight

View File

@ -51,6 +51,7 @@ from lib.swift_utils import (
balance_rings,
remove_from_ring,
services,
set_weight_in_ring,
SWIFT_CONF_DIR,
)
@ -147,10 +148,36 @@ def remove_devices(args):
balance_rings()
def set_weight(args):
""" Sets the device's weight.
Sets the device's weight based on the search pattern.
:raises SwiftProxyCharmException: if pattern action_get('search-value')
doesn't match any device in the ring.
"""
rings_valid = ['account', 'container', 'object', 'all']
ring = action_get('ring')
if ring not in rings_valid:
action_fail('Invalid ring name.')
return
if ring == 'all':
rings_to_update = ['account', 'container', 'object']
else:
rings_to_update = [ring]
for ring_to_update in rings_to_update:
ring_to_update_builder = ring_to_update + '.builder'
ring_to_update_path = os.path.join(SWIFT_CONF_DIR,
ring_to_update_builder)
set_weight_in_ring(ring_to_update_path, action_get('search-value'),
str(action_get('weight')))
balance_rings()
# A dictionary of all the defined actions to callables (which take
# parsed arguments).
ACTIONS = {"pause": pause, "resume": resume, 'diskusage': diskusage,
'remove-devices': remove_devices}
'remove-devices': remove_devices, 'set-weight': set_weight}
def main(argv):

1
actions/set-weight Symbolic link
View File

@ -0,0 +1 @@
actions.py

View File

@ -524,6 +524,29 @@ def remove_from_ring(ring_path, search_value):
"{}".format(search_value, ring_path, e))
def set_weight_in_ring(ring_path, search_value, weight):
""" Resets the device's weight.
Resets the device's weight based on the search pattern.
:param ring_path: path to the ring
:type ring_path: str
:param search_value: search pattern
:type search_value: str
:param weight: the device's weight
:type weight: str
:raises: SwiftProxyCharmException
"""
cmd = ['swift-ring-builder', ring_path, 'set_weight', search_value, weight]
try:
subprocess.check_call(cmd)
except subprocess.CalledProcessError:
raise SwiftProxyCharmException(
"Failed to set {} weight for {} pattern on {}".format(weight,
search_value,
ring_path))
def _ring_port(ring_path, node):
"""Determine correct port from relation settings for a given ring file."""
for name in ['account', 'object', 'container']:

View File

@ -335,3 +335,27 @@ class RemoveDevicesTestCase(CharmTestCase):
self.action_fail.assert_called()
self.remove_from_ring.assert_not_called()
self.balance_rings.assert_not_called()
class SetWeightTestCase(CharmTestCase):
def setUp(self):
super(SetWeightTestCase, self).setUp(
actions.actions, ["action_fail",
"action_get",
"set_weight_in_ring",
"balance_rings"])
def test_ring_valid(self):
self.action_get.side_effect = ['account', 'd1', '0.0']
actions.actions.set_weight([])
self.set_weight_in_ring.assert_called_once_with(
'/etc/swift/account.builder', 'd1', '0.0')
self.balance_rings.assert_called_once()
def test_ring_invalid(self):
self.action_get.side_effect = ['other', 'd1', '0.0']
actions.actions.set_weight([])
self.action_fail.assert_called()
self.set_weight_in_ring.assert_not_called()
self.balance_rings.assert_not_called()

View File

@ -437,6 +437,15 @@ class SwiftUtilsTestCase(unittest.TestCase):
'remove',
'd1'])
@mock.patch.object(subprocess, 'check_call')
def test_set_weight_in_ring(self, check_call):
swift_utils.set_weight_in_ring('/etc/swift/account.builder', 'd1', 0.0)
check_call.assert_called_once_with(['swift-ring-builder',
'/etc/swift/account.builder',
'set_weight',
'd1',
0.0])
@mock.patch('lib.swift_utils.config')
@mock.patch('lib.swift_utils.set_os_workload_status')
@mock.patch('lib.swift_utils.SwiftRingContext.__call__')