Pass data to hacluster charm using JSON
Encode dicts passed to hacluster charm using JSON serialization, supporting consistent data presentation under Python 3 where dict key iteration is non-deterministic. This is supported by prefixing json based data items with 'json_' and encoding with keys sorted. The charm will also clear any unprefixed based data items for upgrades. Change-Id: I21c6acff4a4a22cbcc5e6ea4e78394ce076e79d9 Closes-Bug: 1741304 Depends-On: I364a60ca7b91327fe88ee729cf49ff8ab3f5e2b6
This commit is contained in:
parent
7a61202a9d
commit
852d1f2f3a
|
@ -14,6 +14,7 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import json
|
||||
import sys
|
||||
import uuid
|
||||
from subprocess import (
|
||||
|
@ -298,6 +299,8 @@ def config_changed():
|
|||
amqp_joined(relation_id=r_id)
|
||||
for r_id in relation_ids('identity-service'):
|
||||
identity_joined(rid=r_id)
|
||||
for r_id in relation_ids('ha'):
|
||||
ha_joined(relation_id=r_id)
|
||||
[cluster_joined(rid) for rid in relation_ids('cluster')]
|
||||
|
||||
|
||||
|
@ -574,7 +577,12 @@ def ha_joined(relation_id=None):
|
|||
vip_group.append(vip_key)
|
||||
|
||||
if len(vip_group) >= 1:
|
||||
relation_set(groups={'grp_neutron_vips': ' '.join(vip_group)})
|
||||
relation_set(
|
||||
relation_id=relation_id,
|
||||
json_groups=json.dumps({
|
||||
'grp_neutron_vips': ' '.join(vip_group)
|
||||
}, sort_keys=True)
|
||||
)
|
||||
|
||||
init_services = {
|
||||
'res_neutron_haproxy': 'haproxy'
|
||||
|
@ -583,12 +591,22 @@ def ha_joined(relation_id=None):
|
|||
'cl_nova_haproxy': 'res_neutron_haproxy'
|
||||
}
|
||||
relation_set(relation_id=relation_id,
|
||||
init_services=init_services,
|
||||
corosync_bindiface=cluster_config['ha-bindiface'],
|
||||
corosync_mcastport=cluster_config['ha-mcastport'],
|
||||
resources=resources,
|
||||
resource_params=resource_params,
|
||||
clones=clones)
|
||||
json_init_services=json.dumps(init_services,
|
||||
sort_keys=True),
|
||||
json_resources=json.dumps(resources,
|
||||
sort_keys=True),
|
||||
json_resource_params=json.dumps(resource_params,
|
||||
sort_keys=True),
|
||||
json_clones=json.dumps(clones,
|
||||
sort_keys=True))
|
||||
|
||||
# NOTE(jamespage): Clear any non-json based keys
|
||||
relation_set(relation_id=relation_id,
|
||||
groups=None, init_services=None,
|
||||
resources=None, resource_params=None,
|
||||
clones=None)
|
||||
|
||||
|
||||
@hooks.hook('ha-relation-changed')
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
import sys
|
||||
|
||||
import yaml
|
||||
import json
|
||||
|
||||
from mock import MagicMock, patch, call
|
||||
from test_utils import CharmTestCase
|
||||
|
@ -233,12 +234,14 @@ class NeutronAPIHooksTests(CharmTestCase):
|
|||
_amqp_rel_joined = self.patch('amqp_joined')
|
||||
_id_rel_joined = self.patch('identity_joined')
|
||||
_id_cluster_joined = self.patch('cluster_joined')
|
||||
_id_ha_joined = self.patch('ha_joined')
|
||||
self._call_hook('config-changed')
|
||||
self.assertTrue(_n_api_rel_joined.called)
|
||||
self.assertTrue(_n_plugin_api_rel_joined.called)
|
||||
self.assertTrue(_amqp_rel_joined.called)
|
||||
self.assertTrue(_id_rel_joined.called)
|
||||
self.assertTrue(_id_cluster_joined.called)
|
||||
self.assertTrue(_id_ha_joined.called)
|
||||
self.assertTrue(self.CONFIGS.write_all.called)
|
||||
self.assertTrue(self.do_openstack_upgrade.called)
|
||||
self.assertTrue(self.apt_install.called)
|
||||
|
@ -275,6 +278,7 @@ class NeutronAPIHooksTests(CharmTestCase):
|
|||
_amqp_rel_joined = self.patch('amqp_joined')
|
||||
_id_rel_joined = self.patch('identity_joined')
|
||||
_id_cluster_joined = self.patch('cluster_joined')
|
||||
_id_ha_joined = self.patch('ha_joined')
|
||||
repo = 'cloud:trusty-juno'
|
||||
openstack_origin_git = {
|
||||
'repositories': [
|
||||
|
@ -304,6 +308,7 @@ class NeutronAPIHooksTests(CharmTestCase):
|
|||
self.assertTrue(_amqp_rel_joined.called)
|
||||
self.assertTrue(_id_rel_joined.called)
|
||||
self.assertTrue(_id_cluster_joined.called)
|
||||
self.assertTrue(_id_ha_joined.called)
|
||||
|
||||
@patch.object(hooks, 'git_install_requested')
|
||||
def test_config_changed_with_openstack_upgrade_action(self, git_requested):
|
||||
|
@ -769,23 +774,30 @@ class NeutronAPIHooksTests(CharmTestCase):
|
|||
self.get_netmask_for_address.return_value = '255.255.255.0'
|
||||
_relation_data = {
|
||||
'relation_id': None,
|
||||
'init_services': {'res_neutron_haproxy': 'haproxy'},
|
||||
'corosync_bindiface': _ha_config['ha-bindiface'],
|
||||
'corosync_mcastport': _ha_config['ha-mcastport'],
|
||||
'resources': {
|
||||
'json_init_services': json.dumps({
|
||||
'res_neutron_haproxy': 'haproxy'
|
||||
}, sort_keys=True),
|
||||
'json_resources': json.dumps({
|
||||
'res_neutron_eth0_vip': 'ocf:heartbeat:IPaddr2',
|
||||
'res_neutron_haproxy': 'lsb:haproxy'
|
||||
},
|
||||
'resource_params': {
|
||||
}, sort_keys=True),
|
||||
'json_resource_params': json.dumps({
|
||||
'res_neutron_eth0_vip': vip_params,
|
||||
'res_neutron_haproxy': 'op monitor interval="5s"'
|
||||
},
|
||||
'clones': {'cl_nova_haproxy': 'res_neutron_haproxy'}
|
||||
}, sort_keys=True),
|
||||
'json_clones': json.dumps({
|
||||
'cl_nova_haproxy': 'res_neutron_haproxy'
|
||||
}, sort_keys=True),
|
||||
}
|
||||
self._call_hook('ha-relation-joined')
|
||||
self.relation_set.assert_called_with(
|
||||
**_relation_data
|
||||
)
|
||||
self.relation_set.assert_has_calls([
|
||||
call(**_relation_data),
|
||||
call(clones=None, groups=None,
|
||||
init_services=None, relation_id=None,
|
||||
resource_params=None, resources=None),
|
||||
])
|
||||
|
||||
@patch.object(hooks, 'get_hacluster_config')
|
||||
def test_ha_joined_no_bound_ip(self, _get_ha_config):
|
||||
|
@ -802,23 +814,30 @@ class NeutronAPIHooksTests(CharmTestCase):
|
|||
self.get_netmask_for_address.return_value = None
|
||||
_relation_data = {
|
||||
'relation_id': None,
|
||||
'init_services': {'res_neutron_haproxy': 'haproxy'},
|
||||
'json_init_services': json.dumps({
|
||||
'res_neutron_haproxy': 'haproxy'
|
||||
}, sort_keys=True),
|
||||
'corosync_bindiface': _ha_config['ha-bindiface'],
|
||||
'corosync_mcastport': _ha_config['ha-mcastport'],
|
||||
'resources': {
|
||||
'json_resources': json.dumps({
|
||||
'res_neutron_eth120_vip': 'ocf:heartbeat:IPaddr2',
|
||||
'res_neutron_haproxy': 'lsb:haproxy'
|
||||
},
|
||||
'resource_params': {
|
||||
}, sort_keys=True),
|
||||
'json_resource_params': json.dumps({
|
||||
'res_neutron_eth120_vip': vip_params,
|
||||
'res_neutron_haproxy': 'op monitor interval="5s"'
|
||||
},
|
||||
'clones': {'cl_nova_haproxy': 'res_neutron_haproxy'}
|
||||
}, sort_keys=True),
|
||||
'json_clones': json.dumps({
|
||||
'cl_nova_haproxy': 'res_neutron_haproxy'
|
||||
}, sort_keys=True),
|
||||
}
|
||||
self._call_hook('ha-relation-joined')
|
||||
self.relation_set.assert_called_with(
|
||||
**_relation_data
|
||||
)
|
||||
self.relation_set.assert_has_calls([
|
||||
call(**_relation_data),
|
||||
call(clones=None, groups=None,
|
||||
init_services=None, relation_id=None,
|
||||
resource_params=None, resources=None),
|
||||
])
|
||||
|
||||
@patch.object(hooks, 'get_hacluster_config')
|
||||
def test_ha_joined_with_ipv6(self, _get_ha_config):
|
||||
|
@ -839,23 +858,30 @@ class NeutronAPIHooksTests(CharmTestCase):
|
|||
self.get_netmask_for_address.return_value = 'ffff.ffff.ffff.ffff'
|
||||
_relation_data = {
|
||||
'relation_id': None,
|
||||
'init_services': {'res_neutron_haproxy': 'haproxy'},
|
||||
'json_init_services': json.dumps({
|
||||
'res_neutron_haproxy': 'haproxy'
|
||||
}, sort_keys=True),
|
||||
'corosync_bindiface': _ha_config['ha-bindiface'],
|
||||
'corosync_mcastport': _ha_config['ha-mcastport'],
|
||||
'resources': {
|
||||
'json_resources': json.dumps({
|
||||
'res_neutron_eth0_vip': 'ocf:heartbeat:IPv6addr',
|
||||
'res_neutron_haproxy': 'lsb:haproxy'
|
||||
},
|
||||
'resource_params': {
|
||||
}, sort_keys=True),
|
||||
'json_resource_params': json.dumps({
|
||||
'res_neutron_eth0_vip': vip_params,
|
||||
'res_neutron_haproxy': 'op monitor interval="5s"'
|
||||
},
|
||||
'clones': {'cl_nova_haproxy': 'res_neutron_haproxy'}
|
||||
}, sort_keys=True),
|
||||
'json_clones': json.dumps({
|
||||
'cl_nova_haproxy': 'res_neutron_haproxy'
|
||||
}, sort_keys=True),
|
||||
}
|
||||
self._call_hook('ha-relation-joined')
|
||||
self.relation_set.assert_called_with(
|
||||
**_relation_data
|
||||
)
|
||||
self.relation_set.assert_has_calls([
|
||||
call(**_relation_data),
|
||||
call(clones=None, groups=None,
|
||||
init_services=None, relation_id=None,
|
||||
resource_params=None, resources=None),
|
||||
])
|
||||
|
||||
@patch.object(hooks, 'get_hacluster_config')
|
||||
def test_ha_joined_dns_ha(self, _get_hacluster_config):
|
||||
|
@ -875,24 +901,36 @@ class NeutronAPIHooksTests(CharmTestCase):
|
|||
'os-internal-hostname': None,
|
||||
'os-public-hostname': 'neutron-api.maas',
|
||||
}
|
||||
args = {
|
||||
_relation_data = {
|
||||
'relation_id': None,
|
||||
'corosync_bindiface': 'em0',
|
||||
'corosync_mcastport': '8080',
|
||||
'init_services': {'res_neutron_haproxy': 'haproxy'},
|
||||
'resources': {'res_neutron_public_hostname': 'ocf:maas:dns',
|
||||
'res_neutron_haproxy': 'lsb:haproxy'},
|
||||
'resource_params': {
|
||||
'json_init_services': json.dumps({
|
||||
'res_neutron_haproxy': 'haproxy'
|
||||
}, sort_keys=True),
|
||||
'json_resources': json.dumps({
|
||||
'res_neutron_public_hostname': 'ocf:maas:dns',
|
||||
'res_neutron_haproxy': 'lsb:haproxy'
|
||||
}, sort_keys=True),
|
||||
'json_resource_params': json.dumps({
|
||||
'res_neutron_public_hostname':
|
||||
'params fqdn="neutron-api.maas" ip_address="10.0.0.1"',
|
||||
'res_neutron_haproxy': 'op monitor interval="5s"'},
|
||||
'clones': {'cl_nova_haproxy': 'res_neutron_haproxy'}
|
||||
'res_neutron_haproxy': 'op monitor interval="5s"'
|
||||
}, sort_keys=True),
|
||||
'json_clones': json.dumps({
|
||||
'cl_nova_haproxy': 'res_neutron_haproxy'
|
||||
}, sort_keys=True),
|
||||
}
|
||||
self.update_dns_ha_resource_params.side_effect = _fake_update
|
||||
|
||||
hooks.ha_joined()
|
||||
self.assertTrue(self.update_dns_ha_resource_params.called)
|
||||
self.relation_set.assert_called_with(**args)
|
||||
self.relation_set.assert_has_calls([
|
||||
call(**_relation_data),
|
||||
call(clones=None, groups=None,
|
||||
init_services=None, relation_id=None,
|
||||
resource_params=None, resources=None),
|
||||
])
|
||||
|
||||
def test_ha_changed(self):
|
||||
self.test_relation.set({
|
||||
|
|
Loading…
Reference in New Issue