17
17
)
18
18
from pydantic import ValidationError
19
19
20
+ from common .cassandra_client import CassandraClient
20
21
from core .config import CharmConfig
21
22
from core .state import ApplicationState , ClusterState , UnitWorkloadState
22
23
from core .statuses import Status
@@ -56,35 +57,91 @@ def _on_install(self, _: InstallEvent) -> None:
56
57
self .workload .install ()
57
58
58
59
def _on_start (self , event : StartEvent ) -> None :
59
- self .state .unit .workload_state = UnitWorkloadState .WAITING_FOR_START
60
60
self ._update_network_address ()
61
61
62
- if not self .charm .unit .is_leader () and not self .state .cluster .is_active :
63
- logger .debug ("Deferring on_start for unit due to cluster isn't initialized yet" )
64
- event .defer ()
65
- return
66
-
67
- if self .charm .unit .is_leader ():
68
- self .state .cluster .seeds = [self .state .unit .peer_url ]
69
-
70
62
try :
71
63
self .config_manager .render_env (
72
64
cassandra_limit_memory_mb = 1024 if self .charm .config .profile == "testing" else None
73
65
)
74
- self .config_manager .render_cassandra_config (
75
- cluster_name = self .charm .config .cluster_name ,
76
- listen_address = self .state .unit .ip ,
77
- seeds = self .state .cluster .seeds ,
78
- )
79
66
except ValidationError as e :
80
67
logger .debug (f"Config haven't passed validation: { e } " )
81
68
event .defer ()
82
69
return
83
70
71
+ if not self .charm .unit .is_leader ():
72
+ self ._start_subordinate (event )
73
+ return
74
+
75
+ self .state .cluster .seeds = [self .state .unit .peer_url ]
76
+
77
+ if self .state .unit .workload_state == UnitWorkloadState .CHANGING_PASSWORD :
78
+ self ._finalize_password_change (event )
79
+ return
80
+
81
+ if not self .state .unit .workload_state :
82
+ if self .state .cluster .cassandra_password_secret :
83
+ self ._start_leader ()
84
+ else :
85
+ self ._start_password_change (event )
86
+
87
+ def _start_subordinate (self , event : StartEvent ) -> None :
88
+ if not self .state .cluster .is_active :
89
+ self .state .unit .workload_state = UnitWorkloadState .WAITING_FOR_START
90
+ logger .debug ("Deferring on_start for unit due to cluster isn't initialized yet" )
91
+ event .defer ()
92
+ return
93
+ self .config_manager .render_cassandra_config (
94
+ cluster_name = self .charm .config .cluster_name ,
95
+ listen_address = self .state .unit .ip ,
96
+ seeds = self .state .cluster .seeds ,
97
+ authentication = True ,
98
+ )
84
99
self .workload .start ()
85
100
self .state .unit .workload_state = UnitWorkloadState .STARTING
86
101
102
+ def _start_leader (self ) -> None :
103
+ self .config_manager .render_cassandra_config (
104
+ cluster_name = self .charm .config .cluster_name ,
105
+ listen_address = self .state .unit .ip ,
106
+ seeds = self .state .cluster .seeds ,
107
+ authentication = True ,
108
+ )
109
+ self .workload .start ()
110
+ self .state .unit .workload_state = UnitWorkloadState .STARTING
111
+
112
+ def _start_password_change (self , event : StartEvent ) -> None :
113
+ self .config_manager .render_cassandra_config (
114
+ cluster_name = self .charm .config .cluster_name ,
115
+ listen_address = "127.0.0.1" ,
116
+ seeds = ["127.0.0.1:7000" ],
117
+ authentication = False ,
118
+ )
119
+ self .workload .start ()
120
+ self .state .unit .workload_state = UnitWorkloadState .CHANGING_PASSWORD
121
+ event .defer ()
122
+
123
+ def _finalize_password_change (self , event : StartEvent ) -> None :
124
+ if not self .cluster_manager .is_healthy :
125
+ event .defer ()
126
+ return
127
+ password = self .workload .generate_password ()
128
+ self ._cassandra .change_superuser_password ("cassandra" , password )
129
+ self .state .cluster .cassandra_password_secret = password
130
+ self .config_manager .render_cassandra_config (
131
+ cluster_name = self .charm .config .cluster_name ,
132
+ listen_address = self .state .unit .ip ,
133
+ seeds = self .state .cluster .seeds ,
134
+ authentication = True ,
135
+ )
136
+ self .workload .restart ()
137
+ self .state .unit .workload_state = UnitWorkloadState .STARTING
138
+
87
139
def _on_config_changed (self , _ : ConfigChangedEvent ) -> None :
140
+ if self .state .unit .workload_state not in [
141
+ UnitWorkloadState .STARTING ,
142
+ UnitWorkloadState .ACTIVE ,
143
+ ]:
144
+ return
88
145
try :
89
146
self .config_manager .render_env (
90
147
cassandra_limit_memory_mb = 1024 if self .charm .config .profile == "testing" else None
@@ -93,14 +150,14 @@ def _on_config_changed(self, _: ConfigChangedEvent) -> None:
93
150
cluster_name = self .charm .config .cluster_name ,
94
151
listen_address = self .state .unit .ip ,
95
152
seeds = self .state .cluster .seeds ,
153
+ authentication = True ,
96
154
)
97
155
except ValidationError as e :
98
156
logger .debug (f"Config haven't passed validation: { e } " )
99
157
return
100
- if not self .state .unit .workload_state == UnitWorkloadState .ACTIVE :
101
- return
102
158
self .workload .restart ()
103
- self .state .unit .workload_state = UnitWorkloadState .STARTING
159
+ if self .state .unit .workload_state == UnitWorkloadState .ACTIVE :
160
+ self .state .unit .workload_state = UnitWorkloadState .STARTING
104
161
105
162
def _on_update_status (self , _ : UpdateStatusEvent ) -> None :
106
163
if (
@@ -141,6 +198,9 @@ def _on_collect_unit_status(self, event: CollectStatusEvent) -> None:
141
198
] and (self .charm .unit .is_leader () or self .state .cluster .is_active ):
142
199
event .add_status (Status .STARTING .value )
143
200
201
+ if self .state .unit .workload_state == UnitWorkloadState .CHANGING_PASSWORD :
202
+ event .add_status (Status .CHANGING_PASSWORD .value )
203
+
144
204
event .add_status (Status .ACTIVE .value )
145
205
146
206
def _on_collect_app_status (self , event : CollectStatusEvent ) -> None :
@@ -165,3 +225,11 @@ def _update_network_address(self) -> bool:
165
225
and old_hostname is not None
166
226
and (old_ip != self .state .unit .ip or old_hostname != self .state .unit .hostname )
167
227
)
228
+
229
+ @property
230
+ def _cassandra (self ) -> CassandraClient :
231
+ return CassandraClient (
232
+ [self .state .unit .ip if self .state .cluster .cassandra_password_secret else "127.0.0.1" ],
233
+ "cassandra" ,
234
+ self .state .cluster .cassandra_password_secret or None ,
235
+ )
0 commit comments