2012-12-12 09:18:54 -08:00
|
|
|
#!/usr/bin/python
|
|
|
|
|
|
|
|
import os
|
|
|
|
import sys
|
2013-09-27 13:02:37 +01:00
|
|
|
import subprocess
|
|
|
|
|
|
|
|
from swift_utils import (
|
2014-12-04 18:41:32 +00:00
|
|
|
SwiftProxyCharmException,
|
2013-09-27 13:02:37 +01:00
|
|
|
register_configs,
|
|
|
|
restart_map,
|
|
|
|
determine_packages,
|
|
|
|
ensure_swift_dir,
|
2014-12-01 18:37:56 +00:00
|
|
|
SWIFT_RINGS,
|
|
|
|
get_www_dir,
|
2013-09-27 13:02:37 +01:00
|
|
|
initialize_ring,
|
|
|
|
SWIFT_HA_RES,
|
|
|
|
get_zone,
|
2013-09-27 13:16:22 +01:00
|
|
|
do_openstack_upgrade,
|
2014-12-01 18:37:56 +00:00
|
|
|
setup_ipv6,
|
2014-12-09 15:18:08 +00:00
|
|
|
update_rings,
|
2014-12-01 18:37:56 +00:00
|
|
|
balance_rings,
|
2014-12-09 22:57:39 +00:00
|
|
|
fully_synced,
|
2014-12-01 18:37:56 +00:00
|
|
|
sync_proxy_rings,
|
2014-12-02 17:08:55 +00:00
|
|
|
broadcast_rings_available,
|
2014-12-01 18:37:56 +00:00
|
|
|
mark_www_rings_deleted,
|
2014-12-04 18:41:32 +00:00
|
|
|
SwiftProxyClusterRPC,
|
2014-12-04 20:58:15 +00:00
|
|
|
get_first_available_value,
|
|
|
|
all_responses_equal,
|
2014-12-09 21:57:27 +00:00
|
|
|
ensure_www_dir_permissions,
|
2013-09-27 13:02:37 +01:00
|
|
|
)
|
|
|
|
|
2014-12-01 18:37:56 +00:00
|
|
|
import charmhelpers.contrib.openstack.utils as openstack
|
|
|
|
from charmhelpers.contrib.hahelpers.cluster import (
|
|
|
|
is_elected_leader,
|
|
|
|
is_crm_leader
|
|
|
|
)
|
2013-09-27 13:02:37 +01:00
|
|
|
from charmhelpers.core.hookenv import (
|
|
|
|
config,
|
2014-12-05 13:21:52 +00:00
|
|
|
local_unit,
|
2013-09-27 13:02:37 +01:00
|
|
|
unit_get,
|
|
|
|
relation_set,
|
|
|
|
relation_ids,
|
|
|
|
relation_get,
|
2014-12-01 18:37:56 +00:00
|
|
|
related_units,
|
2014-10-20 13:43:39 +01:00
|
|
|
log,
|
2014-12-01 18:37:56 +00:00
|
|
|
DEBUG,
|
2014-10-21 12:45:36 +01:00
|
|
|
INFO,
|
2014-10-20 13:43:39 +01:00
|
|
|
WARNING,
|
2014-12-17 09:51:47 +00:00
|
|
|
ERROR,
|
2013-09-27 13:02:37 +01:00
|
|
|
Hooks, UnregisteredHookError,
|
2014-12-01 18:37:56 +00:00
|
|
|
open_port,
|
2013-09-27 13:02:37 +01:00
|
|
|
)
|
|
|
|
from charmhelpers.core.host import (
|
|
|
|
service_restart,
|
2014-10-20 11:05:09 +01:00
|
|
|
service_stop,
|
|
|
|
service_start,
|
2014-12-01 18:37:56 +00:00
|
|
|
restart_on_change,
|
2013-09-27 13:02:37 +01:00
|
|
|
)
|
|
|
|
from charmhelpers.fetch import (
|
|
|
|
apt_install,
|
2014-12-01 18:37:56 +00:00
|
|
|
apt_update,
|
2013-09-27 13:02:37 +01:00
|
|
|
)
|
2013-09-27 17:11:20 +01:00
|
|
|
from charmhelpers.payload.execd import execd_preinstall
|
2014-07-14 15:03:48 +01:00
|
|
|
from charmhelpers.contrib.openstack.ip import (
|
|
|
|
canonical_url,
|
2014-12-01 18:37:56 +00:00
|
|
|
PUBLIC,
|
|
|
|
INTERNAL,
|
|
|
|
ADMIN,
|
2014-07-14 15:03:48 +01:00
|
|
|
)
|
2014-07-16 14:43:20 +01:00
|
|
|
from charmhelpers.contrib.network.ip import (
|
|
|
|
get_iface_for_address,
|
2014-09-26 12:35:16 +01:00
|
|
|
get_netmask_for_address,
|
2014-09-30 15:48:30 +08:00
|
|
|
get_address_in_network,
|
2014-09-20 23:49:25 +08:00
|
|
|
get_ipv6_addr,
|
2014-12-01 18:37:56 +00:00
|
|
|
is_ipv6,
|
2014-12-09 15:18:08 +00:00
|
|
|
format_ipv6_addr,
|
2014-07-16 14:43:20 +01:00
|
|
|
)
|
2014-09-30 09:27:09 +01:00
|
|
|
from charmhelpers.contrib.openstack.context import ADDRESS_TYPES
|
|
|
|
|
2013-02-27 16:07:46 +00:00
|
|
|
extra_pkgs = [
|
|
|
|
"haproxy",
|
|
|
|
"python-jinja2"
|
2013-09-27 13:02:37 +01:00
|
|
|
]
|
|
|
|
|
|
|
|
hooks = Hooks()
|
|
|
|
CONFIGS = register_configs()
|
2013-03-12 11:17:32 +00:00
|
|
|
|
2013-09-27 13:02:37 +01:00
|
|
|
|
|
|
|
@hooks.hook('install')
|
2012-12-12 09:18:54 -08:00
|
|
|
def install():
|
2013-09-27 17:11:20 +01:00
|
|
|
execd_preinstall()
|
2013-09-27 13:02:37 +01:00
|
|
|
src = config('openstack-origin')
|
2012-12-12 09:18:54 -08:00
|
|
|
if src != 'distro':
|
|
|
|
openstack.configure_installation_source(src)
|
2014-12-01 18:37:56 +00:00
|
|
|
|
2013-09-27 13:02:37 +01:00
|
|
|
apt_update(fatal=True)
|
2012-12-12 09:18:54 -08:00
|
|
|
rel = openstack.get_os_codename_install_source(src)
|
2013-09-27 13:02:37 +01:00
|
|
|
pkgs = determine_packages(rel)
|
|
|
|
apt_install(pkgs, fatal=True)
|
|
|
|
apt_install(extra_pkgs, fatal=True)
|
|
|
|
ensure_swift_dir()
|
2014-10-20 11:05:09 +01:00
|
|
|
|
2014-12-01 18:37:56 +00:00
|
|
|
if is_elected_leader(SWIFT_HA_RES):
|
|
|
|
log("Leader established, generating ring builders", level=INFO)
|
2014-10-20 11:05:09 +01:00
|
|
|
# initialize new storage rings.
|
2014-12-01 23:54:03 +00:00
|
|
|
for path in SWIFT_RINGS.itervalues():
|
2014-12-01 18:37:56 +00:00
|
|
|
initialize_ring(path,
|
2014-10-20 11:05:09 +01:00
|
|
|
config('partition-power'),
|
|
|
|
config('replicas'),
|
|
|
|
config('min-hours'))
|
2012-12-12 09:18:54 -08:00
|
|
|
|
|
|
|
# configure a directory on webserver for distributing rings.
|
2014-12-09 21:57:27 +00:00
|
|
|
ensure_www_dir_permissions(get_www_dir())
|
2012-12-12 09:18:54 -08:00
|
|
|
|
|
|
|
|
2014-12-01 18:37:56 +00:00
|
|
|
@hooks.hook('config-changed')
|
|
|
|
@restart_on_change(restart_map())
|
|
|
|
def config_changed():
|
|
|
|
if config('prefer-ipv6'):
|
|
|
|
setup_ipv6()
|
|
|
|
|
|
|
|
configure_https()
|
|
|
|
open_port(config('bind-port'))
|
|
|
|
|
|
|
|
# Determine whether or not we should do an upgrade.
|
|
|
|
if openstack.openstack_upgrade_available('python-swift'):
|
|
|
|
do_openstack_upgrade(CONFIGS)
|
|
|
|
|
2014-12-10 10:37:43 +00:00
|
|
|
update_rings(min_part_hours=config('min-hours'))
|
2014-12-01 18:37:56 +00:00
|
|
|
|
2014-12-09 21:26:55 +00:00
|
|
|
if not config('disable-ring-balance') and is_elected_leader(SWIFT_HA_RES):
|
2014-12-09 15:18:08 +00:00
|
|
|
# Try ring balance. If rings are balanced, no sync will occur.
|
|
|
|
balance_rings()
|
2014-12-01 18:37:56 +00:00
|
|
|
|
|
|
|
for r_id in relation_ids('identity-service'):
|
|
|
|
keystone_joined(relid=r_id)
|
|
|
|
|
|
|
|
|
2013-09-27 13:02:37 +01:00
|
|
|
@hooks.hook('identity-service-relation-joined')
|
2012-12-12 09:18:54 -08:00
|
|
|
def keystone_joined(relid=None):
|
2014-12-01 18:37:56 +00:00
|
|
|
if not is_elected_leader(SWIFT_HA_RES):
|
2013-02-27 21:25:38 +00:00
|
|
|
return
|
2014-12-01 18:37:56 +00:00
|
|
|
|
2013-09-27 13:02:37 +01:00
|
|
|
port = config('bind-port')
|
2014-07-14 15:42:25 +01:00
|
|
|
admin_url = '%s:%s' % (canonical_url(CONFIGS, ADMIN), port)
|
|
|
|
internal_url = '%s:%s/v1/AUTH_$(tenant_id)s' % \
|
2014-07-14 15:03:48 +01:00
|
|
|
(canonical_url(CONFIGS, INTERNAL), port)
|
2014-07-14 15:42:25 +01:00
|
|
|
public_url = '%s:%s/v1/AUTH_$(tenant_id)s' % \
|
2014-07-14 15:03:48 +01:00
|
|
|
(canonical_url(CONFIGS, PUBLIC), port)
|
2013-09-27 13:02:37 +01:00
|
|
|
relation_set(service='swift',
|
|
|
|
region=config('region'),
|
2014-06-27 11:56:24 +01:00
|
|
|
public_url=public_url,
|
|
|
|
internal_url=internal_url,
|
2013-09-27 13:02:37 +01:00
|
|
|
admin_url=admin_url,
|
|
|
|
requested_roles=config('operator-roles'),
|
|
|
|
relation_id=relid)
|
2012-12-12 09:18:54 -08:00
|
|
|
|
|
|
|
|
2013-09-27 13:02:37 +01:00
|
|
|
@hooks.hook('identity-service-relation-changed')
|
|
|
|
@restart_on_change(restart_map())
|
2012-12-12 09:18:54 -08:00
|
|
|
def keystone_changed():
|
2013-09-27 13:02:37 +01:00
|
|
|
configure_https()
|
2012-12-12 09:18:54 -08:00
|
|
|
|
|
|
|
|
2014-12-01 18:37:56 +00:00
|
|
|
@hooks.hook('swift-storage-relation-joined')
|
|
|
|
def storage_joined():
|
|
|
|
if not is_elected_leader(SWIFT_HA_RES):
|
|
|
|
log("New storage relation joined - stopping proxy until ring builder "
|
|
|
|
"synced", level=INFO)
|
|
|
|
service_stop('swift-proxy')
|
2013-02-27 16:07:46 +00:00
|
|
|
|
2014-12-04 15:49:24 +00:00
|
|
|
# This unit is not currently responsible for distributing rings but
|
|
|
|
# may become so at some time in the future so we do this to avoid the
|
|
|
|
# possibility of storage nodes getting out-of-date rings by deprecating
|
|
|
|
# any existing ones from the www dir.
|
2014-12-01 18:37:56 +00:00
|
|
|
mark_www_rings_deleted()
|
2012-12-12 09:18:54 -08:00
|
|
|
|
2013-03-12 11:17:32 +00:00
|
|
|
|
2013-09-27 13:02:37 +01:00
|
|
|
@hooks.hook('swift-storage-relation-changed')
|
|
|
|
@restart_on_change(restart_map())
|
2012-12-18 11:59:19 -08:00
|
|
|
def storage_changed():
|
2014-12-09 15:18:08 +00:00
|
|
|
"""Storage relation.
|
|
|
|
|
|
|
|
Only the leader unit can update and distribute rings so if we are not the
|
|
|
|
leader we ignore this event and wait for a resync request from the leader.
|
|
|
|
"""
|
2014-12-01 18:37:56 +00:00
|
|
|
if not is_elected_leader(SWIFT_HA_RES):
|
|
|
|
log("Not the leader - ignoring storage relation until leader ready.",
|
|
|
|
level=DEBUG)
|
|
|
|
return
|
|
|
|
|
|
|
|
log("Leader established, updating ring builders", level=INFO)
|
2014-12-09 15:18:08 +00:00
|
|
|
addr = relation_get('private-address')
|
2014-08-13 20:15:41 +08:00
|
|
|
if config('prefer-ipv6'):
|
2014-12-09 15:18:08 +00:00
|
|
|
host_ip = format_ipv6_addr(addr)
|
|
|
|
if not host_ip:
|
|
|
|
errmsg = ("Did not get IPv6 address from storage relation "
|
|
|
|
"(got=%s)" % (addr))
|
|
|
|
raise SwiftProxyCharmException(errmsg)
|
2014-08-13 20:15:41 +08:00
|
|
|
else:
|
2014-12-09 15:18:08 +00:00
|
|
|
host_ip = openstack.get_host_ip(addr)
|
2014-09-18 21:16:28 +08:00
|
|
|
|
2014-12-01 18:37:56 +00:00
|
|
|
zone = get_zone(config('zone-assignment'))
|
|
|
|
node_settings = {
|
|
|
|
'ip': host_ip,
|
|
|
|
'zone': zone,
|
|
|
|
'account_port': relation_get('account_port'),
|
|
|
|
'object_port': relation_get('object_port'),
|
|
|
|
'container_port': relation_get('container_port'),
|
|
|
|
}
|
2014-10-20 19:27:50 +01:00
|
|
|
|
2014-12-01 18:37:56 +00:00
|
|
|
if None in node_settings.itervalues():
|
2014-12-01 23:54:03 +00:00
|
|
|
missing = [k for k, v in node_settings.iteritems() if v is None]
|
2014-12-01 18:37:56 +00:00
|
|
|
log("Relation not ready - some required values not provided by "
|
|
|
|
"relation (missing=%s)" % (', '.join(missing)), level=INFO)
|
|
|
|
return None
|
2014-10-20 19:27:50 +01:00
|
|
|
|
2014-12-01 18:37:56 +00:00
|
|
|
for k in ['zone', 'account_port', 'object_port', 'container_port']:
|
|
|
|
node_settings[k] = int(node_settings[k])
|
2012-12-12 09:18:54 -08:00
|
|
|
|
2014-12-01 18:37:56 +00:00
|
|
|
CONFIGS.write_all()
|
2014-10-20 19:41:37 +01:00
|
|
|
|
2014-12-01 18:37:56 +00:00
|
|
|
# Allow for multiple devs per unit, passed along as a : separated list
|
2014-12-09 15:18:08 +00:00
|
|
|
# Update and balance rings.
|
2014-12-09 15:33:54 +00:00
|
|
|
devs = relation_get('device')
|
|
|
|
if devs:
|
2014-12-16 14:50:01 +00:00
|
|
|
node_settings['devices'] = devs.split(':')
|
2014-12-09 15:33:54 +00:00
|
|
|
|
|
|
|
update_rings(node_settings)
|
2014-12-09 15:18:08 +00:00
|
|
|
# Restart proxy here in case no config changes made (so
|
|
|
|
# restart_on_change() ineffective).
|
|
|
|
service_restart('swift-proxy')
|
2012-12-12 09:18:54 -08:00
|
|
|
|
2013-03-12 11:17:32 +00:00
|
|
|
|
2013-09-27 13:02:37 +01:00
|
|
|
@hooks.hook('swift-storage-relation-broken')
|
|
|
|
@restart_on_change(restart_map())
|
2012-12-18 11:59:19 -08:00
|
|
|
def storage_broken():
|
2013-09-27 13:02:37 +01:00
|
|
|
CONFIGS.write_all()
|
2012-12-12 09:18:54 -08:00
|
|
|
|
2013-03-12 11:17:32 +00:00
|
|
|
|
2014-09-26 12:35:16 +01:00
|
|
|
@hooks.hook('cluster-relation-joined')
|
|
|
|
def cluster_joined(relation_id=None):
|
2014-09-30 09:27:09 +01:00
|
|
|
for addr_type in ADDRESS_TYPES:
|
2014-10-20 11:05:09 +01:00
|
|
|
netaddr_cfg = 'os-{}-network'.format(addr_type)
|
|
|
|
address = get_address_in_network(config(netaddr_cfg))
|
2014-09-30 09:27:09 +01:00
|
|
|
if address:
|
2014-10-20 11:05:09 +01:00
|
|
|
settings = {'{}-address'.format(addr_type): address}
|
|
|
|
relation_set(relation_id=relation_id, relation_settings=settings)
|
|
|
|
|
2014-08-19 14:25:20 +08:00
|
|
|
if config('prefer-ipv6'):
|
2014-09-30 15:48:30 +08:00
|
|
|
private_addr = get_ipv6_addr(exc_list=[config('vip')])[0]
|
2014-10-02 10:28:13 +01:00
|
|
|
relation_set(relation_id=relation_id,
|
|
|
|
relation_settings={'private-address': private_addr})
|
2014-10-20 11:05:09 +01:00
|
|
|
else:
|
|
|
|
private_addr = unit_get('private-address')
|
|
|
|
|
|
|
|
|
2014-12-04 15:49:24 +00:00
|
|
|
def all_peers_stopped(responses):
|
|
|
|
"""Establish whether all peers have stopped their proxy services.
|
2014-12-02 14:40:58 +00:00
|
|
|
|
2014-12-04 18:51:43 +00:00
|
|
|
Each peer unit will set stop-proxy-service-ack to rq value to indicate that
|
2014-12-04 15:49:24 +00:00
|
|
|
it has stopped its proxy service. We wait for all units to be stopped
|
|
|
|
before triggering a sync. Peer services will be restarted once their rings
|
|
|
|
are synced with the leader.
|
2014-12-02 14:40:58 +00:00
|
|
|
|
|
|
|
To be safe, default expectation is that api is still running.
|
|
|
|
"""
|
2014-12-05 13:32:28 +00:00
|
|
|
rq_key = SwiftProxyClusterRPC.KEY_STOP_PROXY_SVC
|
|
|
|
ack_key = SwiftProxyClusterRPC.KEY_STOP_PROXY_SVC_ACK
|
|
|
|
token = relation_get(attribute=rq_key, unit=local_unit())
|
|
|
|
if not token or token != responses[0].get(ack_key):
|
2014-12-05 13:21:52 +00:00
|
|
|
log("Unmatched token in ack (expected=%s, got=%s)" %
|
2014-12-05 13:32:28 +00:00
|
|
|
(token, responses[0].get(ack_key)), level=DEBUG)
|
2014-12-05 13:21:52 +00:00
|
|
|
return False
|
|
|
|
|
2014-12-05 13:32:28 +00:00
|
|
|
if not all_responses_equal(responses, ack_key):
|
2014-12-02 14:40:58 +00:00
|
|
|
return False
|
|
|
|
|
|
|
|
return True
|
2014-12-02 14:21:47 +00:00
|
|
|
|
|
|
|
|
|
|
|
def cluster_leader_actions():
|
2014-12-04 16:47:09 +00:00
|
|
|
"""Cluster relation hook actions to be performed by leader units.
|
|
|
|
|
|
|
|
NOTE: must be called by leader from cluster relation hook.
|
|
|
|
"""
|
2014-12-05 12:44:14 +00:00
|
|
|
# If we have received an ack, check other units
|
2014-12-17 10:17:50 +00:00
|
|
|
settings = relation_get() or {}
|
2014-12-05 13:32:28 +00:00
|
|
|
ack_key = SwiftProxyClusterRPC.KEY_STOP_PROXY_SVC_ACK
|
2014-12-17 10:17:50 +00:00
|
|
|
|
|
|
|
# Protect against leader changing mid-sync
|
|
|
|
if settings.get(SwiftProxyClusterRPC.KEY_STOP_PROXY_SVC):
|
|
|
|
log("Sync request received yet this is leader unit. This would "
|
|
|
|
"indicate that the leader has changed mid-sync - stopping proxy "
|
|
|
|
"and notifying peers", level=ERROR)
|
|
|
|
service_stop('swift-proxy')
|
|
|
|
SwiftProxyClusterRPC().notify_leader_changed()
|
|
|
|
return
|
|
|
|
elif ack_key in settings:
|
2014-12-05 12:44:14 +00:00
|
|
|
# Find out if all peer units have been stopped.
|
|
|
|
responses = []
|
|
|
|
for rid in relation_ids('cluster'):
|
|
|
|
for unit in related_units(rid):
|
|
|
|
responses.append(relation_get(rid=rid, unit=unit))
|
|
|
|
|
|
|
|
# Ensure all peers stopped before starting sync
|
|
|
|
if all_peers_stopped(responses):
|
|
|
|
key = 'peers-only'
|
|
|
|
if not all_responses_equal(responses, key, must_exist=False):
|
|
|
|
msg = ("Did not get equal response from every peer unit for "
|
|
|
|
"'%s'" % (key))
|
|
|
|
raise SwiftProxyCharmException(msg)
|
|
|
|
|
|
|
|
peers_only = int(get_first_available_value(responses, key,
|
|
|
|
default=0))
|
|
|
|
log("Syncing rings and builders (peers-only=%s)" % (peers_only),
|
|
|
|
level=DEBUG)
|
|
|
|
broadcast_rings_available(storage=not peers_only)
|
|
|
|
else:
|
|
|
|
log("Not all peer apis stopped - skipping sync until all peers "
|
|
|
|
"ready (got %s)" % (responses), level=INFO)
|
2014-12-02 14:21:47 +00:00
|
|
|
else:
|
2014-12-05 12:44:14 +00:00
|
|
|
# Otherwise it might be a new swift-proxy unit so tell it to sync
|
|
|
|
# rings. Note that broker info may already be present in the cluster
|
|
|
|
# relation so don't use a trigger otherwise the hook will re-fire on
|
|
|
|
# all peers.
|
|
|
|
broadcast_rings_available(storage=False, use_trigger=False)
|
2014-12-02 14:21:47 +00:00
|
|
|
|
|
|
|
CONFIGS.write_all()
|
2014-12-01 18:37:56 +00:00
|
|
|
|
|
|
|
|
2014-12-02 14:21:47 +00:00
|
|
|
def cluster_non_leader_actions():
|
2014-12-04 16:47:09 +00:00
|
|
|
"""Cluster relation hook actions to be performed by non-leader units.
|
|
|
|
|
|
|
|
NOTE: must be called by non-leader from cluster relation hook.
|
|
|
|
"""
|
2014-12-17 10:17:50 +00:00
|
|
|
settings = relation_get() or {}
|
2014-12-02 14:21:47 +00:00
|
|
|
|
|
|
|
# Check whether we have been requested to stop proxy service
|
2014-12-05 13:32:28 +00:00
|
|
|
rq_key = SwiftProxyClusterRPC.KEY_STOP_PROXY_SVC
|
|
|
|
token = settings.get(rq_key, None)
|
2014-12-04 20:00:00 +00:00
|
|
|
if token:
|
2014-12-09 22:57:39 +00:00
|
|
|
log("Peer request to stop proxy service received (%s) - sending ack" %
|
|
|
|
(token), level=INFO)
|
2014-12-01 18:37:56 +00:00
|
|
|
service_stop('swift-proxy')
|
2014-12-04 20:00:00 +00:00
|
|
|
peers_only = settings.get('peers-only', None)
|
|
|
|
rq = SwiftProxyClusterRPC().stop_proxy_ack(echo_token=token,
|
|
|
|
echo_peers_only=peers_only)
|
2014-12-04 19:00:54 +00:00
|
|
|
relation_set(relation_settings=rq)
|
2014-12-01 18:37:56 +00:00
|
|
|
return
|
2013-02-27 16:07:46 +00:00
|
|
|
|
2014-12-02 14:21:47 +00:00
|
|
|
# Check if there are any builder files we can sync from the leader.
|
2014-12-01 18:37:56 +00:00
|
|
|
log("Non-leader peer - checking if updated rings available", level=DEBUG)
|
|
|
|
broker = settings.get('builder-broker', None)
|
|
|
|
if not broker:
|
|
|
|
log("No update available", level=DEBUG)
|
|
|
|
return
|
|
|
|
|
2014-12-09 22:57:39 +00:00
|
|
|
builders_only = int(settings.get('sync-only-builders', 0))
|
2014-12-01 18:37:56 +00:00
|
|
|
path = os.path.basename(get_www_dir())
|
|
|
|
try:
|
2014-12-09 22:57:39 +00:00
|
|
|
sync_proxy_rings('http://%s/%s' % (broker, path),
|
|
|
|
rings=not builders_only)
|
2014-12-01 18:37:56 +00:00
|
|
|
except subprocess.CalledProcessError:
|
|
|
|
log("Ring builder sync failed, builders not yet available - "
|
|
|
|
"leader not ready?", level=WARNING)
|
|
|
|
return None
|
|
|
|
|
2014-12-09 22:57:39 +00:00
|
|
|
# Re-enable the proxy once all builders and rings are synced
|
|
|
|
if fully_synced():
|
2014-12-01 18:37:56 +00:00
|
|
|
log("Ring builders synced - starting proxy", level=INFO)
|
|
|
|
CONFIGS.write_all()
|
|
|
|
service_start('swift-proxy')
|
|
|
|
else:
|
2014-12-09 22:57:39 +00:00
|
|
|
log("Not all builders and rings synced yet - waiting for peer sync "
|
|
|
|
"before starting proxy", level=INFO)
|
2014-12-02 14:21:47 +00:00
|
|
|
|
|
|
|
|
|
|
|
@hooks.hook('cluster-relation-changed',
|
|
|
|
'cluster-relation-departed')
|
|
|
|
@restart_on_change(restart_map())
|
|
|
|
def cluster_changed():
|
2014-12-17 09:51:47 +00:00
|
|
|
key = SwiftProxyClusterRPC.KEY_NOTIFY_LEADER_CHANGED
|
|
|
|
leader_changed = relation_get(attribute=key)
|
|
|
|
if leader_changed:
|
|
|
|
log("Leader changed notification received from peer unit. Since this "
|
|
|
|
"most likely occurred during a ring sync proxies will be "
|
|
|
|
"disabled until the leader is restored and a fresh sync request "
|
|
|
|
"is set out", level=WARNING)
|
|
|
|
service_stop("swift-proxy")
|
|
|
|
return
|
|
|
|
|
2014-12-02 14:21:47 +00:00
|
|
|
if is_elected_leader(SWIFT_HA_RES):
|
|
|
|
cluster_leader_actions()
|
|
|
|
else:
|
|
|
|
cluster_non_leader_actions()
|
2014-10-20 12:41:57 +01:00
|
|
|
|
2013-02-27 16:07:46 +00:00
|
|
|
|
2013-09-27 13:02:37 +01:00
|
|
|
@hooks.hook('ha-relation-changed')
|
2013-02-27 16:07:46 +00:00
|
|
|
def ha_relation_changed():
|
2013-09-27 13:02:37 +01:00
|
|
|
clustered = relation_get('clustered')
|
2014-12-01 18:37:56 +00:00
|
|
|
if clustered and is_crm_leader(SWIFT_HA_RES):
|
|
|
|
log("Cluster configured, notifying other services and updating "
|
|
|
|
"keystone endpoint configuration", level=INFO)
|
2013-02-27 16:07:46 +00:00
|
|
|
# Tell all related services to start using
|
2013-03-01 23:20:05 +00:00
|
|
|
# the VIP instead
|
2013-09-27 13:02:37 +01:00
|
|
|
for r_id in relation_ids('identity-service'):
|
2013-02-27 16:07:46 +00:00
|
|
|
keystone_joined(relid=r_id)
|
|
|
|
|
|
|
|
|
2013-09-27 13:02:37 +01:00
|
|
|
@hooks.hook('ha-relation-joined')
|
2013-02-27 16:07:46 +00:00
|
|
|
def ha_relation_joined():
|
|
|
|
# Obtain the config values necessary for the cluster config. These
|
|
|
|
# include multicast port and interface to bind to.
|
2013-09-27 13:02:37 +01:00
|
|
|
corosync_bindiface = config('ha-bindiface')
|
|
|
|
corosync_mcastport = config('ha-mcastport')
|
|
|
|
vip = config('vip')
|
2013-02-27 16:07:46 +00:00
|
|
|
if not vip:
|
2014-12-04 15:49:24 +00:00
|
|
|
msg = 'Unable to configure hacluster as vip not provided'
|
2014-12-04 18:41:32 +00:00
|
|
|
raise SwiftProxyCharmException(msg)
|
2013-02-27 16:07:46 +00:00
|
|
|
|
|
|
|
# Obtain resources
|
2014-12-01 18:37:56 +00:00
|
|
|
resources = {'res_swift_haproxy': 'lsb:haproxy'}
|
|
|
|
resource_params = {'res_swift_haproxy': 'op monitor interval="5s"'}
|
2014-07-16 14:43:20 +01:00
|
|
|
|
|
|
|
vip_group = []
|
|
|
|
for vip in vip.split():
|
2014-09-30 15:48:30 +08:00
|
|
|
if is_ipv6(vip):
|
|
|
|
res_swift_vip = 'ocf:heartbeat:IPv6addr'
|
|
|
|
vip_params = 'ipv6addr'
|
|
|
|
else:
|
|
|
|
res_swift_vip = 'ocf:heartbeat:IPaddr2'
|
|
|
|
vip_params = 'ip'
|
|
|
|
|
2014-07-16 14:43:20 +01:00
|
|
|
iface = get_iface_for_address(vip)
|
|
|
|
if iface is not None:
|
|
|
|
vip_key = 'res_swift_{}_vip'.format(iface)
|
2014-08-13 20:15:41 +08:00
|
|
|
resources[vip_key] = res_swift_vip
|
2014-07-16 14:43:20 +01:00
|
|
|
resource_params[vip_key] = (
|
2014-08-13 14:46:10 +08:00
|
|
|
'params {ip}="{vip}" cidr_netmask="{netmask}"'
|
2014-08-13 20:15:41 +08:00
|
|
|
' nic="{iface}"'.format(ip=vip_params,
|
2014-08-13 14:46:10 +08:00
|
|
|
vip=vip,
|
2014-07-16 14:43:20 +01:00
|
|
|
iface=iface,
|
|
|
|
netmask=get_netmask_for_address(vip))
|
|
|
|
)
|
|
|
|
vip_group.append(vip_key)
|
|
|
|
|
2014-09-04 10:21:21 +01:00
|
|
|
if len(vip_group) >= 1:
|
2014-07-16 14:43:20 +01:00
|
|
|
relation_set(groups={'grp_swift_vips': ' '.join(vip_group)})
|
|
|
|
|
2014-12-01 18:37:56 +00:00
|
|
|
init_services = {'res_swift_haproxy': 'haproxy'}
|
|
|
|
clones = {'cl_swift_haproxy': 'res_swift_haproxy'}
|
2013-09-27 13:02:37 +01:00
|
|
|
|
|
|
|
relation_set(init_services=init_services,
|
|
|
|
corosync_bindiface=corosync_bindiface,
|
|
|
|
corosync_mcastport=corosync_mcastport,
|
|
|
|
resources=resources,
|
|
|
|
resource_params=resource_params,
|
|
|
|
clones=clones)
|
|
|
|
|
|
|
|
|
|
|
|
def configure_https():
|
2014-12-01 18:37:56 +00:00
|
|
|
"""Enables SSL API Apache config if appropriate and kicks identity-service
|
2013-09-27 13:02:37 +01:00
|
|
|
with any required api updates.
|
2014-12-01 18:37:56 +00:00
|
|
|
"""
|
2013-09-27 13:02:37 +01:00
|
|
|
# need to write all to ensure changes to the entire request pipeline
|
|
|
|
# propagate (c-api, haprxy, apache)
|
|
|
|
CONFIGS.write_all()
|
|
|
|
if 'https' in CONFIGS.complete_contexts():
|
|
|
|
cmd = ['a2ensite', 'openstack_https_frontend']
|
|
|
|
subprocess.check_call(cmd)
|
|
|
|
else:
|
|
|
|
cmd = ['a2dissite', 'openstack_https_frontend']
|
|
|
|
subprocess.check_call(cmd)
|
|
|
|
|
2013-09-27 13:16:22 +01:00
|
|
|
# Apache 2.4 required enablement of configuration
|
|
|
|
if os.path.exists('/usr/sbin/a2enconf'):
|
|
|
|
subprocess.check_call(['a2enconf', 'swift-rings'])
|
|
|
|
|
2013-09-27 13:02:37 +01:00
|
|
|
for rid in relation_ids('identity-service'):
|
|
|
|
keystone_joined(relid=rid)
|
|
|
|
|
2014-12-01 18:37:56 +00:00
|
|
|
env_vars = {'OPENSTACK_SERVICE_SWIFT': 'proxy-server',
|
|
|
|
'OPENSTACK_PORT_API': config('bind-port'),
|
|
|
|
'OPENSTACK_PORT_MEMCACHED': 11211}
|
|
|
|
openstack.save_script_rc(**env_vars)
|
2013-09-27 13:16:22 +01:00
|
|
|
|
2013-09-27 13:02:37 +01:00
|
|
|
|
|
|
|
def main():
|
|
|
|
try:
|
|
|
|
hooks.execute(sys.argv)
|
|
|
|
except UnregisteredHookError as e:
|
2014-12-01 18:37:56 +00:00
|
|
|
log('Unknown hook {} - skipping.'.format(e), level=DEBUG)
|
2013-09-27 13:02:37 +01:00
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
main()
|