1+ # coding=utf-8
12# Copyright 2016 F5 Networks Inc.
23
34# Licensed under the Apache License, Version 2.0 (the "License");
1415#
1516#
1617
17- '''Class for managing a DeviceGroup for a set of BIG-IP devices.'''
18+ '''Class for managing a DeviceGroup for a set of BIG-IP® devices
19+
20+ Managing a device group for clustering is an event-driven process. Please
21+ use the methods here to control that process. The fundamental idea is that
22+ any action should have an observable outcome. Adding a device to the device
23+ group should have a consequence for each member of the device group,
24+ including the newly added member.
25+
26+ Examples:
27+
28+ There are two major use-cases here:
29+
30+ * Manage an existing device group:
31+
32+ list_of_bigips = [ManagementRoot(...), ManagementRoot(...)]
33+ device_group = DeviceGroup(
34+ devices=list_of_bigips,
35+ device_group_name='my_cluster',
36+ device_group_type='sync-failover',
37+ device_group_partition='Common'
38+ )
39+ device_group.ensure_all_devices_in_sync()
40+
41+ * Create a new device group and manage it:
42+
43+ list_of_bigips = [ManagementRoot(...), ManagementRoot(...)]
44+ device_group = DeviceGroup()
45+ device_group.create(
46+ devices=list_of_bigips,
47+ device_group_name='my_cluster',
48+ device_group_type='sync-failover',
49+ device_group_partition='Common'
50+ )
51+ device_group.ensure_all_devices_in_sync()
52+
53+ Methods:
54+
55+ * create -- create a device group from a list of devices
56+ * teardown -- teardown a device group, but leave the trust domain intact
57+ * validate -- ensure a device group is in the proper state based on inputs
58+ * manage_extant -- manage an existing device group
59+
60+ '''
1861
1962from f5 .multi_device .exceptions import DeviceGroupNotSupported
20- from f5 .multi_device .exceptions import DeviceGroupOperationNotSupported
2163from f5 .multi_device .exceptions import MissingRequiredDeviceGroupParameter
2264from f5 .multi_device .exceptions import UnexpectedDeviceGroupDevices
2365from f5 .multi_device .exceptions import UnexpectedDeviceGroupState
2466from f5 .multi_device .exceptions import UnexpectedDeviceGroupType
2567
2668from f5 .multi_device .utils import get_device_info
27- from f5 .multi_device .utils import get_device_names_to_objects
2869from f5 .multi_device .utils import pollster
2970
3071
3172class DeviceGroup (object ):
32- '''Class to manage device service group.'''
73+ '''Class to manage device service group
74+
75+ For the non-public methods, there are a few flavors of behavior:
76+ get, check, and ensure. A 'get' retrieves some info from the device
77+ without any assumptions about that info. A 'check' will assert a device's
78+ info is as expected. An 'ensure' method often does one or more of the
79+ above and also may take some other action to enforce the expected state,
80+ such as syncing config.
81+
82+ Example:
83+
3384
34- available_types = ['sync-failover' ]
85+ '''
86+
87+ available_types = ['sync-failover' , 'sync-only' ]
3588 sync_status_entry = 'https://localhost/mgmt/tm/cm/sync-status/0'
3689
3790 def __init__ (self , ** kwargs ):
@@ -78,8 +131,9 @@ def validate(self, **kwargs):
78131 device_name = get_device_info (device ).name
79132 given_device_names .append (device_name )
80133 if sorted (queried_device_names ) != sorted (given_device_names ):
81- msg = ''
134+ msg = 'Given devices does not match queried devices. '
82135 raise UnexpectedDeviceGroupDevices (msg )
136+ self .ensure_all_devices_in_sync ()
83137
84138 def _check_type (self ):
85139 '''Check that the device group type is correct.
@@ -90,6 +144,10 @@ def _check_type(self):
90144 if self .type not in self .available_types :
91145 msg = 'Unsupported cluster type was given: %s' % self .type
92146 raise DeviceGroupNotSupported (msg )
147+ elif self .type == 'sync-only' and self .name != 'device_trust_group' :
148+ msg = "Management of sync-only device groups only supported for " \
149+ "built-in device group named 'device_trust_group'"
150+ raise DeviceGroupNotSupported (msg )
93151
94152 def manage_extant (self , ** kwargs ):
95153 self .validate (** kwargs )
@@ -121,48 +179,6 @@ def teardown(self):
121179 pollster (self ._check_devices_active_licensed )()
122180 pollster (self ._check_all_devices_in_sync )()
123181
124- def scale_up_by_one (self , device ):
125- '''Scale device group up by one device
126-
127- :param device: ManagementRoot object -- device to add to device group
128- '''
129-
130- device_name = get_device_info (device ).name
131- if device_name in self ._get_device_names_in_group ():
132- msg = 'Device: %r is already in device group' % device_name
133- raise DeviceGroupOperationNotSupported (msg )
134- self ._check_device_failover_status (device , 'In Sync' )
135- self ._add_device_to_device_group (device )
136- device .tm .sys .config .exec_cmd ('save' )
137- self .devices .append (device )
138- self .ensure_all_devices_in_sync ()
139-
140- def scale_down_by_one (self , device ):
141- '''Scale device group down by one device
142-
143- :param device: ManagementRoot object -- device to delete from device
144- group
145- '''
146-
147- device_name = get_device_info (device ).name
148- if device_name not in self ._get_device_names_in_group ():
149- msg = 'Device: %r is not in device group' % device_name
150- raise DeviceGroupOperationNotSupported (msg )
151- self ._delete_device_from_device_group (device )
152- device .tm .sys .config .exec_cmd ('save' )
153- name_to_objects = get_device_names_to_objects (self .devices )
154- self .devices .remove (name_to_objects [device_name ])
155- self .ensure_all_devices_in_sync ()
156-
157- def cleanup_scaled_down_device (self , device ):
158- '''Remove all devices from device group on orphaned device.
159-
160- :param device: bigip object -- device to cleanup
161- '''
162-
163- dg = self ._delete_all_devices_from_device_group (device )
164- dg .delete ()
165-
166182 def _get_device_names_in_group (self ):
167183 '''_get_device_names_in_group
168184
0 commit comments