applied post-review changes
This commit is contained in:
@@ -19,7 +19,7 @@ from swift_utils import (
|
|||||||
setup_ipv6,
|
setup_ipv6,
|
||||||
update_rings,
|
update_rings,
|
||||||
balance_rings,
|
balance_rings,
|
||||||
builders_synced,
|
fully_synced,
|
||||||
sync_proxy_rings,
|
sync_proxy_rings,
|
||||||
update_min_part_hours,
|
update_min_part_hours,
|
||||||
broadcast_rings_available,
|
broadcast_rings_available,
|
||||||
@@ -331,8 +331,8 @@ def cluster_non_leader_actions():
|
|||||||
rq_key = SwiftProxyClusterRPC.KEY_STOP_PROXY_SVC
|
rq_key = SwiftProxyClusterRPC.KEY_STOP_PROXY_SVC
|
||||||
token = settings.get(rq_key, None)
|
token = settings.get(rq_key, None)
|
||||||
if token:
|
if token:
|
||||||
log("Peer request to stop proxy service received (%s)" % (token),
|
log("Peer request to stop proxy service received (%s) - sending ack" %
|
||||||
level=INFO)
|
(token), level=INFO)
|
||||||
service_stop('swift-proxy')
|
service_stop('swift-proxy')
|
||||||
peers_only = settings.get('peers-only', None)
|
peers_only = settings.get('peers-only', None)
|
||||||
rq = SwiftProxyClusterRPC().stop_proxy_ack(echo_token=token,
|
rq = SwiftProxyClusterRPC().stop_proxy_ack(echo_token=token,
|
||||||
@@ -347,22 +347,24 @@ def cluster_non_leader_actions():
|
|||||||
log("No update available", level=DEBUG)
|
log("No update available", level=DEBUG)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
builders_only = int(settings.get('sync-only-builders', 0))
|
||||||
path = os.path.basename(get_www_dir())
|
path = os.path.basename(get_www_dir())
|
||||||
try:
|
try:
|
||||||
sync_proxy_rings('http://%s/%s' % (broker, path))
|
sync_proxy_rings('http://%s/%s' % (broker, path),
|
||||||
|
rings=not builders_only)
|
||||||
except subprocess.CalledProcessError:
|
except subprocess.CalledProcessError:
|
||||||
log("Ring builder sync failed, builders not yet available - "
|
log("Ring builder sync failed, builders not yet available - "
|
||||||
"leader not ready?", level=WARNING)
|
"leader not ready?", level=WARNING)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# Re-enable the proxy once all builders are synced
|
# Re-enable the proxy once all builders and rings are synced
|
||||||
if builders_synced():
|
if fully_synced():
|
||||||
log("Ring builders synced - starting proxy", level=INFO)
|
log("Ring builders synced - starting proxy", level=INFO)
|
||||||
CONFIGS.write_all()
|
CONFIGS.write_all()
|
||||||
service_start('swift-proxy')
|
service_start('swift-proxy')
|
||||||
else:
|
else:
|
||||||
log("Not all builders synced yet - waiting for peer sync before "
|
log("Not all builders and rings synced yet - waiting for peer sync "
|
||||||
"starting proxy", level=INFO)
|
"before starting proxy", level=INFO)
|
||||||
|
|
||||||
|
|
||||||
@hooks.hook('cluster-relation-changed',
|
@hooks.hook('cluster-relation-changed',
|
||||||
|
|||||||
@@ -174,10 +174,11 @@ class SwiftProxyClusterRPC(object):
|
|||||||
'builder-broker': None,
|
'builder-broker': None,
|
||||||
self.KEY_STOP_PROXY_SVC: None,
|
self.KEY_STOP_PROXY_SVC: None,
|
||||||
self.KEY_STOP_PROXY_SVC_ACK: None,
|
self.KEY_STOP_PROXY_SVC_ACK: None,
|
||||||
'peers-only': None}}
|
'peers-only': None,
|
||||||
|
'sync-only-builders': None}}
|
||||||
return copy.deepcopy(templates[self._version])
|
return copy.deepcopy(templates[self._version])
|
||||||
|
|
||||||
def stop_proxy_request(self, peers_only=None):
|
def stop_proxy_request(self, peers_only=False):
|
||||||
"""Request to stop peer proxy service.
|
"""Request to stop peer proxy service.
|
||||||
|
|
||||||
NOTE: leader action
|
NOTE: leader action
|
||||||
@@ -185,7 +186,9 @@ class SwiftProxyClusterRPC(object):
|
|||||||
rq = self.template()
|
rq = self.template()
|
||||||
rq['trigger'] = str(uuid.uuid4())
|
rq['trigger'] = str(uuid.uuid4())
|
||||||
rq[self.KEY_STOP_PROXY_SVC] = rq['trigger']
|
rq[self.KEY_STOP_PROXY_SVC] = rq['trigger']
|
||||||
rq['peers-only'] = peers_only
|
if peers_only:
|
||||||
|
rq['peers-only'] = 1
|
||||||
|
|
||||||
return rq
|
return rq
|
||||||
|
|
||||||
def stop_proxy_ack(self, echo_token, echo_peers_only):
|
def stop_proxy_ack(self, echo_token, echo_peers_only):
|
||||||
@@ -200,7 +203,8 @@ class SwiftProxyClusterRPC(object):
|
|||||||
rq['peers-only'] = echo_peers_only
|
rq['peers-only'] = echo_peers_only
|
||||||
return rq
|
return rq
|
||||||
|
|
||||||
def sync_rings_request(self, broker_host, use_trigger=True):
|
def sync_rings_request(self, broker_host, use_trigger=True,
|
||||||
|
builders_only=False):
|
||||||
"""Request for peer to sync rings.
|
"""Request for peer to sync rings.
|
||||||
|
|
||||||
NOTE: leader action
|
NOTE: leader action
|
||||||
@@ -212,6 +216,9 @@ class SwiftProxyClusterRPC(object):
|
|||||||
if use_trigger:
|
if use_trigger:
|
||||||
rq['trigger'] = str(uuid.uuid4())
|
rq['trigger'] = str(uuid.uuid4())
|
||||||
|
|
||||||
|
if builders_only:
|
||||||
|
rq['sync-only-builders'] = 1
|
||||||
|
|
||||||
rq['builder-broker'] = broker_host
|
rq['builder-broker'] = broker_host
|
||||||
return rq
|
return rq
|
||||||
|
|
||||||
@@ -564,7 +571,7 @@ def setup_ipv6():
|
|||||||
apt_install('haproxy/trusty-backports', fatal=True)
|
apt_install('haproxy/trusty-backports', fatal=True)
|
||||||
|
|
||||||
|
|
||||||
def sync_proxy_rings(broker_url):
|
def sync_proxy_rings(broker_url, builders=True, rings=True):
|
||||||
"""The leader proxy is responsible for intialising, updating and
|
"""The leader proxy is responsible for intialising, updating and
|
||||||
rebalancing the ring. Once the leader is ready the rings must then be
|
rebalancing the ring. Once the leader is ready the rings must then be
|
||||||
synced into each other proxy unit.
|
synced into each other proxy unit.
|
||||||
@@ -578,6 +585,7 @@ def sync_proxy_rings(broker_url):
|
|||||||
synced = []
|
synced = []
|
||||||
tmpdir = tempfile.mkdtemp(prefix='swiftrings')
|
tmpdir = tempfile.mkdtemp(prefix='swiftrings')
|
||||||
for server in ['account', 'object', 'container']:
|
for server in ['account', 'object', 'container']:
|
||||||
|
if builders:
|
||||||
url = '%s/%s.builder' % (broker_url, server)
|
url = '%s/%s.builder' % (broker_url, server)
|
||||||
log('Fetching %s.' % url, level=DEBUG)
|
log('Fetching %s.' % url, level=DEBUG)
|
||||||
builder = "%s.builder" % (server)
|
builder = "%s.builder" % (server)
|
||||||
@@ -586,6 +594,7 @@ def sync_proxy_rings(broker_url):
|
|||||||
subprocess.check_call(cmd)
|
subprocess.check_call(cmd)
|
||||||
synced.append(builder)
|
synced.append(builder)
|
||||||
|
|
||||||
|
if rings:
|
||||||
url = '%s/%s.%s' % (broker_url, server, SWIFT_RING_EXT)
|
url = '%s/%s.%s' % (broker_url, server, SWIFT_RING_EXT)
|
||||||
log('Fetching %s.' % url, level=DEBUG)
|
log('Fetching %s.' % url, level=DEBUG)
|
||||||
ring = '%s.%s' % (server, SWIFT_RING_EXT)
|
ring = '%s.%s' % (server, SWIFT_RING_EXT)
|
||||||
@@ -609,19 +618,24 @@ def ensure_www_dir_permissions(www_dir):
|
|||||||
os.chown(www_dir, uid, gid)
|
os.chown(www_dir, uid, gid)
|
||||||
|
|
||||||
|
|
||||||
def update_www_rings():
|
def update_www_rings(rings=True, builders=True):
|
||||||
"""Copy rings to apache www dir.
|
"""Copy rings to apache www dir.
|
||||||
|
|
||||||
Try to do this as atomically as possible to avoid races with storage nodes
|
Try to do this as atomically as possible to avoid races with storage nodes
|
||||||
syncing rings.
|
syncing rings.
|
||||||
"""
|
"""
|
||||||
|
if not (rings or builders):
|
||||||
|
return
|
||||||
|
|
||||||
tmp_dir = tempfile.mkdtemp(prefix='swift-rings-www-tmp')
|
tmp_dir = tempfile.mkdtemp(prefix='swift-rings-www-tmp')
|
||||||
for ring, builder_path in SWIFT_RINGS.iteritems():
|
for ring, builder_path in SWIFT_RINGS.iteritems():
|
||||||
|
if rings:
|
||||||
ringfile = '%s.%s' % (ring, SWIFT_RING_EXT)
|
ringfile = '%s.%s' % (ring, SWIFT_RING_EXT)
|
||||||
src = os.path.join(SWIFT_CONF_DIR, ringfile)
|
src = os.path.join(SWIFT_CONF_DIR, ringfile)
|
||||||
dst = os.path.join(tmp_dir, ringfile)
|
dst = os.path.join(tmp_dir, ringfile)
|
||||||
shutil.copyfile(src, dst)
|
shutil.copyfile(src, dst)
|
||||||
|
|
||||||
|
if builders:
|
||||||
src = builder_path
|
src = builder_path
|
||||||
dst = os.path.join(tmp_dir, os.path.basename(builder_path))
|
dst = os.path.join(tmp_dir, os.path.basename(builder_path))
|
||||||
shutil.copyfile(src, dst)
|
shutil.copyfile(src, dst)
|
||||||
@@ -681,13 +695,17 @@ def sync_builders_and_rings_if_changed(f):
|
|||||||
rings_changed = rings_after != rings_before
|
rings_changed = rings_after != rings_before
|
||||||
builders_changed = builders_after != builders_before
|
builders_changed = builders_after != builders_before
|
||||||
if rings_changed or builders_changed:
|
if rings_changed or builders_changed:
|
||||||
path = os.path.join(SWIFT_CONF_DIR, '*.%s' % (SWIFT_RING_EXT))
|
rings_path = os.path.join(SWIFT_CONF_DIR, '*.%s' %
|
||||||
if len(glob.glob(path)) == len(SWIFT_RINGS):
|
(SWIFT_RING_EXT))
|
||||||
# Copy to www dir
|
if len(glob.glob(rings_path)) == len(SWIFT_RINGS):
|
||||||
|
# Copy all to www dir
|
||||||
update_www_rings()
|
update_www_rings()
|
||||||
# Trigger sync
|
# Trigger sync
|
||||||
cluster_sync_rings(peers_only=not rings_changed)
|
cluster_sync_rings(peers_only=not rings_changed)
|
||||||
else:
|
else:
|
||||||
|
# Copy just builders to www dir
|
||||||
|
update_www_rings(rings=False)
|
||||||
|
cluster_sync_rings(peers_only=True)
|
||||||
log("Rings not ready for sync - skipping", level=DEBUG)
|
log("Rings not ready for sync - skipping", level=DEBUG)
|
||||||
else:
|
else:
|
||||||
log("Rings/builders unchanged so skipping sync", level=DEBUG)
|
log("Rings/builders unchanged so skipping sync", level=DEBUG)
|
||||||
@@ -749,7 +767,7 @@ def mark_www_rings_deleted():
|
|||||||
os.rename(path, "%s.deleted" % (path))
|
os.rename(path, "%s.deleted" % (path))
|
||||||
|
|
||||||
|
|
||||||
def notify_peers_builders_available(use_trigger=True):
|
def notify_peers_builders_available(use_trigger=True, builders_only=True):
|
||||||
"""Notify peer swift-proxy units that they should synchronise ring and
|
"""Notify peer swift-proxy units that they should synchronise ring and
|
||||||
builder files.
|
builder files.
|
||||||
|
|
||||||
@@ -769,7 +787,8 @@ def notify_peers_builders_available(use_trigger=True):
|
|||||||
# Notify peers that builders are available
|
# Notify peers that builders are available
|
||||||
log("Notifying peer(s) that rings are ready for sync.", level=INFO)
|
log("Notifying peer(s) that rings are ready for sync.", level=INFO)
|
||||||
rq = SwiftProxyClusterRPC().sync_rings_request(hostname,
|
rq = SwiftProxyClusterRPC().sync_rings_request(hostname,
|
||||||
use_trigger=use_trigger)
|
use_trigger=use_trigger,
|
||||||
|
builders_only=builders_only)
|
||||||
for rid in relation_ids('cluster'):
|
for rid in relation_ids('cluster'):
|
||||||
log("Notifying rid=%s" % (rid), level=DEBUG)
|
log("Notifying rid=%s" % (rid), level=DEBUG)
|
||||||
relation_set(relation_id=rid, relation_settings=rq)
|
relation_set(relation_id=rid, relation_settings=rq)
|
||||||
@@ -821,11 +840,6 @@ def cluster_sync_rings(peers_only=False):
|
|||||||
rel_ids = relation_ids('cluster')
|
rel_ids = relation_ids('cluster')
|
||||||
trigger = str(uuid.uuid4())
|
trigger = str(uuid.uuid4())
|
||||||
|
|
||||||
if peers_only:
|
|
||||||
peers_only = 1
|
|
||||||
else:
|
|
||||||
peers_only = 0
|
|
||||||
|
|
||||||
log("Sending request to stop proxy service to all peers (%s)" % (trigger),
|
log("Sending request to stop proxy service to all peers (%s)" % (trigger),
|
||||||
level=INFO)
|
level=INFO)
|
||||||
rq = SwiftProxyClusterRPC().stop_proxy_request(peers_only)
|
rq = SwiftProxyClusterRPC().stop_proxy_request(peers_only)
|
||||||
@@ -860,14 +874,19 @@ def notify_storage_rings_available():
|
|||||||
rings_url=rings_url, trigger=trigger)
|
rings_url=rings_url, trigger=trigger)
|
||||||
|
|
||||||
|
|
||||||
def builders_synced():
|
def fully_synced():
|
||||||
"""Check that we have all the ring builders synced from the leader.
|
"""Check that we have all the rings and builders synced from the leader.
|
||||||
|
|
||||||
Returns True if we have all ring builders.
|
Returns True if we have all ring builders.
|
||||||
"""
|
"""
|
||||||
for ring in SWIFT_RINGS.itervalues():
|
for ring, builder in SWIFT_RINGS.iteritems():
|
||||||
if not os.path.exists(ring):
|
ringfile = '%s.%s' % (ring, SWIFT_RING_EXT)
|
||||||
log("Builder not yet synced - %s" % (ring), level=DEBUG)
|
if not os.path.exists(builder):
|
||||||
|
log("Builder not yet synced - %s" % (builder), level=DEBUG)
|
||||||
|
return False
|
||||||
|
|
||||||
|
if not os.path.exists(ringfile):
|
||||||
|
log("Ring not yet synced - %s" % (ringfile), level=DEBUG)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|||||||
@@ -123,14 +123,16 @@ class SwiftUtilsTestCase(unittest.TestCase):
|
|||||||
'builder-broker': None,
|
'builder-broker': None,
|
||||||
'peers-only': True,
|
'peers-only': True,
|
||||||
'stop-proxy-service': 'test-uuid',
|
'stop-proxy-service': 'test-uuid',
|
||||||
'stop-proxy-service-ack': None}, rq)
|
'stop-proxy-service-ack': None,
|
||||||
|
'sync-only-builders': None}, rq)
|
||||||
|
|
||||||
rq = rpc.stop_proxy_request()
|
rq = rpc.stop_proxy_request()
|
||||||
self.assertEqual({'trigger': 'test-uuid',
|
self.assertEqual({'trigger': 'test-uuid',
|
||||||
'builder-broker': None,
|
'builder-broker': None,
|
||||||
'peers-only': None,
|
'peers-only': None,
|
||||||
'stop-proxy-service': 'test-uuid',
|
'stop-proxy-service': 'test-uuid',
|
||||||
'stop-proxy-service-ack': None}, rq)
|
'stop-proxy-service-ack': None,
|
||||||
|
'sync-only-builders': None}, rq)
|
||||||
|
|
||||||
@mock.patch('swift_utils.uuid')
|
@mock.patch('swift_utils.uuid')
|
||||||
def test_cluster_rpc_stop_proxy_ack(self, mock_uuid):
|
def test_cluster_rpc_stop_proxy_ack(self, mock_uuid):
|
||||||
@@ -141,7 +143,8 @@ class SwiftUtilsTestCase(unittest.TestCase):
|
|||||||
'builder-broker': None,
|
'builder-broker': None,
|
||||||
'peers-only': '1',
|
'peers-only': '1',
|
||||||
'stop-proxy-service': None,
|
'stop-proxy-service': None,
|
||||||
'stop-proxy-service-ack': 'token1'}, rq)
|
'stop-proxy-service-ack': 'token1',
|
||||||
|
'sync-only-builders': None}, rq)
|
||||||
|
|
||||||
@mock.patch('swift_utils.uuid')
|
@mock.patch('swift_utils.uuid')
|
||||||
def test_cluster_rpc_sync_request(self, mock_uuid):
|
def test_cluster_rpc_sync_request(self, mock_uuid):
|
||||||
@@ -152,7 +155,8 @@ class SwiftUtilsTestCase(unittest.TestCase):
|
|||||||
'builder-broker': 'HostA',
|
'builder-broker': 'HostA',
|
||||||
'peers-only': None,
|
'peers-only': None,
|
||||||
'stop-proxy-service': None,
|
'stop-proxy-service': None,
|
||||||
'stop-proxy-service-ack': None}, rq)
|
'stop-proxy-service-ack': None,
|
||||||
|
'sync-only-builders': None}, rq)
|
||||||
|
|
||||||
def test_all_responses_equal(self):
|
def test_all_responses_equal(self):
|
||||||
responses = [{'a': 1, 'c': 3}]
|
responses = [{'a': 1, 'c': 3}]
|
||||||
|
|||||||
Reference in New Issue
Block a user