@@ -261,6 +261,19 @@ def unit_address(self) -> str:
261
261
"""Return the address of this unit."""
262
262
return self .get_unit_address ()
263
263
264
+ @property
265
+ def is_new_unit (self ) -> bool :
266
+ """Return whether the unit is a clean state.
267
+
268
+ e.g. scaling from zero units
269
+ """
270
+ _default_unit_data_keys = {
271
+ "egress-subnets" ,
272
+ "ingress-address" ,
273
+ "private-address" ,
274
+ }
275
+ return self .unit_peer_data .keys () == _default_unit_data_keys
276
+
264
277
def get_unit_hostname (self , unit_name : Optional [str ] = None ) -> str :
265
278
"""Get the hostname.localdomain for a unit.
266
279
@@ -424,8 +437,6 @@ def _reconcile_pebble_layer(self, container: Container) -> None:
424
437
):
425
438
container .stop (MYSQLD_EXPORTER_SERVICE )
426
439
427
- self ._on_update_status (None )
428
-
429
440
def _restart (self , event : EventBase ) -> None :
430
441
"""Restart the service."""
431
442
if self .peers .units != self .restart_peers .units :
@@ -702,6 +713,21 @@ def _on_mysql_pebble_ready(self, event) -> None:
702
713
self .unit .status = MaintenanceStatus ("Starting mysqld" )
703
714
logger .info ("Data directory is already initialised, skipping configuration" )
704
715
self ._reconcile_pebble_layer (container )
716
+ if self .is_new_unit :
717
+ # when unit is new and has data, it means the app is scaling out
718
+ # from zero units
719
+ logger .info ("Scaling out from zero units" )
720
+ if self .unit .is_leader ():
721
+ # create the cluster due it being dissolved on scale-down
722
+ self .create_cluster ()
723
+ self ._on_update_status (None )
724
+ else :
725
+ # Non-leader units try to join cluster
726
+ self .unit .status = WaitingStatus ("Waiting for instance to join the cluster" )
727
+ self .unit_peer_data .update ({
728
+ "member-role" : "secondary" ,
729
+ "member-state" : "waiting" ,
730
+ })
705
731
return
706
732
707
733
self .unit .status = MaintenanceStatus ("Initialising mysqld" )
@@ -845,10 +871,12 @@ def _on_update_status(self, _: Optional[UpdateStatusEvent]) -> None:
845
871
if not self .unit .is_leader () and self ._is_unit_waiting_to_join_cluster ():
846
872
# join cluster test takes precedence over blocked test
847
873
# due to matching criteria
874
+ logger .info ("Attempting to join cluster" )
848
875
self .join_unit_to_cluster ()
849
876
return
850
877
851
878
if self ._is_cluster_blocked ():
879
+ logger .info ("Cluster is blocked. Skipping." )
852
880
return
853
881
del self .restart_peers .data [self .unit ]["state" ]
854
882
@@ -926,6 +954,11 @@ def _on_database_storage_detaching(self, _) -> None:
926
954
# Inform other hooks of current status
927
955
self .unit_peer_data ["unit-status" ] = "removing"
928
956
957
+ if self .unit .is_leader ():
958
+ # Update 'units-added-to-cluster' counter in the peer relation databag
959
+ units = int (self .app_peer_data .get ("units-added-to-cluster" , 1 ))
960
+ self .app_peer_data ["units-added-to-cluster" ] = str (units - 1 )
961
+
929
962
930
963
if __name__ == "__main__" :
931
964
main (MySQLOperatorCharm )
0 commit comments