def test_is_leader_bootstrapped_once(self):
        leader_config = {
            'bootstrap-uuid': None,
            'mysql.passwd': None,
            'root-password': None,
            'sst-password': None
        }
        self.leader_get.return_value = leader_config
        self.assertFalse(percona_utils.is_leader_bootstrapped())

        leader_config = {
            'bootstrap-uuid': 'UUID',
            'mysql.passwd': None,
            'root-password': None,
            'sst-password': None
        }
        self.leader_get.return_value = leader_config
        self.assertFalse(percona_utils.is_leader_bootstrapped())

        leader_config = {
            'bootstrap-uuid': None,
            'mysql.passwd': None,
            'root-password': '******',
            'sst-password': None
        }
        self.leader_get.return_value = leader_config
        self.assertFalse(percona_utils.is_leader_bootstrapped())

        leader_config = {
            'bootstrap-uuid': 'UUID',
            'mysql.passwd': 'pass',
            'root-password': '******',
            'sst-password': '******',
            'leader-ip': '10.10.10.10'
        }
        self.leader_get.return_value = leader_config
        self.assertTrue(percona_utils.is_leader_bootstrapped())
def install_percona_xtradb_cluster():
    '''Attempt PXC install based on seeding of passwords for users'''
    if pxc_installed():
        log('MySQL already installed, skipping')
        return

    if not is_leader() and not is_leader_bootstrapped():
        log('Non-leader waiting on leader bootstrap, skipping percona install',
            DEBUG)
        return

    _root_password = root_password()
    _sst_password = sst_password()
    if not _root_password or not _sst_password:
        log('Passwords not seeded, unable to install MySQL at this'
            ' point so deferring installation')
        return
    configure_mysql_root_password(_root_password)

    apt_install(determine_packages(), fatal=True)

    configure_sstuser(_sst_password)
    if config('harden') and 'mysql' in config('harden'):
        run_mysql_checks()
def install_percona_xtradb_cluster():
    '''Attempt PXC install based on seeding of passwords for users'''
    if pxc_installed():
        log('MySQL already installed, skipping')
        return

    if not is_leader() and not is_leader_bootstrapped():
        log('Non-leader waiting on leader bootstrap, skipping percona install',
            DEBUG)
        return

    _root_password = root_password()
    _sst_password = sst_password()
    if not _root_password or not _sst_password:
        log('Passwords not seeded, unable to install MySQL at this'
            ' point so deferring installation')
        return
    configure_mysql_root_password(_root_password)

    apt_install(determine_packages(), fatal=True)

    configure_sstuser(_sst_password)
    if config('harden') and 'mysql' in config('harden'):
        run_mysql_checks()
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()