charm-designate-bind/src/reactive/designate_bind_handlers.py

139 lines
4.9 KiB
Python

# Copyright 2016 Canonical Ltd
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import charms.reactive as reactive
import charmhelpers.core.hookenv as hookenv
import charm.openstack.designate_bind as designate_bind
@reactive.when_not('installed')
def install_packages():
'''Install charms packages'''
designate_bind.install()
designate_bind.set_apparmor()
reactive.set_state('installed')
@reactive.when_not('rndckey.available')
def setup_secret():
'''Get the existing rndc key from leader db if one exists else generate a
new one'''
if designate_bind.init_rndckey():
reactive.set_state('rndckey.available')
@reactive.when('rndckey.available')
@reactive.when('dns-backend.related')
def send_info(dns_client):
'''Send the secret and the algorithm used to encode the key to clients'''
dns_client.send_rndckey_info(
designate_bind.get_rndc_secret(),
designate_bind.get_rndc_algorithm())
@reactive.when('rndckey.available')
@reactive.when('dns-backend.related')
def config_changed(*args):
'''Render configs and restart services if necessary'''
designate_bind.set_apparmor()
designate_bind.render_all_configs(args)
@reactive.when_not('sync.request.sent')
@reactive.when_not('zones.initialised')
@reactive.when_not('cluster.connected')
@reactive.when('installed')
def setup_sync_target_alone():
'''If this is the only unit in the application then setup a sync target.
This will likely by empty as zones.initialised is only unset when a unit
frst comes up but the presence of the target allows subsequent units to
bootstrap if leadership flips to them as they come up'''
if hookenv.is_leader():
designate_bind.setup_sync()
reactive.set_state('zones.initialised')
@reactive.when_not('zones.initialised')
@reactive.when('sync.request.sent')
@reactive.when('cluster.connected')
def update_zones_from_peer(hacluster):
'''A sync request has been sent by this unit so check if a peer has
responded and if so retrieve the zone information and install it'''
designate_bind.retrieve_zones(hacluster)
@reactive.when_not('sync.request.sent')
@reactive.when_not('zones.initialised')
@reactive.when('installed')
@reactive.when('cluster.connected')
def check_zone_status(hacluster):
'''This unit has not been initialised yet so request a zones file or
set an inital sync'''
if hookenv.is_leader():
if designate_bind.get_sync_time():
# This unit is not the leader but a sync target has already been
# set suggests this is a new unit which has been nominated as
# leader early in its lifecycle. The leader responds to sync
# requests and this unit is the leader so not worth sending out a
# sync request.
designate_bind.retrieve_zones()
else:
# This unit is the leader and no other unit has set up a sync
# target then create one since this is a new deployment
designate_bind.setup_sync()
reactive.set_state('zones.initialised')
else:
# If this unit is not the leader as is not yet initialised then request
# a zones file from a peer
designate_bind.request_sync(hacluster)
@reactive.when('zones.initialised')
@reactive.when('cluster.connected')
def process_sync_requests(hacluster):
'''If this unit is the leader process and new sync requests'''
if hookenv.is_leader():
designate_bind.process_requests(hacluster)
@reactive.when('zones.initialised')
def assess_status():
designate_bind.assess_status()
@reactive.when('config.changed.service_ips')
def service_ips_changed():
"""Reconfigure service IPs on the unit."""
designate_bind.reconfigure_service_ips()
@reactive.when('ha.connected')
def hacluster_connected(_):
"""Check if service IPs are awaiting configuration via hacluster."""
if reactive.is_flag_set(designate_bind.AWAITING_HACLUSTER_FLAG):
hookenv.log('hacluster connected, configuring Service IPs',
hookenv.INFO)
designate_bind.reconfigure_service_ips()
reactive.clear_flag(designate_bind.AWAITING_HACLUSTER_FLAG)
@reactive.when('ha-relation-departed')
def hacluster_departed(_):
"""Set blocked state if hacluster leaves and service_ips are configured."""
if hookenv.config('service_ips'):
reactive.set_flag(designate_bind.AWAITING_HACLUSTER_FLAG)
designate_bind.assess_status()