Comment 4 for bug 1890505

Revision history for this message
Dmitrii Shcherbakov (dmitriis) wrote :

Two code-paths set relation data on the HA relation.

1) cluster_connected -> this_charm.configure_ha_resources -> configure_ha_resources -> hacluster.bind_resources
2) cluster_connected -> hacluster.manage_resources(crm)

I thought that the second call with a custom CRM object (where crm.resources == {}) might be a overriding the relation data but it turns out not to be the case base of "if v" here:

https://github.com/openstack/charm-interface-hacluster/blob/9ea447c296466ba9fdca1eb8e9752bbd6a75cc59/requires.py#L98
        relation_data = {
            'json_{}'.format(k): json.dumps(v, sort_keys=True)
            for k, v in crm.items() if v
        }

charms_openstack/charm/classes.py

    def configure_ha_resources(self, hacluster):
        """Inform the ha subordinate about each service it should manage. The
        child class specifies the services via self.ha_resources

        @param hacluster instance of interface class HAClusterRequires
        """
        RESOURCE_TYPES = {
            'vips': self._add_ha_vips_config,
            'haproxy': self._add_ha_haproxy_config,
            'dnsha': self._add_dnsha_config,
        }
        if self.ha_resources:
            for res_type in self.ha_resources:
                RESOURCE_TYPES[res_type](hacluster)
            hacluster.bind_resources(iface=self.config[IFACE_KEY]) # <-------- this

requires.py

    def manage_resources(self, crm): # <-------- this
        """
        Request for the hacluster to manage the resources defined in the
        crm object.

            res = CRM()
            res.primitive('res_neutron_haproxy', 'lsb:haproxy',
                          op='monitor interval="5s"')
            res.init_services('haproxy')
            res.clone('cl_nova_haproxy', 'res_neutron_haproxy')

            hacluster.manage_resources(crm)

        :param crm: CRM() instance - Config object for Pacemaker resources
        :returns: None
        """
        relation_data = {
            'json_{}'.format(k): json.dumps(v, sort_keys=True)
            for k, v in crm.items() if v
        }
        if data_changed('hacluster-manage_resources', relation_data):
            self.set_local(**relation_data)
            self.set_remote(**relation_data)

    def bind_resources(self, iface=None, mcastport=None):
        """Inform the ha subordinate about each service it should manage. The
        child class specifies the services via self.ha_resources

        :param iface: string - Network interface to bind to
        :param mcastport: int - Multicast port corosync should use for cluster
                                management traffic
        """
        if mcastport is None:
            mcastport = 4440
        resources_dict = self.get_local('resources')
        self.bind_on(iface=iface, mcastport=mcastport)
        if resources_dict:
            resources = relations.hacluster.common.CRM(**resources_dict) # <-------- this
            self.manage_resources(resources) # <-------- this

@reactive.when('ha.connected', 'ganesha-pool-configured',
               'config.rendered')
@reactive.when_not('ha.available')
def cluster_connected(hacluster):
    """Configure HA resources in corosync"""
    with charm.provide_charm_instance() as this_charm:
        this_charm.configure_ha_resources(hacluster) # <-------- this adds a vip resource via charms.openstack
        for service in ['nfs-ganesha', 'manila-share']:
            ch_core.host.service('disable', service)
            ch_core.host.service('stop', service)
        hacluster.add_systemd_service('nfs-ganesha',
                                      'nfs-ganesha',
                                      clone=False)
        hacluster.add_systemd_service('manila-share',
                                      'manila-share',
                                      clone=False)
        # This is a bit of a nasty hack to ensure that we can colocate the
        # services to make manila + ganesha colocate. This can be tidied up
        # once
        # https://bugs.launchpad.net/charm-interface-hacluster/+bug/1880644
        # is resolved
        import hooks.relations.hacluster.common as hacluster_common # noqa
        crm = hacluster_common.CRM() # <-------- this creates a new resource dict but it does not get populated from the existing local data.
        crm.colocation('ganesha_with_vip',
                       'inf',
                       'res_nfs_ganesha_nfs_ganesha',
                       'grp_ganesha_vips')
        crm.colocation('manila_with_vip',
                       'inf',
                       'res_manila_share_manila_share',
                       'grp_ganesha_vips')
        hacluster.manage_resources(crm) # # <-------- this adds json_collocations key values
        this_charm.assess_status()