[hopem,r=gnuoy]
Fixes unicast ipv6 Closes-Bug: 1461145
This commit is contained in:
commit
974177bb78
@ -16,10 +16,12 @@ from charmhelpers.core.hookenv import (
|
|||||||
INFO,
|
INFO,
|
||||||
related_units,
|
related_units,
|
||||||
relation_ids,
|
relation_ids,
|
||||||
|
relation_get,
|
||||||
relation_set,
|
relation_set,
|
||||||
config,
|
config,
|
||||||
Hooks,
|
Hooks,
|
||||||
UnregisteredHookError,
|
UnregisteredHookError,
|
||||||
|
local_unit,
|
||||||
)
|
)
|
||||||
|
|
||||||
from charmhelpers.core.host import (
|
from charmhelpers.core.host import (
|
||||||
@ -51,9 +53,13 @@ from utils import (
|
|||||||
enable_lsb_services,
|
enable_lsb_services,
|
||||||
disable_lsb_services,
|
disable_lsb_services,
|
||||||
disable_upstart_services,
|
disable_upstart_services,
|
||||||
|
get_ipv6_addr,
|
||||||
)
|
)
|
||||||
|
|
||||||
from charmhelpers.contrib.charmsupport import nrpe
|
from charmhelpers.contrib.charmsupport import nrpe
|
||||||
|
from charmhelpers.contrib.network.ip import (
|
||||||
|
is_ipv6,
|
||||||
|
)
|
||||||
|
|
||||||
hooks = Hooks()
|
hooks = Hooks()
|
||||||
|
|
||||||
@ -97,6 +103,18 @@ def get_transport():
|
|||||||
return val
|
return val
|
||||||
|
|
||||||
|
|
||||||
|
def ensure_ipv6_requirements(hanode_rid):
|
||||||
|
# hanode relation needs ipv6 private-address
|
||||||
|
addr = relation_get(rid=hanode_rid, unit=local_unit(),
|
||||||
|
attribute='private-address')
|
||||||
|
log("Current private-address is %s" % (addr))
|
||||||
|
if not is_ipv6(addr):
|
||||||
|
addr = get_ipv6_addr()
|
||||||
|
log("New private-address is %s" % (addr))
|
||||||
|
relation_set(relation_id=hanode_rid,
|
||||||
|
**{'private-address': addr})
|
||||||
|
|
||||||
|
|
||||||
@hooks.hook()
|
@hooks.hook()
|
||||||
def config_changed():
|
def config_changed():
|
||||||
if config('prefer-ipv6'):
|
if config('prefer-ipv6'):
|
||||||
@ -108,6 +126,10 @@ def config_changed():
|
|||||||
|
|
||||||
enable_lsb_services('pacemaker')
|
enable_lsb_services('pacemaker')
|
||||||
|
|
||||||
|
if config('prefer-ipv6'):
|
||||||
|
for rid in relation_ids('hanode'):
|
||||||
|
ensure_ipv6_requirements(rid)
|
||||||
|
|
||||||
if configure_corosync():
|
if configure_corosync():
|
||||||
pcmk.wait_for_pcmk()
|
pcmk.wait_for_pcmk()
|
||||||
configure_cluster_global()
|
configure_cluster_global()
|
||||||
@ -124,10 +146,17 @@ def upgrade_charm():
|
|||||||
update_nrpe_config()
|
update_nrpe_config()
|
||||||
|
|
||||||
|
|
||||||
@hooks.hook('ha-relation-joined',
|
@hooks.hook('hanode-relation-joined',
|
||||||
'ha-relation-changed',
|
|
||||||
'hanode-relation-joined',
|
|
||||||
'hanode-relation-changed')
|
'hanode-relation-changed')
|
||||||
|
def hanode_relation_changed():
|
||||||
|
if config('prefer-ipv6'):
|
||||||
|
ensure_ipv6_requirements(None)
|
||||||
|
|
||||||
|
ha_relation_changed()
|
||||||
|
|
||||||
|
|
||||||
|
@hooks.hook('ha-relation-joined',
|
||||||
|
'ha-relation-changed')
|
||||||
def ha_relation_changed():
|
def ha_relation_changed():
|
||||||
# Check that we are related to a principle and that
|
# Check that we are related to a principle and that
|
||||||
# it has already provided the required corosync configuration
|
# it has already provided the required corosync configuration
|
||||||
|
@ -15,11 +15,11 @@ from charmhelpers.core.hookenv import (
|
|||||||
log,
|
log,
|
||||||
DEBUG,
|
DEBUG,
|
||||||
INFO,
|
INFO,
|
||||||
|
WARNING,
|
||||||
relation_get,
|
relation_get,
|
||||||
related_units,
|
related_units,
|
||||||
relation_ids,
|
relation_ids,
|
||||||
config,
|
config,
|
||||||
unit_private_ip,
|
|
||||||
unit_get,
|
unit_get,
|
||||||
)
|
)
|
||||||
from charmhelpers.contrib.openstack.utils import get_host_ip
|
from charmhelpers.contrib.openstack.utils import get_host_ip
|
||||||
@ -158,16 +158,6 @@ def get_corosync_id(unit_name):
|
|||||||
return off_set + int(unit_name.split('/')[1])
|
return off_set + int(unit_name.split('/')[1])
|
||||||
|
|
||||||
|
|
||||||
def get_ha_nodes():
|
|
||||||
ha_units = peer_ips(peer_relation='hanode')
|
|
||||||
ha_units[local_unit()] = unit_private_ip()
|
|
||||||
ha_nodes = {}
|
|
||||||
for unit in ha_units:
|
|
||||||
corosync_id = get_corosync_id(unit)
|
|
||||||
ha_nodes[corosync_id] = get_host_ip(ha_units[unit])
|
|
||||||
return ha_nodes
|
|
||||||
|
|
||||||
|
|
||||||
def nulls(data):
|
def nulls(data):
|
||||||
"""Returns keys of values that are null (but not bool)"""
|
"""Returns keys of values that are null (but not bool)"""
|
||||||
return [k for k in data.iterkeys()
|
return [k for k in data.iterkeys()
|
||||||
@ -297,9 +287,60 @@ def get_transport():
|
|||||||
return val
|
return val
|
||||||
|
|
||||||
|
|
||||||
|
def get_ipv6_addr():
|
||||||
|
"""Exclude any ip addresses configured or managed by corosync."""
|
||||||
|
excludes = []
|
||||||
|
for rid in relation_ids('ha'):
|
||||||
|
for unit in related_units(rid):
|
||||||
|
resources = parse_data(rid, unit, 'resources')
|
||||||
|
for res in resources.itervalues():
|
||||||
|
if 'ocf:heartbeat:IPv6addr' in res:
|
||||||
|
res_params = parse_data(rid, unit, 'resource_params')
|
||||||
|
res_p = res_params.get(res)
|
||||||
|
if res_p:
|
||||||
|
for k, v in res_p.itervalues():
|
||||||
|
if utils.is_ipv6(v):
|
||||||
|
log("Excluding '%s' from address list" % v,
|
||||||
|
level=DEBUG)
|
||||||
|
excludes.append(v)
|
||||||
|
|
||||||
|
return utils.get_ipv6_addr(exc_list=excludes)[0]
|
||||||
|
|
||||||
|
|
||||||
|
def get_ha_nodes():
|
||||||
|
ha_units = peer_ips(peer_relation='hanode')
|
||||||
|
ha_nodes = {}
|
||||||
|
for unit in ha_units:
|
||||||
|
corosync_id = get_corosync_id(unit)
|
||||||
|
addr = ha_units[unit]
|
||||||
|
if config('prefer-ipv6'):
|
||||||
|
if not utils.is_ipv6(addr):
|
||||||
|
# Not an error since cluster may still be forming/updating
|
||||||
|
log("Expected an ipv6 address but got %s" % (addr),
|
||||||
|
level=WARNING)
|
||||||
|
|
||||||
|
ha_nodes[corosync_id] = addr
|
||||||
|
else:
|
||||||
|
ha_nodes[corosync_id] = get_host_ip(addr)
|
||||||
|
|
||||||
|
corosync_id = get_corosync_id(local_unit())
|
||||||
|
if config('prefer-ipv6'):
|
||||||
|
addr = get_ipv6_addr()
|
||||||
|
else:
|
||||||
|
addr = get_host_ip(unit_get('private-address'))
|
||||||
|
|
||||||
|
ha_nodes[corosync_id] = addr
|
||||||
|
|
||||||
|
return ha_nodes
|
||||||
|
|
||||||
|
|
||||||
def get_cluster_nodes():
|
def get_cluster_nodes():
|
||||||
hosts = []
|
hosts = []
|
||||||
hosts.append(unit_get('private-address'))
|
if config('prefer-ipv6'):
|
||||||
|
hosts.append(get_ipv6_addr())
|
||||||
|
else:
|
||||||
|
hosts.append(unit_get('private-address'))
|
||||||
|
|
||||||
for relid in relation_ids('hanode'):
|
for relid in relation_ids('hanode'):
|
||||||
for unit in related_units(relid):
|
for unit in related_units(relid):
|
||||||
if relation_get('ready', rid=relid, unit=unit):
|
if relation_get('ready', rid=relid, unit=unit):
|
||||||
|
@ -25,6 +25,7 @@ class UtilsTestCase(unittest.TestCase):
|
|||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
shutil.rmtree(self.tmpdir)
|
shutil.rmtree(self.tmpdir)
|
||||||
|
|
||||||
|
@mock.patch.object(utils, 'get_ha_nodes', lambda *args: {'1': '10.0.0.1'})
|
||||||
@mock.patch.object(utils, 'relation_get')
|
@mock.patch.object(utils, 'relation_get')
|
||||||
@mock.patch.object(utils, 'related_units')
|
@mock.patch.object(utils, 'related_units')
|
||||||
@mock.patch.object(utils, 'relation_ids')
|
@mock.patch.object(utils, 'relation_ids')
|
||||||
@ -47,7 +48,6 @@ class UtilsTestCase(unittest.TestCase):
|
|||||||
related_units.return_value = ['unit-machine-0']
|
related_units.return_value = ['unit-machine-0']
|
||||||
relation_get.return_value = 'iface'
|
relation_get.return_value = 'iface'
|
||||||
|
|
||||||
utils.get_ha_nodes = mock.MagicMock()
|
|
||||||
conf = utils.get_corosync_conf()
|
conf = utils.get_corosync_conf()
|
||||||
|
|
||||||
if enabled:
|
if enabled:
|
||||||
@ -87,3 +87,62 @@ class UtilsTestCase(unittest.TestCase):
|
|||||||
def test_nulls(self):
|
def test_nulls(self):
|
||||||
self.assertEquals(utils.nulls({'a': '', 'b': None, 'c': False}),
|
self.assertEquals(utils.nulls({'a': '', 'b': None, 'c': False}),
|
||||||
['a', 'b'])
|
['a', 'b'])
|
||||||
|
|
||||||
|
@mock.patch.object(utils, 'local_unit', lambda *args: 'hanode/0')
|
||||||
|
@mock.patch.object(utils, 'get_ipv6_addr')
|
||||||
|
@mock.patch.object(utils, 'get_host_ip')
|
||||||
|
@mock.patch.object(utils.utils, 'is_ipv6', lambda *args: None)
|
||||||
|
@mock.patch.object(utils, 'get_corosync_id', lambda u: "%s-cid" % (u))
|
||||||
|
@mock.patch.object(utils, 'peer_ips', lambda *args, **kwargs:
|
||||||
|
{'hanode/1': '10.0.0.2'})
|
||||||
|
@mock.patch.object(utils, 'unit_get')
|
||||||
|
@mock.patch.object(utils, 'config')
|
||||||
|
def test_get_ha_nodes(self, mock_config, mock_unit_get, mock_get_host_ip,
|
||||||
|
mock_get_ipv6_addr):
|
||||||
|
mock_get_host_ip.side_effect = lambda host: host
|
||||||
|
|
||||||
|
def unit_get(key):
|
||||||
|
return {'private-address': '10.0.0.1'}.get(key)
|
||||||
|
|
||||||
|
mock_unit_get.side_effect = unit_get
|
||||||
|
|
||||||
|
def config(key):
|
||||||
|
return {'prefer-ipv6': False}.get(key)
|
||||||
|
|
||||||
|
mock_config.side_effect = config
|
||||||
|
nodes = utils.get_ha_nodes()
|
||||||
|
self.assertEqual(nodes, {'hanode/0-cid': '10.0.0.1',
|
||||||
|
'hanode/1-cid': '10.0.0.2'})
|
||||||
|
|
||||||
|
self.assertTrue(mock_get_host_ip.called)
|
||||||
|
self.assertFalse(mock_get_ipv6_addr.called)
|
||||||
|
|
||||||
|
@mock.patch.object(utils, 'local_unit', lambda *args: 'hanode/0')
|
||||||
|
@mock.patch.object(utils, 'get_ipv6_addr')
|
||||||
|
@mock.patch.object(utils, 'get_host_ip')
|
||||||
|
@mock.patch.object(utils.utils, 'is_ipv6')
|
||||||
|
@mock.patch.object(utils, 'get_corosync_id', lambda u: "%s-cid" % (u))
|
||||||
|
@mock.patch.object(utils, 'peer_ips', lambda *args, **kwargs:
|
||||||
|
{'hanode/1': '2001:db8:1::2'})
|
||||||
|
@mock.patch.object(utils, 'unit_get')
|
||||||
|
@mock.patch.object(utils, 'config')
|
||||||
|
def test_get_ha_nodes_ipv6(self, mock_config, mock_unit_get, mock_is_ipv6,
|
||||||
|
mock_get_host_ip, mock_get_ipv6_addr):
|
||||||
|
mock_get_ipv6_addr.return_value = '2001:db8:1::1'
|
||||||
|
mock_get_host_ip.side_effect = lambda host: host
|
||||||
|
|
||||||
|
def unit_get(key):
|
||||||
|
return {'private-address': '10.0.0.1'}.get(key)
|
||||||
|
|
||||||
|
mock_unit_get.side_effect = unit_get
|
||||||
|
|
||||||
|
def config(key):
|
||||||
|
return {'prefer-ipv6': True}.get(key)
|
||||||
|
|
||||||
|
mock_config.side_effect = config
|
||||||
|
nodes = utils.get_ha_nodes()
|
||||||
|
self.assertEqual(nodes, {'hanode/0-cid': '2001:db8:1::1',
|
||||||
|
'hanode/1-cid': '2001:db8:1::2'})
|
||||||
|
|
||||||
|
self.assertFalse(mock_get_host_ip.called)
|
||||||
|
self.assertTrue(mock_get_ipv6_addr.called)
|
||||||
|
Loading…
Reference in New Issue
Block a user