def upgrade():

    if is_leader():
        if is_unit_paused_set():
            log('Unit is paused, skiping upgrade', level=INFO)
            return

        # broadcast the bootstrap-uuid
        wsrep_ready = get_wsrep_value('wsrep_ready') or ""
        if wsrep_ready.lower() in ['on', 'ready']:
            cluster_state_uuid = get_wsrep_value('wsrep_cluster_state_uuid')
            if cluster_state_uuid:
                mark_seeded()
                notify_bootstrapped(cluster_uuid=cluster_state_uuid)
    else:
        # Ensure all the peers have the bootstrap-uuid attribute set
        # as this is all happening during the upgrade-charm hook is reasonable
        # to expect the cluster is running.

        # Wait until the leader has set the
        try:
            update_bootstrap_uuid()
        except LeaderNoBootstrapUUIDError:
            status_set('waiting', "Waiting for bootstrap-uuid set by leader")

    config_changed()
def leader_settings_changed():
    '''Re-trigger install once leader has seeded passwords into install'''
    install_percona_xtradb_cluster()
    # Notify any changes to data in leader storage
    update_shared_db_rels()
    log('leader-settings-changed', level='DEBUG')
    try:
        update_bootstrap_uuid()
    except LeaderNoBootstrapUUIDError:
        # until the bootstrap-uuid attribute is not replicated cluster_ready()
        # will evaluate to False, so it is necessary to feed back this info
        # to the user.
        status_set('waiting', "Waiting for bootstrap-uuid set by leader")
    def test_bootstrap_uuid_could_not_be_retrieved(self, mock_notify):
        self.leader_get.return_value = '1234-abcd'

        def fake_wsrep(k):
            d = {'wsrep_ready': 'ON', 'wsrep_cluster_state_uuid': ''}
            return d[k]

        self.get_wsrep_value.side_effect = fake_wsrep
        self.assertFalse(percona_utils.update_bootstrap_uuid())
        mock_notify.assert_not_called()
    def test_bootstrap_uuid_already_set(self):
        self.leader_get.return_value = '1234-abcd'

        def fake_wsrep(k):
            d = {'wsrep_ready': 'ON', 'wsrep_cluster_state_uuid': '1234-abcd'}
            return d[k]

        self.get_wsrep_value.side_effect = fake_wsrep
        self.relation_ids.return_value = ['cluster:2']
        self.is_leader.return_value = False
        percona_utils.update_bootstrap_uuid()
        self.relation_set.assert_called_with(relation_id='cluster:2',
                                             **{'bootstrap-uuid': '1234-abcd'})
        self.leader_set.assert_not_called()

        self.is_leader.return_value = True
        percona_utils.update_bootstrap_uuid()
        self.relation_set.assert_called_with(relation_id='cluster:2',
                                             **{'bootstrap-uuid': '1234-abcd'})
        self.leader_set.assert_called_with(**{'bootstrap-uuid': '1234-abcd'})
def upgrade():

    if is_leader():
        if is_unit_paused_set():
            log('Unit is paused, skiping upgrade', level=INFO)
            return

        # Leader sets on upgrade
        leader_set(**{'leader-ip': get_relation_ip('cluster')})
        configure_sstuser(sst_password())
        if not leader_get('root-password') and leader_get('mysql.passwd'):
            leader_set(**{'root-password': leader_get('mysql.passwd')})

        # On upgrade-charm we assume the cluster was complete at some point
        kvstore = kv()
        initial_clustered = kvstore.get(INITIAL_CLUSTERED_KEY, False)
        if not initial_clustered:
            kvstore.set(key=INITIAL_CLUSTERED_KEY, value=True)
            kvstore.flush()

        # broadcast the bootstrap-uuid
        wsrep_ready = get_wsrep_value('wsrep_ready') or ""
        if wsrep_ready.lower() in ['on', 'ready']:
            cluster_state_uuid = get_wsrep_value('wsrep_cluster_state_uuid')
            if cluster_state_uuid:
                mark_seeded()
                notify_bootstrapped(cluster_uuid=cluster_state_uuid)
    else:
        # Ensure all the peers have the bootstrap-uuid attribute set
        # as this is all happening during the upgrade-charm hook is reasonable
        # to expect the cluster is running.

        # Wait until the leader has set the
        try:
            update_bootstrap_uuid()
        except LeaderNoBootstrapUUIDError:
            status_set('waiting', "Waiting for bootstrap-uuid set by leader")
def upgrade():

    if is_leader():
        if is_unit_paused_set() or is_unit_upgrading_set():
            log('Unit is paused, skiping upgrade', level=INFO)
            return

        # Leader sets on upgrade
        leader_set(**{'leader-ip': get_relation_ip('cluster')})
        configure_sstuser(sst_password())
        if not leader_get('root-password') and leader_get('mysql.passwd'):
            leader_set(**{'root-password': leader_get('mysql.passwd')})

        # On upgrade-charm we assume the cluster was complete at some point
        kvstore = kv()
        initial_clustered = kvstore.get(INITIAL_CLUSTERED_KEY, False)
        if not initial_clustered:
            kvstore.set(key=INITIAL_CLUSTERED_KEY, value=True)
            kvstore.flush()

        # broadcast the bootstrap-uuid
        wsrep_ready = get_wsrep_value('wsrep_ready') or ""
        if wsrep_ready.lower() in ['on', 'ready']:
            cluster_state_uuid = get_wsrep_value('wsrep_cluster_state_uuid')
            if cluster_state_uuid:
                mark_seeded()
                notify_bootstrapped(cluster_uuid=cluster_state_uuid)
    else:
        # Ensure all the peers have the bootstrap-uuid attribute set
        # as this is all happening during the upgrade-charm hook is reasonable
        # to expect the cluster is running.

        # Wait until the leader has set the
        try:
            update_bootstrap_uuid()
        except LeaderNoBootstrapUUIDError:
            status_set('waiting', "Waiting for bootstrap-uuid set by leader")
def config_changed():

    # It is critical that the installation is attempted first before any
    # rendering of the configuration files occurs.
    # install_percona_xtradb_cluster has the code to decide if this is the
    # leader or if the leader is bootstrapped and therefore ready for install.
    install_percona_xtradb_cluster()

    # if we are paused, delay doing any config changed hooks.  It is forced on
    # the resume.
    if is_unit_paused_set():
        return

    if config('prefer-ipv6'):
        assert_charm_supports_ipv6()

    hosts = get_cluster_hosts()
    leader_bootstrapped = is_leader_bootstrapped()
    leader_ip = leader_get('leader-ip')

    if is_leader():
        # If the cluster has not been fully bootstrapped once yet, use an empty
        # hosts list to avoid restarting the leader node's mysqld during
        # cluster buildup.
        # After, the cluster has bootstrapped at least one time, it is much
        # less likely to have restart collisions. It is then safe to use the
        # full hosts list and have the leader node's mysqld restart.
        if not clustered_once():
            hosts = []
        log("Leader unit - bootstrap required=%s" % (not leader_bootstrapped),
            DEBUG)
        render_config_restart_on_changed(hosts,
                                         bootstrap=not leader_bootstrapped)
    elif leader_bootstrapped and is_sufficient_peers():
        # Speed up cluster process by bootstrapping when the leader has
        # bootstrapped if we have expected number of peers
        if leader_ip not in hosts:
            # Fix Bug #1738896
            hosts = [leader_ip] + hosts
        log("Leader is bootstrapped - configuring mysql on this node", DEBUG)
        # Rendering the mysqld.cnf and restarting is bootstrapping for a
        # non-leader node.
        render_config_restart_on_changed(hosts)
        # Assert we are bootstrapped. This will throw an
        # InconsistentUUIDError exception if UUIDs do not match.
        update_bootstrap_uuid()
    else:
        # Until the bootstrap-uuid attribute is set by the leader,
        # cluster_ready() will evaluate to False. So it is necessary to
        # feed this information to the user.
        status_set('waiting', "Waiting for bootstrap-uuid set by leader")
        log('Non-leader waiting on leader bootstrap, skipping render', DEBUG)
        return

    # Notify any changes to the access network
    update_client_db_relations()

    # (re)install pcmkr agent
    install_mysql_ocf()

    for rid in relation_ids('ha'):
        # make sure all the HA resources are (re)created
        ha_relation_joined(relation_id=rid)

    if is_relation_made('nrpe-external-master'):
        update_nrpe_config()

    open_port(DEFAULT_MYSQL_PORT)

    # the password needs to be updated only if the node was already
    # bootstrapped
    if is_bootstrapped():
        update_root_password()
        set_ready_on_peers()
def config_changed():

    # if we are paused or upgrading, delay doing any config changed hooks.
    # It is forced on the resume.
    if is_unit_paused_set() or is_unit_upgrading_set():
        log("Unit is paused or upgrading. Skipping config_changed", "WARN")
        return

    # It is critical that the installation is attempted first before any
    # rendering of the configuration files occurs.
    # install_percona_xtradb_cluster has the code to decide if this is the
    # leader or if the leader is bootstrapped and therefore ready for install.
    install_percona_xtradb_cluster()

    if config('prefer-ipv6'):
        assert_charm_supports_ipv6()

    hosts = get_cluster_hosts()
    leader_bootstrapped = is_leader_bootstrapped()
    leader_ip = leader_get('leader-ip')

    # Cluster upgrade adds some complication
    cluster_series_upgrading = leader_get("cluster_series_upgrading")
    if cluster_series_upgrading:
        leader = (leader_get('cluster_series_upgrade_leader') ==
                  get_relation_ip('cluster'))
        leader_ip = leader_get('cluster_series_upgrade_leader')
    else:
        leader = is_leader()
        leader_ip = leader_get('leader-ip')

    if leader:
        # If the cluster has not been fully bootstrapped once yet, use an empty
        # hosts list to avoid restarting the leader node's mysqld during
        # cluster buildup.
        # After, the cluster has bootstrapped at least one time, it is much
        # less likely to have restart collisions. It is then safe to use the
        # full hosts list and have the leader node's mysqld restart.
        # Empty hosts if cluster_series_upgrading
        if not clustered_once() or cluster_series_upgrading:
            hosts = []
        log("Leader unit - bootstrap required=%s" % (not leader_bootstrapped),
            DEBUG)
        render_config_restart_on_changed(hosts,
                                         bootstrap=not leader_bootstrapped)
    elif (leader_bootstrapped and
          is_sufficient_peers() and not
          cluster_series_upgrading):
        # Skip if cluster_series_upgrading
        # Speed up cluster process by bootstrapping when the leader has
        # bootstrapped if we have expected number of peers
        if leader_ip not in hosts:
            # Fix Bug #1738896
            hosts = [leader_ip] + hosts
        log("Leader is bootstrapped - configuring mysql on this node",
            DEBUG)
        # Rendering the mysqld.cnf and restarting is bootstrapping for a
        # non-leader node.
        render_config_restart_on_changed(hosts)
        # Assert we are bootstrapped. This will throw an
        # InconsistentUUIDError exception if UUIDs do not match.
        update_bootstrap_uuid()
    else:
        # Until the bootstrap-uuid attribute is set by the leader,
        # cluster_ready() will evaluate to False. So it is necessary to
        # feed this information to the user.
        status_set('waiting', "Waiting for bootstrap-uuid set by leader")
        log('Non-leader waiting on leader bootstrap, skipping render',
            DEBUG)
        return

    # Notify any changes to the access network
    update_client_db_relations()

    # (re)install pcmkr agent
    install_mysql_ocf()

    for rid in relation_ids('ha'):
        # make sure all the HA resources are (re)created
        ha_relation_joined(relation_id=rid)

    if is_relation_made('nrpe-external-master'):
        update_nrpe_config()

    open_port(DEFAULT_MYSQL_PORT)

    # the password needs to be updated only if the node was already
    # bootstrapped
    if is_bootstrapped():
        update_root_password()
        set_ready_on_peers()

    # NOTE(tkurek): re-set 'master' relation data
    if relation_ids('master'):
        master_joined()