Charm Interface - HA Cluster
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
OpenDev Sysadmins 0bc9985bb8 OpenDev Migration Patch 2 months ago
unit_tests Stop duplicates being added to delete_resources 6 months ago
.gitignore Add unit tests and fix for _parse bug exposed 6 months ago
.gitreview OpenDev Migration Patch 2 months ago
.testr.conf Add unit tests and fix for _parse bug exposed 6 months ago
.zuul.yaml Added tox environment for gathering coverage 3 months ago Add .gitreview, update tox.ini, update readme. 3 years ago Fix Python3.4 compability 4 months ago
copyright First commit of the proposed hacluster interface. 3 years ago
interface.yaml Add interface build ignore rules 6 months ago Adding support for deletion of vip, dns, and init services. 4 months ago
test-requirements.txt Add unit tests and fix for _parse bug exposed 6 months ago
tox.ini Added tox environment for gathering coverage 3 months ago


This interface handles the communication with the hacluster subordinate charm using the ha interface protocol.



The interface layer will set the following reactive states, as appropriate:

  • {relation_name}.connected The relation is established and ready for the local charm to configure the hacluster subordinate charm. The configuration of the resources to manage for the hacluster charm can be managed via one of the following methods:

    • manage_resources method
    • bind_on method

    Configuration of the managed resources within the hacluster can be managed by passing common.CRM object definitions to the manage_resources method.

  • {relation_name}.available The hacluster is up and ready.

For example:

from charms.reactive import when, when_not
from charms.reactive import set_state, remove_state

from relations.hacluster.common import CRM

def cluster_connected(hacluster):

    resources = CRM()
    resources.primitive('res_vip', 'ocf:IPAddr2',
                        params='ip= nic=eth0',
                        op='monitor interval="10s"')
    resources.clone('cl_res_vip', 'res_vip')

    hacluster.bind_on(iface='eth0', mcastport=4430)

Additionally, for more code clarity a custom object implements the interface defined in common.ResourceDescriptor can be used to simplify the code for reuse.

For example:

import ipaddress

from relation.hacluster.common import CRM
from relation.hacluster.common import ResourceDescriptor

class VirtualIP(ResourceDescriptor):
    def __init__(self, vip, nic='eth0'): = vip
        self.nic = 'eth0'

    def configure_resource(self, crm):
        ipaddr = ipaddress.ip_address(
        if isinstance(ipaddr, ipaddress.IPv4Address):
            res_type = 'ocf:heartbeat:IPAddr2'
            res_parms = 'ip={ip} nic={nic}'.format(,
            res_type = 'ocf:heartbeat:IPv6addr'
            res_params = 'ipv6addr={ip} nic={nic}'.format(,

        crm.primitive('res_vip', res_type, params=res_params,
                      op='monitor interval="10s"')
        crm.clone('cl_res_vip', 'res_vip')

Once the VirtualIP class above has been defined in charm code, it can make the code a bit cleaner. The example above can thusly be written as:

def cluster_connected(hacluster):
    resources = CRM()

    hacluster.bind_on(iface='eth0', mcastport=4430)