Do less work in the update-status hook
This patchset, along with the corresponding ones in charms.openstack and interface-hacluster reduce the amount of work that the charm does during an update-status hook. This also fixes the issue where an update-status hook triggered activity in the hacluster subordinate due to data being set on the interface. There is still work to be done in this area, as the configs for the charm are still being written on every update-status hook, although this doesn't result in a restart of any of the services. This probably requires a re-think of how the charm-helpers function runs; patch to charm-helpers coming up soon. This also fixes bug 1712973 where the update-pools command with empty pools errors causing the charm to error out and fail. This is undesirable, so this condition is caught and logged instead. Change-Id: I6db68a479dc903ce620ba62c1898247f71d14701 Depends-On: I3717387d1d8d2ab875d51f262efd1df7f2529689 Depends-On: I750f3c41a2f0447a47cfd19bab1d4958de4577f2 Closes-Bug: #1708396 Closes-Bug: #1712973
This commit is contained in:
parent
af969ceb2c
commit
1ef3522f86
|
@ -36,173 +36,9 @@ NEUTRON_SINK_FILE = DESIGNATE_DIR + '/conf.d/neutron_sink.cfg'
|
|||
RC_FILE = '/root/novarc'
|
||||
|
||||
|
||||
def install():
|
||||
"""Use the singleton from the DesignateCharm to install the packages on the
|
||||
unit
|
||||
|
||||
@returns: None
|
||||
"""
|
||||
DesignateCharm.singleton.install()
|
||||
|
||||
|
||||
def db_sync_done():
|
||||
"""Use the singleton from the DesignateCharm to check if db migration has
|
||||
been run
|
||||
|
||||
@returns: str or None. Str if sync has been done otherwise None
|
||||
"""
|
||||
return DesignateCharm.singleton.db_sync_done()
|
||||
|
||||
|
||||
def db_sync():
|
||||
"""Use the singleton from the DesignateCharm to run db migration
|
||||
|
||||
@returns: None
|
||||
"""
|
||||
DesignateCharm.singleton.db_sync()
|
||||
|
||||
|
||||
def render_base_config(interfaces_list):
|
||||
"""Use the singleton from the DesignateCharm to run render_base_config
|
||||
|
||||
@param interfaces_list: List of instances of interface classes.
|
||||
@returns: None
|
||||
"""
|
||||
DesignateCharm.singleton.render_base_config(interfaces_list)
|
||||
|
||||
|
||||
def create_initial_servers_and_domains():
|
||||
"""Use the singleton from the DesignateCharm to run create inital servers
|
||||
and domains in designate
|
||||
|
||||
@returns: None
|
||||
"""
|
||||
DesignateCharm.singleton.create_initial_servers_and_domains()
|
||||
|
||||
|
||||
def domain_init_done():
|
||||
"""Use the singleton from the DesignateCharm to check if inital servers
|
||||
and domains have been created
|
||||
|
||||
@returns: str or None. Str if init has been done otherwise None
|
||||
"""
|
||||
return DesignateCharm.singleton.domain_init_done()
|
||||
|
||||
|
||||
def render_full_config(interfaces_list):
|
||||
"""Use the singleton from the DesignateCharm to render all configs
|
||||
|
||||
@param interfaces_list: List of instances of interface classes.
|
||||
@returns: None
|
||||
"""
|
||||
DesignateCharm.singleton.render_full_config(interfaces_list)
|
||||
|
||||
|
||||
def render_sink_configs(interfaces_list):
|
||||
"""Use the singleton from the DesignateCharm to render sink configs
|
||||
|
||||
@param interfaces_list: List of instances of interface classes.
|
||||
@returns: None
|
||||
"""
|
||||
configs = [NOVA_SINK_FILE, NEUTRON_SINK_FILE, DESIGNATE_DEFAULT]
|
||||
DesignateCharm.singleton.render_with_interfaces(
|
||||
interfaces_list,
|
||||
configs=configs)
|
||||
|
||||
|
||||
def register_endpoints(keystone):
|
||||
"""When the keystone interface connects, register this unit in the keystone
|
||||
catalogue.
|
||||
|
||||
@param keystone: KeystoneRequires() interface class
|
||||
@returns: None
|
||||
"""
|
||||
charm = DesignateCharm.singleton
|
||||
keystone.register_endpoints(charm.service_type,
|
||||
charm.region,
|
||||
charm.public_url,
|
||||
charm.internal_url,
|
||||
charm.admin_url)
|
||||
|
||||
|
||||
def configure_ha_resources(hacluster):
|
||||
"""Use the singleton from the DesignateCharm to run configure ha resources
|
||||
|
||||
@param hacluster: OpenstackHAPeers() interface class
|
||||
@returns: None
|
||||
"""
|
||||
DesignateCharm.singleton.configure_ha_resources(hacluster)
|
||||
|
||||
|
||||
def restart_all():
|
||||
"""Use the singleton from the DesignateCharm to restart all registered
|
||||
services
|
||||
|
||||
@returns: None
|
||||
"""
|
||||
DesignateCharm.singleton.restart_all()
|
||||
|
||||
|
||||
def configure_ssl(keystone=None):
|
||||
"""Use the singleton from the DesignateCharm to configure ssl
|
||||
|
||||
@param keystone: KeystoneRequires() interface class
|
||||
@returns: None
|
||||
"""
|
||||
DesignateCharm.singleton.configure_ssl(keystone)
|
||||
|
||||
|
||||
def update_peers(hacluster):
|
||||
"""Use the singleton from the DesignateCharm to update peers with detials
|
||||
of this unit
|
||||
|
||||
@param hacluster: OpenstackHAPeers() interface class
|
||||
@returns: None
|
||||
"""
|
||||
DesignateCharm.singleton.update_peers(hacluster)
|
||||
|
||||
|
||||
def render_rndc_keys():
|
||||
"""Use the singleton from the DesignateCharm write out rndc key files
|
||||
|
||||
@returns: None
|
||||
"""
|
||||
DesignateCharm.singleton.render_rndc_keys()
|
||||
|
||||
|
||||
def assess_status():
|
||||
"""Just call the DesignateCharm.singleton.assess_status() command to update
|
||||
status on the unit.
|
||||
|
||||
@returns: None
|
||||
"""
|
||||
DesignateCharm.singleton.assess_status()
|
||||
|
||||
|
||||
def update_pools():
|
||||
"""Just call the DesignateCharm.singleton.update_pools() command to update
|
||||
pool info in the db
|
||||
|
||||
@returns: None
|
||||
"""
|
||||
DesignateCharm.singleton.update_pools()
|
||||
|
||||
|
||||
def upgrade_if_available(interfaces_list):
|
||||
"""Just call the DesignateCharm.singleton.upgrade_if_available() command to
|
||||
update OpenStack package if upgrade is available
|
||||
|
||||
@returns: None
|
||||
"""
|
||||
DesignateCharm.singleton.upgrade_if_available(interfaces_list)
|
||||
|
||||
|
||||
class DesignateDBAdapter(openstack_adapters.DatabaseRelationAdapter):
|
||||
"""Get database URIs for the two designate databases"""
|
||||
|
||||
def __init__(self, relation):
|
||||
super(DesignateDBAdapter, self).__init__(relation)
|
||||
|
||||
@property
|
||||
def designate_uri(self):
|
||||
"""URI for designate DB"""
|
||||
|
@ -218,9 +54,6 @@ class BindRNDCRelationAdapter(openstack_adapters.OpenStackRelationAdapter):
|
|||
|
||||
interface_type = "dns"
|
||||
|
||||
def __init__(self, relation):
|
||||
super(BindRNDCRelationAdapter, self).__init__(relation)
|
||||
|
||||
@property
|
||||
def slave_ips(self):
|
||||
"""List of DNS slave address infoprmation
|
||||
|
@ -283,10 +116,6 @@ class BindRNDCRelationAdapter(openstack_adapters.OpenStackRelationAdapter):
|
|||
class DesignateConfigurationAdapter(
|
||||
openstack_adapters.APIConfigurationAdapter):
|
||||
|
||||
def __init__(self, port_map=None, *args, **kwargs):
|
||||
super(DesignateConfigurationAdapter, self).__init__(
|
||||
port_map=port_map, service_name='designate', *args, **kwargs)
|
||||
|
||||
@property
|
||||
def pool_config(self):
|
||||
"""List of DNS slave information from user defined config
|
||||
|
@ -416,12 +245,6 @@ class DesignateAdapters(openstack_adapters.OpenStackAPIRelationAdapters):
|
|||
'dns_backend': BindRNDCRelationAdapter,
|
||||
}
|
||||
|
||||
def __init__(self, relations):
|
||||
super(DesignateAdapters, self).__init__(
|
||||
relations,
|
||||
options_instance=DesignateConfigurationAdapter(
|
||||
port_map=DesignateCharm.api_ports))
|
||||
|
||||
|
||||
class DesignateCharm(openstack_charm.HAOpenStackCharm):
|
||||
"""Designate charm"""
|
||||
|
@ -631,10 +454,14 @@ class DesignateCharm(openstack_charm.HAOpenStackCharm):
|
|||
"""Create the nameserver entry and domains based on the charm user
|
||||
supplied config
|
||||
|
||||
NOTE(AJK): This only wants to be done ONCE and by the leader, so we use
|
||||
leader settings to store that we've done it, after it's successfully
|
||||
completed.
|
||||
|
||||
@returns None
|
||||
"""
|
||||
if hookenv.is_leader():
|
||||
cls.ensure_api_responding()
|
||||
KEY = 'create_initial_servers_and_domains'
|
||||
if hookenv.is_leader() and not hookenv.leader_get(KEY):
|
||||
nova_domain_name = hookenv.config('nova-domain')
|
||||
neutron_domain_name = hookenv.config('neutron-domain')
|
||||
with cls.check_zone_ids(nova_domain_name, neutron_domain_name):
|
||||
|
@ -654,13 +481,32 @@ class DesignateCharm(openstack_charm.HAOpenStackCharm):
|
|||
cls.create_domain(
|
||||
neutron_domain_name,
|
||||
hookenv.config('neutron-domain-email'))
|
||||
# if this fails, we weren't the leader any more; another unit may
|
||||
# attempt to do this too.
|
||||
hookenv.leader_set(KEY, 'done')
|
||||
|
||||
def update_pools(self):
|
||||
# designate-manage communicates with designate via message bus so no
|
||||
# need to set OS_ vars
|
||||
# NOTE(AJK) this runs with every hook (once most relations are up) and
|
||||
# so if it fails it will be picked up by the next relation change or
|
||||
# update-status. i.e. it will heal eventually.
|
||||
if hookenv.is_leader():
|
||||
cmd = ['designate-manage', 'pool', 'update']
|
||||
subprocess.check_call(cmd)
|
||||
try:
|
||||
cmd = "designate-manage pool update"
|
||||
# Note(tinwood) that this command may fail if the pools.yaml
|
||||
# doesn't actually contain any pools. This happens when the
|
||||
# relation is broken, which errors out the charm. This stops
|
||||
# this happening and logs the error.
|
||||
subprocess.check_call(cmd.split(), timeout=60)
|
||||
except subprocess.CalledProcessError as e:
|
||||
hookenv.log("designate-manage pool update failed: {}"
|
||||
.format(str(e)))
|
||||
except subprocess.TimeoutExpired as e:
|
||||
# the timeout is if the rabbitmq server has gone away; it just
|
||||
# retries continuously; this lets the hook complete.
|
||||
hookenv.log("designate-manage pool command timed out: {}".
|
||||
format(str(e)))
|
||||
|
||||
def custom_assess_status_check(self):
|
||||
if (not hookenv.config('nameservers') and
|
||||
|
|
|
@ -12,11 +12,15 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import subprocess
|
||||
|
||||
import charm.openstack.designate as designate
|
||||
import charms.reactive as reactive
|
||||
import charmhelpers.core.hookenv as hookenv
|
||||
|
||||
from charms_openstack.charm import provide_charm_instance
|
||||
from charms_openstack.charm.utils import is_data_changed
|
||||
|
||||
|
||||
# If either dns-backend.available is set OR config('dns-slaves') is valid, then
|
||||
# the following state will be set.
|
||||
|
@ -59,33 +63,47 @@ def clear_dns_config_available():
|
|||
@reactive.when_not('installed')
|
||||
def install_packages():
|
||||
"""Install charms packages"""
|
||||
designate.install()
|
||||
with provide_charm_instance() as instance:
|
||||
instance.install()
|
||||
reactive.set_state('installed')
|
||||
reactive.remove_state('amqp.requested-access')
|
||||
reactive.remove_state('shared-db.setup')
|
||||
reactive.remove_state('base-config.rendered')
|
||||
reactive.remove_state('db.synched')
|
||||
|
||||
|
||||
@reactive.when('amqp.connected')
|
||||
@reactive.when_not('amqp.requested-access')
|
||||
def setup_amqp_req(amqp):
|
||||
"""Send request fir rabbit access and vhost"""
|
||||
"""Send request for rabbit access and vhost"""
|
||||
amqp.request_access(username='designate',
|
||||
vhost='openstack')
|
||||
designate.assess_status()
|
||||
reactive.set_state('amqp.requested-access')
|
||||
|
||||
|
||||
@reactive.when('shared-db.connected')
|
||||
@reactive.when_not('shared-db.setup')
|
||||
def setup_database(database):
|
||||
"""Send request designate accounts and dbs"""
|
||||
database.configure('designate', 'designate',
|
||||
prefix='designate')
|
||||
database.configure('dpm', 'dpm',
|
||||
prefix='dpm')
|
||||
designate.assess_status()
|
||||
reactive.set_state('shared-db.setup')
|
||||
|
||||
|
||||
@reactive.when('identity-service.connected')
|
||||
def setup_endpoint(keystone):
|
||||
"""Register endpoints with keystone"""
|
||||
designate.register_endpoints(keystone)
|
||||
designate.assess_status()
|
||||
def maybe_setup_endpoint(keystone):
|
||||
"""When the keystone interface connects, register this unit in the keystone
|
||||
catalogue.
|
||||
"""
|
||||
with provide_charm_instance() as instance:
|
||||
args = [instance.service_type, instance.region, instance.public_url,
|
||||
instance.internal_url, instance.admin_url]
|
||||
# This function checkes that the data has changed before sending it
|
||||
with is_data_changed('charms.openstack.register-endpoints', args) as c:
|
||||
if c:
|
||||
keystone.register_endpoints(*args)
|
||||
|
||||
|
||||
@reactive.when_not('base-config.rendered')
|
||||
|
@ -99,7 +117,8 @@ def configure_designate_basic(*args):
|
|||
dns_backend = reactive.RelationBase.from_state('dns-backend.available')
|
||||
if dns_backend is not None:
|
||||
args = args + (dns_backend, )
|
||||
designate.render_base_config(args)
|
||||
with provide_charm_instance() as instance:
|
||||
instance.render_base_config(args)
|
||||
reactive.set_state('base-config.rendered')
|
||||
|
||||
|
||||
|
@ -108,15 +127,19 @@ def configure_designate_basic(*args):
|
|||
@reactive.when(*COMPLETE_INTERFACE_STATES)
|
||||
def run_db_migration(*args):
|
||||
"""Run database migrations"""
|
||||
designate.db_sync()
|
||||
if designate.db_sync_done():
|
||||
reactive.set_state('db.synched')
|
||||
with provide_charm_instance() as instance:
|
||||
instance.db_sync()
|
||||
if instance.db_sync_done():
|
||||
reactive.set_state('db.synched')
|
||||
|
||||
|
||||
@reactive.when('cluster.available')
|
||||
def update_peers(cluster):
|
||||
"""Inform designate peers about this unit"""
|
||||
designate.update_peers(cluster)
|
||||
with provide_charm_instance() as instance:
|
||||
# This function ONLY updates the peers if the data has changed. Thus
|
||||
# it's okay to call it on every hook invocation.
|
||||
instance.update_peers(cluster)
|
||||
|
||||
|
||||
@reactive.when('db.synched')
|
||||
|
@ -130,25 +153,48 @@ def configure_designate_full(*args):
|
|||
dns_backend = reactive.RelationBase.from_state('dns-backend.available')
|
||||
if dns_backend is not None:
|
||||
args = args + (dns_backend, )
|
||||
designate.upgrade_if_available(args)
|
||||
designate.configure_ssl()
|
||||
designate.render_full_config(args)
|
||||
designate.create_initial_servers_and_domains()
|
||||
designate.render_sink_configs(args)
|
||||
designate.render_rndc_keys()
|
||||
designate.update_pools()
|
||||
designate.assess_status()
|
||||
with provide_charm_instance() as instance:
|
||||
instance.upgrade_if_available(args)
|
||||
instance.configure_ssl()
|
||||
instance.render_full_config(args)
|
||||
try:
|
||||
# the following function should only run once for the leader.
|
||||
instance.create_initial_servers_and_domains()
|
||||
_render_sink_configs(instance, args)
|
||||
instance.render_rndc_keys()
|
||||
instance.update_pools()
|
||||
except subprocess.CalledProcessError as e:
|
||||
hookenv.log("ensure_api_responding() errored out: {}"
|
||||
.format(str(e)),
|
||||
level=hookenv.ERROR)
|
||||
|
||||
|
||||
def _render_sink_configs(instance, interfaces_list):
|
||||
"""Helper: use the singleton from the DesignateCharm to render sink configs
|
||||
|
||||
@param instance: an instance that has the render_with_intefaces() method
|
||||
@param interfaces_list: List of instances of interface classes.
|
||||
@returns: None
|
||||
"""
|
||||
configs = [designate.NOVA_SINK_FILE,
|
||||
designate.NEUTRON_SINK_FILE,
|
||||
designate.DESIGNATE_DEFAULT]
|
||||
instance.render_with_interfaces(interfaces_list, configs=configs)
|
||||
|
||||
|
||||
@reactive.when('ha.connected')
|
||||
def cluster_connected(hacluster):
|
||||
"""Configure HA resources in corosync"""
|
||||
designate.configure_ha_resources(hacluster)
|
||||
designate.assess_status()
|
||||
with provide_charm_instance() as instance:
|
||||
instance.configure_ha_resources(hacluster)
|
||||
|
||||
|
||||
@reactive.when('config.changed')
|
||||
def config_changed():
|
||||
"""When the configuration changes, assess the unit's status to update any
|
||||
juju state required"""
|
||||
designate.assess_status()
|
||||
@reactive.when_not('dont-set-assess-status')
|
||||
def run_assess_status_on_every_hook():
|
||||
"""The call to charm instance.assess_status() sets up the assess status
|
||||
functionality to be called atexit() of the charm. i.e. as the last thing
|
||||
it does. Thus, this handle gets called for EVERY hook invocation, which
|
||||
means that no other handlers need to call the assess_status function.
|
||||
"""
|
||||
with provide_charm_instance() as instance:
|
||||
instance.assess_status()
|
||||
|
|
|
@ -20,7 +20,7 @@ class TestRegisteredHooks(test_utils.TestRegisteredHooks):
|
|||
'when': {
|
||||
'setup_amqp_req': ('amqp.connected', ),
|
||||
'setup_database': ('shared-db.connected', ),
|
||||
'setup_endpoint': ('identity-service.connected', ),
|
||||
'maybe_setup_endpoint': ('identity-service.connected', ),
|
||||
'configure_ssl': ('identity-service.available', ),
|
||||
'update_peers': ('cluster.available', ),
|
||||
'config_changed': ('config.changed', ),
|
||||
|
@ -34,10 +34,14 @@ class TestRegisteredHooks(test_utils.TestRegisteredHooks):
|
|||
'configure_designate_basic': all_interfaces,
|
||||
},
|
||||
'when_not': {
|
||||
'setup_amqp_req': ('amqp.requested-access', ),
|
||||
'setup_database': ('shared-db.setup', ),
|
||||
'install_packages': ('installed', ),
|
||||
'run_db_migration': ('db.synched', ),
|
||||
'configure_designate_basic': ('base-config.rendered', ),
|
||||
'create_servers_and_domains': ('domains.created', ),
|
||||
'run_assess_status_on_every_hook': (
|
||||
'dont-set-assess-status', ),
|
||||
},
|
||||
'when_any': {
|
||||
'set_dns_config_available': (
|
||||
|
@ -58,23 +62,36 @@ class TestRegisteredHooks(test_utils.TestRegisteredHooks):
|
|||
|
||||
class TestHandlers(test_utils.PatchHelper):
|
||||
|
||||
def _patch_provide_charm_instance(self):
|
||||
the_charm = mock.MagicMock()
|
||||
self.patch_object(handlers, 'provide_charm_instance',
|
||||
name='provide_charm_instance',
|
||||
new=mock.MagicMock())
|
||||
self.provide_charm_instance().__enter__.return_value = the_charm
|
||||
self.provide_charm_instance().__exit__.return_value = None
|
||||
return the_charm
|
||||
|
||||
def test_install_packages(self):
|
||||
self.patch_object(handlers.designate, 'install')
|
||||
the_charm = self._patch_provide_charm_instance()
|
||||
self.patch_object(handlers.reactive, 'set_state')
|
||||
self.patch_object(handlers.reactive, 'remove_state')
|
||||
handlers.install_packages()
|
||||
self.install.assert_called_once_with()
|
||||
self.set_state.assert_called_once_with('installed')
|
||||
the_charm.install.assert_called_once_with()
|
||||
calls = [mock.call('amqp.requested-access'),
|
||||
mock.call('shared-db.setup'),
|
||||
mock.call('base-config.rendered'),
|
||||
mock.call('db.synched')]
|
||||
self.remove_state.assert_has_calls(calls)
|
||||
|
||||
def test_setup_amqp_req(self):
|
||||
self.patch_object(handlers.designate, 'assess_status')
|
||||
self.patch_object(handlers.reactive, 'set_state')
|
||||
amqp = mock.MagicMock()
|
||||
handlers.setup_amqp_req(amqp)
|
||||
amqp.request_access.assert_called_once_with(
|
||||
username='designate', vhost='openstack')
|
||||
self.assess_status.assert_called_once_with()
|
||||
self.set_state.assert_called_once_with('amqp.requested-access')
|
||||
|
||||
def test_database(self):
|
||||
self.patch_object(handlers.designate, 'assess_status')
|
||||
database = mock.MagicMock()
|
||||
handlers.setup_database(database)
|
||||
calls = [
|
||||
|
@ -88,74 +105,72 @@ class TestHandlers(test_utils.PatchHelper):
|
|||
prefix='dpm'),
|
||||
]
|
||||
database.configure.has_calls(calls)
|
||||
self.assess_status.assert_called_once_with()
|
||||
|
||||
def test_setup_endpoint(self):
|
||||
self.patch_object(handlers.designate, 'assess_status')
|
||||
self.patch_object(handlers.designate, 'register_endpoints')
|
||||
handlers.setup_endpoint('endpoint_object')
|
||||
self.register_endpoints.assert_called_once_with('endpoint_object')
|
||||
self.assess_status.assert_called_once_with()
|
||||
the_charm = self._patch_provide_charm_instance()
|
||||
the_charm.service_type = 's1'
|
||||
the_charm.region = 'r1'
|
||||
the_charm.public_url = 'p1'
|
||||
the_charm.internal_url = 'i1'
|
||||
the_charm.admin_url = 'a1'
|
||||
args = ['s1', 'r1', 'p1', 'i1', 'a1']
|
||||
self.patch_object(handlers, 'is_data_changed',
|
||||
name='is_data_changed',
|
||||
new=mock.MagicMock())
|
||||
self.is_data_changed().__enter__.return_value = True
|
||||
self.is_data_changed().__exit__.return_value = None
|
||||
keystone = mock.MagicMock()
|
||||
handlers.maybe_setup_endpoint(keystone)
|
||||
self.is_data_changed.called_once_with(mock.ANY, args)
|
||||
keystone.register_endpoints.assert_called_once_with(*args)
|
||||
|
||||
def test_configure_designate_basic(self):
|
||||
the_charm = self._patch_provide_charm_instance()
|
||||
self.patch_object(handlers.reactive, 'set_state')
|
||||
self.patch_object(handlers.designate, 'render_base_config')
|
||||
self.patch_object(handlers.reactive.RelationBase, 'from_state',
|
||||
return_value=None)
|
||||
handlers.configure_designate_basic('arg1', 'arg2')
|
||||
self.render_base_config.assert_called_once_with(('arg1', 'arg2', ))
|
||||
the_charm.render_base_config.assert_called_once_with(
|
||||
('arg1', 'arg2', ))
|
||||
self.set_state.assert_called_once_with('base-config.rendered')
|
||||
|
||||
def test_run_db_migration(self):
|
||||
the_charm = self._patch_provide_charm_instance()
|
||||
self.patch_object(handlers.reactive, 'set_state')
|
||||
self.patch_object(handlers.designate, 'db_sync')
|
||||
self.patch_object(handlers.designate, 'db_sync_done')
|
||||
self.db_sync_done.return_value = False
|
||||
the_charm.db_sync_done.return_value = False
|
||||
handlers.run_db_migration('arg1', 'arg2')
|
||||
self.db_sync.assert_called_once_with()
|
||||
the_charm.db_sync.assert_called_once_with()
|
||||
self.assertFalse(self.set_state.called)
|
||||
self.db_sync.reset_mock()
|
||||
self.db_sync_done.return_value = True
|
||||
the_charm.db_sync.reset_mock()
|
||||
the_charm.db_sync_done.return_value = True
|
||||
handlers.run_db_migration('arg1', 'arg2')
|
||||
self.db_sync.assert_called_once_with()
|
||||
the_charm.db_sync.assert_called_once_with()
|
||||
self.set_state.assert_called_once_with('db.synched')
|
||||
|
||||
def test_update_peers(self):
|
||||
cluster = mock.MagicMock()
|
||||
self.patch_object(handlers.designate, 'update_peers')
|
||||
handlers.update_peers(cluster)
|
||||
self.update_peers.assert_called_once_with(cluster)
|
||||
the_charm = self._patch_provide_charm_instance()
|
||||
handlers.update_peers('cluster')
|
||||
the_charm.update_peers.assert_called_once_with('cluster')
|
||||
|
||||
def test_configure_designate_full(self):
|
||||
the_charm = self._patch_provide_charm_instance()
|
||||
self.patch_object(handlers.reactive.RelationBase,
|
||||
'from_state',
|
||||
return_value=None)
|
||||
self.patch_object(handlers.designate, 'upgrade_if_available')
|
||||
self.patch_object(handlers.designate, 'configure_ssl')
|
||||
self.patch_object(handlers.designate, 'render_full_config')
|
||||
self.patch_object(handlers.designate,
|
||||
'create_initial_servers_and_domains')
|
||||
self.patch_object(handlers.designate, 'render_sink_configs')
|
||||
self.patch_object(handlers.designate, 'render_rndc_keys')
|
||||
self.patch_object(handlers.designate, 'update_pools')
|
||||
handlers.configure_designate_full('arg1', 'arg2')
|
||||
self.configure_ssl.assert_called_once_with()
|
||||
self.render_full_config.assert_called_once_with(('arg1', 'arg2', ))
|
||||
self.create_initial_servers_and_domains.assert_called_once_with()
|
||||
self.render_sink_configs.assert_called_once_with(('arg1', 'arg2', ))
|
||||
self.render_rndc_keys.assert_called_once_with()
|
||||
self.update_pools.assert_called_once_with()
|
||||
self.upgrade_if_available.assert_called_once_with(('arg1', 'arg2', ))
|
||||
the_charm.configure_ssl.assert_called_once_with()
|
||||
the_charm.render_full_config.assert_called_once_with(
|
||||
('arg1', 'arg2', ))
|
||||
the_charm.create_initial_servers_and_domains.assert_called_once_with()
|
||||
the_charm.render_with_interfaces.assert_called_once_with(
|
||||
('arg1', 'arg2'), configs=mock.ANY)
|
||||
the_charm.render_rndc_keys.assert_called_once_with()
|
||||
the_charm.update_pools.assert_called_once_with()
|
||||
the_charm.upgrade_if_available.assert_called_once_with(
|
||||
('arg1', 'arg2', ))
|
||||
|
||||
def test_cluster_connected(self):
|
||||
the_charm = self._patch_provide_charm_instance()
|
||||
hacluster = mock.MagicMock()
|
||||
self.patch_object(handlers.designate, 'configure_ha_resources')
|
||||
self.patch_object(handlers.designate, 'assess_status')
|
||||
handlers.cluster_connected(hacluster)
|
||||
self.configure_ha_resources.assert_called_once_with(hacluster)
|
||||
self.assess_status.assert_called_once_with()
|
||||
|
||||
def test_config_changed(self):
|
||||
self.patch_object(handlers.designate, 'assess_status')
|
||||
handlers.config_changed()
|
||||
self.assess_status.assert_called_once_with()
|
||||
the_charm.configure_ha_resources.assert_called_once_with(hacluster)
|
||||
|
|
|
@ -71,90 +71,6 @@ class Helper(unittest.TestCase):
|
|||
setattr(self, name, started)
|
||||
|
||||
|
||||
class TestOpenStackDesignate(Helper):
|
||||
|
||||
def test_install(self):
|
||||
self.patch(designate.DesignateCharm.singleton, 'install')
|
||||
designate.install()
|
||||
self.install.assert_called_once_with()
|
||||
|
||||
def test_db_sync_done(self):
|
||||
self.patch(designate.DesignateCharm.singleton, 'db_sync_done')
|
||||
designate.db_sync_done()
|
||||
self.db_sync_done.assert_called_once_with()
|
||||
|
||||
def test_db_sync(self):
|
||||
self.patch(designate.DesignateCharm.singleton, 'db_sync')
|
||||
designate.db_sync()
|
||||
self.db_sync.assert_called_once_with()
|
||||
|
||||
def test_render_base_config(self):
|
||||
self.patch(designate.DesignateCharm.singleton, 'render_base_config')
|
||||
designate.render_base_config('interfaces_list')
|
||||
self.render_base_config.assert_called_once_with('interfaces_list')
|
||||
|
||||
def test_domain_init_done(self):
|
||||
self.patch(designate.DesignateCharm.singleton, 'domain_init_done')
|
||||
designate.domain_init_done()
|
||||
self.domain_init_done.assert_called_once_with()
|
||||
|
||||
def test_render_full_config(self):
|
||||
self.patch(designate.DesignateCharm.singleton, 'render_full_config')
|
||||
designate.render_full_config('interfaces_list')
|
||||
self.render_full_config.assert_called_once_with('interfaces_list')
|
||||
|
||||
def test_register_endpoints(self):
|
||||
self.patch(designate.DesignateCharm, 'service_type',
|
||||
new_callable=mock.PropertyMock)
|
||||
self.patch(designate.DesignateCharm, 'region',
|
||||
new_callable=mock.PropertyMock)
|
||||
self.patch(designate.DesignateCharm, 'public_url',
|
||||
new_callable=mock.PropertyMock)
|
||||
self.patch(designate.DesignateCharm, 'internal_url',
|
||||
new_callable=mock.PropertyMock)
|
||||
self.patch(designate.DesignateCharm, 'admin_url',
|
||||
new_callable=mock.PropertyMock)
|
||||
self.service_type.return_value = 'type1'
|
||||
self.region.return_value = 'region1'
|
||||
self.public_url.return_value = 'public_url'
|
||||
self.internal_url.return_value = 'internal_url'
|
||||
self.admin_url.return_value = 'admin_url'
|
||||
keystone = mock.MagicMock()
|
||||
designate.register_endpoints(keystone)
|
||||
keystone.register_endpoints.assert_called_once_with(
|
||||
'type1', 'region1', 'public_url', 'internal_url', 'admin_url')
|
||||
|
||||
def test_configure_ha_resources(self):
|
||||
self.patch(designate.DesignateCharm.singleton, 'db_sync')
|
||||
designate.db_sync()
|
||||
self.db_sync.assert_called_once_with()
|
||||
|
||||
def test_restart_all(self):
|
||||
self.patch(designate.DesignateCharm.singleton, 'restart_all')
|
||||
designate.restart_all()
|
||||
self.restart_all.assert_called_once_with()
|
||||
|
||||
def test_configure_ssl(self):
|
||||
self.patch(designate.DesignateCharm.singleton, 'configure_ssl')
|
||||
designate.configure_ssl()
|
||||
self.configure_ssl.assert_called_once_with(None)
|
||||
|
||||
def test_update_peers(self):
|
||||
self.patch(designate.DesignateCharm.singleton, 'update_peers')
|
||||
designate.update_peers('cluster')
|
||||
self.update_peers.assert_called_once_with('cluster')
|
||||
|
||||
def test_render_rndc_keys(self):
|
||||
self.patch(designate.DesignateCharm.singleton, 'render_rndc_keys')
|
||||
designate.render_rndc_keys()
|
||||
self.render_rndc_keys.assert_called_once_with()
|
||||
|
||||
def test_assess_status(self):
|
||||
self.patch(designate.DesignateCharm.singleton, 'assess_status')
|
||||
designate.assess_status()
|
||||
self.assess_status.assert_called_once_with()
|
||||
|
||||
|
||||
class TestDesignateDBAdapter(Helper):
|
||||
|
||||
def fake_get_uri(self, prefix):
|
||||
|
@ -279,35 +195,6 @@ class TestDesignateConfigurationAdapter(Helper):
|
|||
self.assertEqual(a.rndc_master_ip, 'intip')
|
||||
|
||||
|
||||
class TestDesignateAdapters(Helper):
|
||||
|
||||
def test_designate_adapters(self):
|
||||
self.patch(
|
||||
designate.openstack_adapters.APIConfigurationAdapter,
|
||||
'get_network_addresses')
|
||||
cluster_relation = mock.MagicMock()
|
||||
cluster_relation.relation_name = 'cluster'
|
||||
amqp_relation = mock.MagicMock()
|
||||
amqp_relation.relation_name = 'amqp'
|
||||
shared_db_relation = mock.MagicMock()
|
||||
shared_db_relation.relation_name = 'shared_db'
|
||||
other_relation = mock.MagicMock()
|
||||
other_relation.relation_name = 'other'
|
||||
other_relation.thingy = 'help'
|
||||
# verify that the class is created with a DesignateConfigurationAdapter
|
||||
b = designate.DesignateAdapters([amqp_relation,
|
||||
cluster_relation,
|
||||
shared_db_relation,
|
||||
other_relation])
|
||||
# ensure that the relevant things got put on.
|
||||
self.assertTrue(
|
||||
isinstance(
|
||||
b.other,
|
||||
designate.openstack_adapters.OpenStackRelationAdapter))
|
||||
self.assertIsInstance(b.options,
|
||||
designate.DesignateConfigurationAdapter)
|
||||
|
||||
|
||||
class TestDesignateCharm(Helper):
|
||||
|
||||
def test_install(self):
|
||||
|
@ -420,6 +307,7 @@ class TestDesignateCharm(Helper):
|
|||
self.ensure_api_responding.return_value = True
|
||||
self.patch(designate.hookenv, 'is_leader', return_value=True)
|
||||
self.patch(designate.hookenv, 'leader_set')
|
||||
self.patch(designate.hookenv, 'leader_get', return_value=False)
|
||||
self.patch(designate.DesignateCharm, 'create_server')
|
||||
self.patch(designate.DesignateCharm, 'create_domain')
|
||||
|
||||
|
|
Loading…
Reference in New Issue