def test_ha_relation_changed_pacemaker_remote( self, config, get_corosync_conf, relation_ids, relation_set, get_cluster_nodes, trigger_corosync_update_from_leader, relation_type, remote_unit): """Test pacemaker-remote-relation-changed. Validates that ha_relation_changed() doesn't call trigger_corosync_update_from_leader() when called from the pacemaker-remote-relation-changed hook. See lp:1920124 """ cfg = {'cluster_count': 3} config.side_effect = lambda key: cfg.get(key) # 2 out of 3 so that the function under test finishes early: get_cluster_nodes.return_value = ['10.0.3.2', '10.0.3.3'] relation_ids.return_value = ['hanode:1'] get_corosync_conf.return_value = True relation_type.return_value = 'pacemaker-remote' remote_unit.return_value = 'pacemaker-remote/0' hooks.ha_relation_changed() relation_set.assert_any_call(relation_id='hanode:1', ready=True) trigger_corosync_update_from_leader.assert_not_called()
def test_ha_relation_changed_dns_ha_missing( self, parse_data, config, commit, get_corosync_conf, relation_ids, relation_set, get_cluster_nodes, related_units, configure_stonith, configure_monitor_host, configure_cluster_global, configure_corosync, oldest_peer, crm_opt_exists, peer_units, wait_for_pcmk, validate_dns_ha, setup_maas_api): validate_dns_ha.return_value = False crm_opt_exists.return_value = False oldest_peer.return_value = True related_units.return_value = ['ha/0', 'ha/1', 'ha/2'] get_cluster_nodes.return_value = ['10.0.3.2', '10.0.3.3', '10.0.3.4'] relation_ids.return_value = ['ha:1'] get_corosync_conf.return_value = True cfg = { 'debug': False, 'prefer-ipv6': False, 'corosync_transport': 'udpu', 'corosync_mcastaddr': 'corosync_mcastaddr', 'cluster_count': 3, 'maas_url': 'http://maas/MAAAS/', 'maas_credentials': None } config.side_effect = lambda key: cfg.get(key) rel_get_data = { 'locations': { 'loc_foo': 'bar rule inf: meh eq 1' }, 'clones': { 'cl_foo': 'res_foo meta interleave=true' }, 'groups': { 'grp_foo': 'res_foo' }, 'colocations': { 'co_foo': 'inf: grp_foo cl_foo' }, 'resources': { 'res_foo_hostname': 'ocf:maas:dns' }, 'resource_params': { 'res_foo_hostname': 'params bar' }, 'ms': { 'ms_foo': 'res_foo meta notify=true' }, 'orders': { 'foo_after': 'inf: res_foo ms_foo' } } def fake_parse_data(relid, unit, key): return rel_get_data.get(key, {}) parse_data.side_effect = fake_parse_data with self.assertRaises(ValueError): hooks.ha_relation_changed()
def test_ha_relation_changed(self, parse_data, config, commit, get_corosync_conf, relation_ids, relation_set, get_cluster_nodes, related_units, configure_stonith, configure_monitor_host, configure_cluster_global, configure_corosync, oldest_peer, crm_opt_exists, peer_units, wait_for_pcmk, write_maas_dns_address): crm_opt_exists.return_value = False oldest_peer.return_value = True related_units.return_value = ['ha/0', 'ha/1', 'ha/2'] get_cluster_nodes.return_value = ['10.0.3.2', '10.0.3.3', '10.0.3.4'] relation_ids.return_value = ['hanode:1'] get_corosync_conf.return_value = True cfg = {'debug': False, 'prefer-ipv6': False, 'corosync_transport': 'udpu', 'corosync_mcastaddr': 'corosync_mcastaddr', 'cluster_count': 3} config.side_effect = lambda key: cfg.get(key) rel_get_data = {'locations': {'loc_foo': 'bar rule inf: meh eq 1'}, 'clones': {'cl_foo': 'res_foo meta interleave=true'}, 'groups': {'grp_foo': 'res_foo'}, 'colocations': {'co_foo': 'inf: grp_foo cl_foo'}, 'resources': {'res_foo': 'ocf:heartbeat:IPaddr2', 'res_bar': 'ocf:heartbear:IPv6addr'}, 'resource_params': {'res_foo': 'params bar'}, 'ms': {'ms_foo': 'res_foo meta notify=true'}, 'orders': {'foo_after': 'inf: res_foo ms_foo'}} def fake_parse_data(relid, unit, key): return rel_get_data.get(key, {}) parse_data.side_effect = fake_parse_data hooks.ha_relation_changed() relation_set.assert_any_call(relation_id='hanode:1', ready=True) configure_stonith.assert_called_with() configure_monitor_host.assert_called_with() configure_cluster_global.assert_called_with() configure_corosync.assert_called_with() write_maas_dns_address.assert_not_called() for kw, key in [('location', 'locations'), ('clone', 'clones'), ('group', 'groups'), ('colocation', 'colocations'), ('primitive', 'resources'), ('ms', 'ms'), ('order', 'orders')]: for name, params in rel_get_data[key].items(): if name in rel_get_data['resource_params']: res_params = rel_get_data['resource_params'][name] commit.assert_any_call( 'crm -w -F configure %s %s %s %s' % (kw, name, params, res_params)) else: commit.assert_any_call( 'crm -w -F configure %s %s %s' % (kw, name, params))
def test_ha_relation_changed_dns_ha( self, parse_data, config, commit, get_corosync_conf, relation_ids, relation_set, get_cluster_nodes, related_units, configure_stonith, configure_monitor_host, configure_cluster_global, configure_corosync, is_leader, crm_opt_exists, wait_for_pcmk, validate_dns_ha, setup_maas_api, write_maas_dns_addr, set_cluster_symmetry, configure_pacemaker_remote_resources, configure_pacemaker_remote_stonith_resource, configure_resources_on_remotes, get_member_ready_nodes): validate_dns_ha.return_value = True crm_opt_exists.return_value = False is_leader.return_value = True related_units.return_value = ['ha/0', 'ha/1', 'ha/2'] get_cluster_nodes.return_value = ['10.0.3.2', '10.0.3.3', '10.0.3.4'] get_member_ready_nodes.return_value = ['10.0.3.2', '10.0.3.3', '10.0.3.4'] relation_ids.return_value = ['ha:1'] get_corosync_conf.return_value = True cfg = {'debug': False, 'prefer-ipv6': False, 'corosync_transport': 'udpu', 'corosync_mcastaddr': 'corosync_mcastaddr', 'cluster_count': 3, 'maas_url': 'http://maas/MAAAS/', 'maas_credentials': 'secret'} config.side_effect = lambda key: cfg.get(key) rel_get_data = {'locations': {'loc_foo': 'bar rule inf: meh eq 1'}, 'clones': {'cl_foo': 'res_foo meta interleave=true'}, 'groups': {'grp_foo': 'res_foo'}, 'colocations': {'co_foo': 'inf: grp_foo cl_foo'}, 'resources': {'res_foo_hostname': 'ocf:maas:dns'}, 'resource_params': { 'res_foo_hostname': 'params bar ' 'ip_address="172.16.0.1"'}, 'ms': {'ms_foo': 'res_foo meta notify=true'}, 'orders': {'foo_after': 'inf: res_foo ms_foo'}} def fake_parse_data(relid, unit, key): return rel_get_data.get(key, {}) parse_data.side_effect = fake_parse_data hooks.ha_relation_changed() self.assertTrue(validate_dns_ha.called) self.assertTrue(setup_maas_api.called) write_maas_dns_addr.assert_called_with('res_foo_hostname', '172.16.0.1') # Validate maas_credentials and maas_url are added to params commit.assert_any_call( 'crm -w -F configure primitive res_foo_hostname ocf:maas:dns ' 'params bar ip_address="172.16.0.1" maas_url="http://maas/MAAAS/" ' 'maas_credentials="secret"')
def test_ha_relation_changed_dns_ha_missing( self, parse_data, config, commit, get_corosync_conf, relation_ids, relation_set, get_cluster_nodes, related_units, configure_stonith, configure_monitor_host, configure_cluster_global, configure_corosync, is_leader, crm_opt_exists, wait_for_pcmk, validate_dns_ha, setup_maas_api): def fake_validate(): raise utils.MAASConfigIncomplete('DNS HA invalid config') validate_dns_ha.side_effect = fake_validate crm_opt_exists.return_value = False is_leader.return_value = True related_units.return_value = ['ha/0', 'ha/1', 'ha/2'] get_cluster_nodes.return_value = ['10.0.3.2', '10.0.3.3', '10.0.3.4'] relation_ids.return_value = ['ha:1'] get_corosync_conf.return_value = True cfg = {'debug': False, 'prefer-ipv6': False, 'corosync_transport': 'udpu', 'corosync_mcastaddr': 'corosync_mcastaddr', 'cluster_count': 3, 'maas_url': 'http://maas/MAAAS/', 'maas_credentials': None} config.side_effect = lambda key: cfg.get(key) rel_get_data = {'locations': {'loc_foo': 'bar rule inf: meh eq 1'}, 'clones': {'cl_foo': 'res_foo meta interleave=true'}, 'groups': {'grp_foo': 'res_foo'}, 'colocations': {'co_foo': 'inf: grp_foo cl_foo'}, 'resources': {'res_foo_hostname': 'ocf:maas:dns'}, 'resource_params': {'res_foo_hostname': 'params bar'}, 'ms': {'ms_foo': 'res_foo meta notify=true'}, 'orders': {'foo_after': 'inf: res_foo ms_foo'}} def fake_parse_data(relid, unit, key): return rel_get_data.get(key, {}) parse_data.side_effect = fake_parse_data with mock.patch.object(hooks, 'status_set') as mock_status_set: hooks.ha_relation_changed() mock_status_set.assert_called_with('blocked', 'DNS HA invalid config')
def test_ha_relation_changed( self, parse_data, config, commit, get_corosync_conf, relation_ids, relation_set, get_cluster_nodes, related_units, configure_stonith, configure_monitor_host, configure_cluster_global, configure_corosync, is_leader, crm_opt_exists, wait_for_pcmk, write_maas_dns_address, set_cluster_symmetry, configure_pacemaker_remote_resources, configure_pacemaker_remote_stonith_resource, configure_resources_on_remotes, get_member_ready_nodes, configure_peer_stonith_resource, is_stonith_configured, trigger_corosync_update_from_leader, relation_type, remote_unit, mock_kv): def fake_crm_opt_exists(res_name): # res_ubuntu will take the "update resource" route # res_nova_eth0_vip will take the delete resource route return res_name in ["res_ubuntu", "res_nova_eth0_vip"] db = test_utils.FakeKvStore() mock_kv.return_value = db crm_opt_exists.side_effect = fake_crm_opt_exists commit.return_value = 0 is_stonith_configured.return_value = False is_leader.return_value = True related_units.return_value = ['ha/0', 'ha/1', 'ha/2'] get_cluster_nodes.return_value = ['10.0.3.2', '10.0.3.3', '10.0.3.4'] get_member_ready_nodes.return_value = [ '10.0.3.2', '10.0.3.3', '10.0.3.4' ] relation_ids.return_value = ['hanode:1'] get_corosync_conf.return_value = True cfg = { 'debug': False, 'prefer-ipv6': False, 'corosync_transport': 'udpu', 'corosync_mcastaddr': 'corosync_mcastaddr', 'cluster_count': 3, 'failure_timeout': 180, 'cluster_recheck_interval': 60 } trigger_corosync_update_from_leader.return_value = False relation_type.return_value = "hanode" remote_unit.return_value = "hacluster/0" config.side_effect = lambda key: cfg.get(key) rel_get_data = { 'locations': { 'loc_foo': 'bar rule inf: meh eq 1' }, 'clones': { 'cl_foo': 'res_foo meta interleave=true' }, 'groups': { 'grp_foo': 'res_foo' }, 'colocations': { 'co_foo': 'inf: grp_foo cl_foo' }, 'resources': { 'res_foo': 'ocf:heartbeat:IPaddr2', 'res_bar': 'ocf:heartbear:IPv6addr', 'res_ubuntu': 'IPaddr2' }, 'resource_params': { 'res_foo': 'params bar', 'res_ubuntu': 'params ubuntu=42' }, 'ms': { 'ms_foo': 'res_foo meta notify=true' }, 'orders': { 'foo_after': 'inf: res_foo ms_foo' }, 'delete_resources': ['res_nova_eth0_vip'] } def fake_parse_data(relid, unit, key): return rel_get_data.get(key, {}) parse_data.side_effect = fake_parse_data with mock.patch.object(tempfile, "NamedTemporaryFile", side_effect=lambda: self.tmpfile): hooks.ha_relation_changed() relation_set.assert_any_call(relation_id='hanode:1', ready=True) configure_stonith.assert_called_with() configure_monitor_host.assert_called_with() configure_cluster_global.assert_called_with(180, 60) configure_corosync.assert_called_with() set_cluster_symmetry.assert_called_with() configure_pacemaker_remote_resources.assert_called_with() write_maas_dns_address.assert_not_called() # verify deletion of resources. crm_opt_exists.assert_any_call('res_nova_eth0_vip') commit.assert_any_call('crm resource cleanup res_nova_eth0_vip') commit.assert_any_call('crm -w -F resource stop res_nova_eth0_vip') commit.assert_any_call('crm -w -F configure delete res_nova_eth0_vip') for kw, key in [('location', 'locations'), ('clone', 'clones'), ('group', 'groups'), ('colocation', 'colocations'), ('primitive', 'resources'), ('ms', 'ms'), ('order', 'orders')]: for name, params in rel_get_data[key].items(): if name == "res_ubuntu": commit.assert_any_call('crm configure load update %s' % self.tmpfile.name) elif name in rel_get_data['resource_params']: res_params = rel_get_data['resource_params'][name] commit.assert_any_call('crm -w -F configure %s %s %s %s' % (kw, name, params, res_params)) else: commit.assert_any_call('crm -w -F configure %s %s %s' % (kw, name, params))
def test_ha_relation_changed_dns_ha_missing( self, parse_data, config, commit, get_corosync_conf, relation_ids, relation_set, get_cluster_nodes, related_units, configure_stonith, configure_monitor_host, configure_cluster_global, configure_corosync, is_leader, crm_opt_exists, wait_for_pcmk, validate_dns_ha, setup_maas_api, trigger_corosync_update_from_leader, relation_type, remote_unit): def fake_validate(): raise utils.MAASConfigIncomplete('DNS HA invalid config') validate_dns_ha.side_effect = fake_validate crm_opt_exists.return_value = False is_leader.return_value = True related_units.return_value = ['ha/0', 'ha/1', 'ha/2'] get_cluster_nodes.return_value = ['10.0.3.2', '10.0.3.3', '10.0.3.4'] relation_ids.return_value = ['ha:1'] get_corosync_conf.return_value = True cfg = { 'debug': False, 'prefer-ipv6': False, 'corosync_transport': 'udpu', 'corosync_mcastaddr': 'corosync_mcastaddr', 'cluster_count': 3, 'maas_url': 'http://maas/MAAAS/', 'maas_credentials': None } trigger_corosync_update_from_leader.return_value = False relation_type.return_value = "hanode" remote_unit.return_value = "hacluster/0" config.side_effect = lambda key: cfg.get(key) rel_get_data = { 'locations': { 'loc_foo': 'bar rule inf: meh eq 1' }, 'clones': { 'cl_foo': 'res_foo meta interleave=true' }, 'groups': { 'grp_foo': 'res_foo' }, 'colocations': { 'co_foo': 'inf: grp_foo cl_foo' }, 'resources': { 'res_foo_hostname': 'ocf:maas:dns' }, 'resource_params': { 'res_foo_hostname': 'params bar' }, 'ms': { 'ms_foo': 'res_foo meta notify=true' }, 'orders': { 'foo_after': 'inf: res_foo ms_foo' } } def fake_parse_data(relid, unit, key): return rel_get_data.get(key, {}) parse_data.side_effect = fake_parse_data with mock.patch.object(hooks, 'status_set') as mock_status_set: hooks.ha_relation_changed() mock_status_set.assert_called_with('blocked', 'DNS HA invalid config')
def test_ha_relation_changed(self): _id_joined = self.patch('identity_joined') self.relation_get.return_value = True self.relation_ids.return_value = ['rid'] ceph_hooks.ha_relation_changed() _id_joined.assert_called_with(relid='rid')
def test_ha_relation_changed(self, parse_data, config, commit, get_corosync_conf, relation_ids, relation_set, get_cluster_nodes, related_units, configure_stonith, configure_monitor_host, configure_cluster_global, configure_corosync, is_leader, crm_opt_exists, wait_for_pcmk, write_maas_dns_address): def fake_crm_opt_exists(res_name): # res_ubuntu will take the "update resource" route return res_name == "res_ubuntu" crm_opt_exists.side_effect = fake_crm_opt_exists commit.return_value = 0 is_leader.return_value = True related_units.return_value = ['ha/0', 'ha/1', 'ha/2'] get_cluster_nodes.return_value = ['10.0.3.2', '10.0.3.3', '10.0.3.4'] relation_ids.return_value = ['hanode:1'] get_corosync_conf.return_value = True cfg = {'debug': False, 'prefer-ipv6': False, 'corosync_transport': 'udpu', 'corosync_mcastaddr': 'corosync_mcastaddr', 'cluster_count': 3} config.side_effect = lambda key: cfg.get(key) rel_get_data = {'locations': {'loc_foo': 'bar rule inf: meh eq 1'}, 'clones': {'cl_foo': 'res_foo meta interleave=true'}, 'groups': {'grp_foo': 'res_foo'}, 'colocations': {'co_foo': 'inf: grp_foo cl_foo'}, 'resources': {'res_foo': 'ocf:heartbeat:IPaddr2', 'res_bar': 'ocf:heartbear:IPv6addr', 'res_ubuntu': 'IPaddr2'}, 'resource_params': {'res_foo': 'params bar', 'res_ubuntu': 'params ubuntu=42'}, 'ms': {'ms_foo': 'res_foo meta notify=true'}, 'orders': {'foo_after': 'inf: res_foo ms_foo'}} def fake_parse_data(relid, unit, key): return rel_get_data.get(key, {}) parse_data.side_effect = fake_parse_data with mock.patch.object(tempfile, "NamedTemporaryFile", side_effect=lambda: self.tmpfile): hooks.ha_relation_changed() relation_set.assert_any_call(relation_id='hanode:1', ready=True) configure_stonith.assert_called_with() configure_monitor_host.assert_called_with() configure_cluster_global.assert_called_with() configure_corosync.assert_called_with() write_maas_dns_address.assert_not_called() for kw, key in [('location', 'locations'), ('clone', 'clones'), ('group', 'groups'), ('colocation', 'colocations'), ('primitive', 'resources'), ('ms', 'ms'), ('order', 'orders')]: for name, params in rel_get_data[key].items(): if name == "res_ubuntu": commit.assert_any_call( 'crm configure load update %s' % self.tmpfile.name) elif name in rel_get_data['resource_params']: res_params = rel_get_data['resource_params'][name] commit.assert_any_call( 'crm -w -F configure %s %s %s %s' % (kw, name, params, res_params)) else: commit.assert_any_call( 'crm -w -F configure %s %s %s' % (kw, name, params))