Skip to content

Commit 8eff9c0

Browse files
author
Paul Breaux
committed
Changing scaling to explicitly be scale_up_by_one and scale_down_by_one. Exception in poll_for_exceptionless_callable now passed up to MaximumAttemptsReached.
1 parent 732f3ef commit 8eff9c0

5 files changed

Lines changed: 73 additions & 27 deletions

File tree

f5/multi_device/cluster/__init__.py

Lines changed: 46 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,39 @@
1414
#
1515
#
1616

17-
# TrustDomain and DeviceGroup may need to move under multi_device
17+
'''The classes within define the management of a cluster of BIG_IP devices.
18+
19+
Definitions:
20+
Cluster: The manager of the TrustDomain and DeviceGroup objects.
21+
TrustDomain: a group of BIG-IP devices that have exchanged certificates
22+
and trust one another
23+
DeviceGroup: a group of BIG-IP device that sync configuration data and
24+
failover connections.
25+
26+
Clustering is broken down into three component parts: a cluster manager, a
27+
trust domain, and a device group. The cluster manager presents the external
28+
interface to a user for operations like create, teardown etc....
29+
30+
To create a device service group (aka cluster) of devices, those devices
31+
must trust one another. This is coordinated by the TrustDomain class. Once
32+
those devices trust one another, a device group is created and each is added
33+
to the group. After this step, a cluster exists.
34+
35+
Currently the only supported type of cluster is a 'sync-failover' cluster.
36+
37+
ClusterManager Methods:
38+
39+
* create -- creates a cluster based on kwargs given by user
40+
* teardown -- tears down an existing cluster
41+
* scale_up_by_one -- add one device to the cluster
42+
* scale_down_by_one -- remove one device from the cluster
43+
44+
Classes:
45+
46+
* ClusterManager -- manages a cluster of devices with the methods above
47+
* TrustDomain -- manages the trust domain for a cluster
48+
* DeviceGroup -- manages the device group for a cluster
49+
'''
1850

1951
from f5.sdk_exception import F5SDKError
2052
from f5.utils.decorators import poll_for_exceptionless_callable
@@ -24,7 +56,6 @@
2456

2557
class ClusterError(F5SDKError):
2658
def __init__(self, *args, **kwargs):
27-
# TODO(paul): Place your logging 0ssmness here.
2859
super(ClusterError, self).__init__(*args, **kwargs)
2960

3061

@@ -215,7 +246,7 @@ def teardown(self):
215246
self.trust_domain.teardown()
216247
self.cluster = None
217248

218-
def scale_up(self, device):
249+
def scale_up_by_one(self, device):
219250
'''Scale cluster up by one device.
220251
221252
:param bigip: bigip object -- bigip to add
@@ -226,12 +257,12 @@ def scale_up(self, device):
226257
msg = 'The number of devices to cluster is not supported.'
227258
raise ClusterNotSupported(msg)
228259
print('Scaling cluster up by one device...')
229-
self.trust_domain.scale_up(device)
230-
self.device_group.scale_up(device)
260+
self.trust_domain.scale_up_by_one(device)
261+
self.device_group.scale_up_by_one(device)
231262
self.cluster.devices.append(device)
232263
self.device_group.ensure_all_devices_in_sync()
233264

234-
def scale_down(self, device):
265+
def scale_down_by_one(self, device):
235266
'''Scale cluster down by one device.
236267
237268
:param device: ManagementRoot object -- device to delete
@@ -242,8 +273,8 @@ def scale_down(self, device):
242273
msg = 'The number of devices to cluster is not supported.'
243274
raise ClusterNotSupported(msg)
244275
print('Scaling cluster down by one device...')
245-
self.device_group.scale_down(device)
246-
self.trust_domain.scale_down(device, self.device_group)
276+
self.device_group.scale_down_by_one(device)
277+
self.trust_domain.scale_down_by_one(device, self.device_group)
247278
self.cluster.devices.remove(device)
248279
self.device_group.ensure_all_devices_in_sync()
249280

@@ -341,7 +372,7 @@ def teardown(self):
341372
pollster(self._check_devices_active_licensed)()
342373
pollster(self._check_all_devices_in_sync)()
343374

344-
def scale_up(self, device):
375+
def scale_up_by_one(self, device):
345376
'''Scale device group up by one device
346377
347378
:param device: ManagementRoot object -- device to add to device group
@@ -357,7 +388,7 @@ def scale_up(self, device):
357388
self.devices.append(device)
358389
self.ensure_all_devices_in_sync()
359390

360-
def scale_down(self, device):
391+
def scale_down_by_one(self, device):
361392
'''Scale device group down by one device
362393
363394
:param device: ManagementRoot object -- device to delete from device
@@ -628,7 +659,7 @@ def teardown(self):
628659
self._populate_domain()
629660
self.domain = {}
630661

631-
def scale_up(self, device):
662+
def scale_up_by_one(self, device):
632663
'''Scale up trust domain by one device.
633664
634665
:param device: ManagementRoot object -- device to scale up
@@ -638,7 +669,7 @@ def scale_up(self, device):
638669
self._add_trustee(device)
639670
pollster(self.validate)()
640671

641-
def scale_down(self, device, device_group_object=None):
672+
def scale_down_by_one(self, device, device_group_object=None):
642673
'''Scale down trust domain by one device.
643674
644675
:param device: ManagementRoot object -- device to scale down
@@ -662,8 +693,9 @@ def _add_trustee(self, device):
662693
def _remove_trustee(self, device, device_group_object=None):
663694
'''Remove a trustee from the trust domain.
664695
665-
If this is called as part of scale_down, the device being scaled must
666-
remove the members of its device group before removing trusted devices
696+
If this is called as part of scale_down_by_one, the device being scaled
697+
must remove the members of its device group before removing trusted
698+
devices. This is optional.
667699
668700
:param device: MangementRoot object -- device to remove
669701
'''

f5/multi_device/cluster/test/test_cluster_manager.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -154,15 +154,15 @@ def test_scale_up_too_many_devices(ClusterManagerCreateNew, BigIPs):
154154
devices=mock_bigips, device_group_name='name',
155155
device_group_partition='part', device_group_type='sync-failover')
156156
mock_bigip1 = mock.MagicMock()
157-
cm.scale_up(mock_bigip1)
157+
cm.scale_up_by_one(mock_bigip1)
158158
mock_bigip2 = mock.MagicMock()
159-
cm.scale_up(mock_bigip2)
159+
cm.scale_up_by_one(mock_bigip2)
160160
mock_bigip3 = mock.MagicMock()
161-
cm.scale_up(mock_bigip3)
161+
cm.scale_up_by_one(mock_bigip3)
162162
mock_bigip4 = mock.MagicMock()
163-
cm.scale_up(mock_bigip4)
163+
cm.scale_up_by_one(mock_bigip4)
164164
with pytest.raises(ClusterNotSupported) as ex:
165-
cm.scale_up(mock.MagicMock())
165+
cm.scale_up_by_one(mock.MagicMock())
166166
assert sorted(cm.cluster.devices) == sorted(mock_bigips)
167167
assert 'The number of devices to cluster is not supported.' == \
168168
ex.value.message
@@ -174,10 +174,10 @@ def test_scale_down_cluster_not_supported(ClusterManagerCreateNew, BigIPs):
174174
cm.create(
175175
devices=mock_bigips, device_group_name='name',
176176
device_group_partition='part', device_group_type='sync-failover')
177-
cm.scale_down(mock_bigips[0])
177+
cm.scale_down_by_one(mock_bigips[0])
178178
assert cm.cluster.devices == mock_bigips
179-
cm.scale_down(mock_bigips[0])
179+
cm.scale_down_by_one(mock_bigips[0])
180180
with pytest.raises(ClusterNotSupported) as ex:
181-
cm.scale_down(mock_bigips[0])
181+
cm.scale_down_by_one(mock_bigips[0])
182182
assert 'The number of devices to cluster is not supported.' == \
183183
ex.value.message

f5/multi_device/cluster/test/test_device_group.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ def test_scale_up_device_already_in_group(DeviceGroupCreateNew, BigIPs):
104104
mock_names_in_group.return_value = ['test']
105105
dg._get_device_names_in_group = mock_names_in_group
106106
with pytest.raises(DeviceGroupOperationNotSupported) as ex:
107-
dg.scale_up(mock_bigip)
107+
dg.scale_up_by_one(mock_bigip)
108108
assert "Device: 'test' is already in device group" == ex.value.message
109109

110110

@@ -119,7 +119,7 @@ def test_scale_down_device_not_in_group(DeviceGroupCreateNew, BigIPs):
119119
mock_names_in_group.return_value = ['no_match']
120120
dg._get_device_names_in_group = mock_names_in_group
121121
with pytest.raises(DeviceGroupOperationNotSupported) as ex:
122-
dg.scale_down(mock_bigip)
122+
dg.scale_down_by_one(mock_bigip)
123123
assert "Device: 'test' is not in device group" == ex.value.message
124124

125125

f5/utils/decorators.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,13 @@
1515
#
1616

1717
from functools import wraps
18-
from future.utils import raise_from
1918
import time
2019

2120
from f5.utils.util_exceptions import UtilError
2221

2322

2423
class MaximumAttemptsReached(UtilError):
2524
def __init__(self, *args, **kwargs):
26-
# TODO(paul): Add logging here!
2725
super(MaximumAttemptsReached, self).__init__(*args, **kwargs)
2826

2927

@@ -43,7 +41,7 @@ def poll(*args, **kwargs):
4341
return callable(*args, **kwargs)
4442
except Exception as ex:
4543
if attempt == attempts-1:
46-
raise_from(MaximumAttemptsReached(), ex)
44+
raise MaximumAttemptsReached(ex)
4745
time.sleep(interval)
4846
continue
4947
return poll

test/functional/cluster/test_cluster.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,22 @@ def teardown_cluster():
7676
request.addfinalizer(teardown_cluster)
7777

7878

79+
def test_existing_failover_cluster(BigIPSetup):
80+
a, b, = BigIPSetup
81+
bigip_list = [a, b]
82+
83+
cm = ClusterManager(
84+
devices=bigip_list,
85+
device_group_name=DEVICE_GROUP_NAME,
86+
device_group_partition=PARTITION,
87+
device_group_type='sync-failover'
88+
)
89+
assert cm.cluster.devices == bigip_list
90+
assert cm.cluster.device_group_name == DEVICE_GROUP_NAME
91+
assert cm.cluster.device_group_type == 'sync-failover'
92+
assert cm.cluster.device_group_partition == PARTITION
93+
94+
7995
def test_new_failover_cluster_two_member(BigIPSetup):
8096
a, b, c = BigIPSetup
8197
bigip_list = [a, b]

0 commit comments

Comments
 (0)