def cluster_changed(): # Need to make sure hostname is excluded to build inclusion list (paying # attention to those excluded by default in peer_echo(). # TODO(dosaboy): extend peer_echo() to support providing exclusion list as # well as inclusion list. # NOTE(jamespage): deprecated - leader-election rdata = relation_get() inc_list = [] for attr in rdata.keys(): if attr not in [ 'hostname', 'private-address', 'cluster-address', 'public-address', 'ready' ]: inc_list.append(attr) peer_echo(includes=inc_list) # NOTE(jamespage): deprecated - leader-election maybe_notify_bootstrapped() cluster_joined() config_changed() if is_bootstrapped() and not seeded(): mark_seeded()
def config_changed(): # 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() clustered = len(hosts) > 1 bootstrapped = is_bootstrapped() # NOTE: only configure the cluster if we have sufficient peers. This only # applies if min-cluster-size is provided and is used to avoid extraneous # configuration changes and premature bootstrapping as the cluster is # deployed. if is_sufficient_peers(): try: # NOTE(jamespage): try with leadership election if is_leader(): log("Leader unit - bootstrap required=%s" % (not bootstrapped), DEBUG) render_config_restart_on_changed(clustered, hosts, bootstrap=not bootstrapped) elif bootstrapped: log("Cluster is bootstrapped - configuring mysql on this node", DEBUG) render_config_restart_on_changed(clustered, hosts) else: log("Not configuring", DEBUG) except NotImplementedError: # NOTE(jamespage): fallback to legacy behaviour. oldest = oldest_peer(peer_units()) if oldest: log("Leader unit - bootstrap required=%s" % (not bootstrapped), DEBUG) render_config_restart_on_changed(clustered, hosts, bootstrap=not bootstrapped) elif bootstrapped: log("Cluster is bootstrapped - configuring mysql on this node", DEBUG) render_config_restart_on_changed(clustered, hosts) else: log("Not configuring", DEBUG) # Notify any changes to the access network update_shared_db_rels() # (re)install pcmkr agent install_mysql_ocf() if relation_ids('ha'): # make sure all the HA resources are (re)created ha_relation_joined() if is_relation_made('nrpe-external-master'): update_nrpe_config()
def upgrade(): check_bootstrap = False try: if is_leader(): check_bootstrap = True except: if oldest_peer(peer_units()): check_bootstrap = True if check_bootstrap and not is_bootstrapped() and is_sufficient_peers(): # If this is the leader but we have not yet broadcast the cluster uuid # then do so now. 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) config_changed()
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 test_is_bootstrapped(self, mock_is_sufficient_peers): kvstore = mock.MagicMock() kvstore.get.return_value = False self.kv.return_value = kvstore # Not sufficient number of peers mock_is_sufficient_peers.return_value = False self.assertFalse(percona_utils.is_bootstrapped()) # Not all cluster ready mock_is_sufficient_peers.return_value = True self.relation_ids.return_value = ['cluster:0'] self.related_units.return_value = ['test/0', 'test/1'] self.relation_get.return_value = False _config = {'min-cluster-size': 3} self.config.side_effect = lambda key: _config.get(key) self.assertFalse(percona_utils.is_bootstrapped()) # kvstore.set has not been called with incomplete clusters kvstore.set.assert_not_called() # All cluster ready mock_is_sufficient_peers.return_value = True self.relation_ids.return_value = ['cluster:0'] self.related_units.return_value = ['test/0', 'test/1'] self.relation_get.return_value = 'UUID' _config = {'min-cluster-size': 3} self.config.side_effect = lambda key: _config.get(key) self.assertTrue(percona_utils.is_bootstrapped()) kvstore.set.assert_called_once_with(key='initial-cluster-complete', value=True) # Now set the key for clustered at least once kvstore.get.return_value = True kvstore.set.reset_mock() # Not all cluster ready no min-cluster-size mock_is_sufficient_peers.return_value = True self.relation_ids.return_value = ['cluster:0'] self.related_units.return_value = ['test/0', 'test/1'] self.relation_get.return_value = False _config = {'min-cluster-size': None} self.config.side_effect = lambda key: _config.get(key) self.assertFalse(percona_utils.is_bootstrapped()) kvstore.set.assert_not_called() # All cluster ready no min-cluster-size mock_is_sufficient_peers.return_value = True self.relation_ids.return_value = ['cluster:0'] self.related_units.return_value = ['test/0', 'test/1'] self.relation_get.return_value = 'UUID' _config = {'min-cluster-size': None} self.config.side_effect = lambda key: _config.get(key) self.assertTrue(percona_utils.is_bootstrapped()) # Assume single unit no-min-cluster-size mock_is_sufficient_peers.return_value = True self.relation_ids.return_value = [] self.related_units.return_value = [] self.relation_get.return_value = None _config = {'min-cluster-size': None} self.config.side_effect = lambda key: _config.get(key) self.assertTrue(percona_utils.is_bootstrapped())
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()