2
2
# Copyright 2025 Canonical Ltd.
3
3
# See LICENSE file for licensing details.
4
4
5
- """TODO ."""
5
+ """Application state definition ."""
6
6
7
7
import logging
8
8
from enum import StrEnum
16
16
from ops import Application , CharmBase , Object , Relation , Unit
17
17
18
18
PEER_RELATION = "cassandra-peers"
19
- PEER_PORT = 7000
20
- CLIENT_PORT = 9042
19
+ CASSANDRA_PEER_PORT = 7000
20
+ CASSANDRA_CLIENT_PORT = 9042
21
21
22
22
logger = logging .getLogger (__name__ )
23
23
24
24
25
25
class ClusterState (StrEnum ):
26
- """TODO ."""
26
+ """Current state of the Cassandra cluster ."""
27
27
28
28
UNKNOWN = ""
29
+ """Cassandra cluster isn't yet initialized by the leader unit."""
29
30
ACTIVE = "active"
31
+ """Cassandra cluster is initialized by the leader unit and active."""
30
32
31
33
32
34
class UnitWorkloadState (StrEnum ):
33
- """TODO ."""
35
+ """Current state of the Cassandra workload ."""
34
36
35
37
INSTALLING = ""
38
+ """Cassandra is installing."""
36
39
WAITING_FOR_START = "waiting_for_start"
40
+ """Subordinate unit is waiting for leader to initialize cluster before it starts workload."""
37
41
STARTING = "starting"
42
+ """Cassandra is starting."""
38
43
ACTIVE = "active"
44
+ """Cassandra is active and ready."""
39
45
40
46
41
47
class RelationState :
42
- """Relation state object ."""
48
+ """Basic class for relation bag mapping classes ."""
43
49
44
50
def __init__ (
45
51
self ,
@@ -54,9 +60,8 @@ def __init__(
54
60
55
61
def _field_setter_wrapper (self , field : str , value : str ) -> None :
56
62
if not self .relation :
57
- logger .warning (
58
- f"Field `{ field } ` were attempted to\
59
- be written on the relation before it exists."
63
+ logger .error (
64
+ f"Field `{ field } ` were attempted to be written on the relation before it exists."
60
65
)
61
66
return
62
67
@@ -70,7 +75,10 @@ def _field_setter_wrapper(self, field: str, value: str) -> None:
70
75
71
76
72
77
class UnitContext (RelationState ):
73
- """State/Relation data collection for a unit."""
78
+ """Unit context of the application state.
79
+
80
+ Provides mappings for the unit data bag of peer relation.
81
+ """
74
82
75
83
def __init__ (
76
84
self ,
@@ -88,14 +96,9 @@ def unit_id(self) -> int:
88
96
89
97
@property
90
98
def unit_name (self ) -> str :
91
- """The id of the unit from the unit name."""
99
+ """Unit name."""
92
100
return self .unit .name
93
101
94
- @property
95
- def node_name (self ) -> str :
96
- """The Human-readable name for this cassandra cluster node."""
97
- return f"{ self .unit .app .name } { self .unit_id } "
98
-
99
102
@property
100
103
def hostname (self ) -> str :
101
104
"""The hostname for the unit."""
@@ -116,17 +119,17 @@ def ip(self, value: str) -> None:
116
119
117
120
@property
118
121
def peer_url (self ) -> str :
119
- """The peer connection endpoint for the cassandra server."""
120
- return f"{ self .ip } :{ PEER_PORT } "
122
+ """The internode connection endpoint for the cassandra server from unit IP ."""
123
+ return f"{ self .ip } :{ CASSANDRA_PEER_PORT } "
121
124
122
125
@property
123
126
def client_url (self ) -> str :
124
- """The client connection endpoint for the cassandra server."""
125
- return f"{ self .ip } :{ CLIENT_PORT } "
127
+ """The client connection endpoint for the cassandra server from unit IP ."""
128
+ return f"{ self .ip } :{ CASSANDRA_CLIENT_PORT } "
126
129
127
130
@property
128
131
def workload_state (self ) -> UnitWorkloadState :
129
- """TODO ."""
132
+ """Current state of the Cassandra workload ."""
130
133
return self .relation_data .get ("workload_state" , UnitWorkloadState .INSTALLING )
131
134
132
135
@workload_state .setter
@@ -135,7 +138,10 @@ def workload_state(self, value: UnitWorkloadState) -> None:
135
138
136
139
137
140
class ClusterContext (RelationState ):
138
- """State/Relation data collection for the cassandra application."""
141
+ """Cluster context of the application state.
142
+
143
+ Provides mappings for the application data bag of peer relation.
144
+ """
139
145
140
146
def __init__ (
141
147
self ,
@@ -148,7 +154,7 @@ def __init__(
148
154
149
155
@property
150
156
def seeds (self ) -> list [str ]:
151
- """TODO ."""
157
+ """List of peer urls of Cassandra seed nodes ."""
152
158
seeds = self .relation_data .get ("seeds" , "" )
153
159
return seeds .split ("," ) if seeds else []
154
160
@@ -158,22 +164,21 @@ def seeds(self, value: list[str]) -> None:
158
164
159
165
@property
160
166
def state (self ) -> ClusterState :
161
- """The cluster state ('new' or 'existing') of the cassandra cluster."""
167
+ """Current state of the Cassandra cluster."""
162
168
return self .relation_data .get ("cluster_state" , ClusterState .UNKNOWN )
163
169
164
170
@state .setter
165
171
def state (self , value : ClusterState ) -> None :
166
- """TODO."""
167
172
self ._field_setter_wrapper ("cluster_state" , value .value )
168
173
169
174
@property
170
175
def is_active (self ) -> bool :
171
- """TODO ."""
176
+ """Is Cassandra cluster state `ACTIVE` ."""
172
177
return self .state == ClusterState .ACTIVE
173
178
174
179
175
180
class ApplicationState (Object ):
176
- """Global state object for the cassandra cluster ."""
181
+ """Mappings for the charm relations that forms global application state ."""
177
182
178
183
def __init__ (self , charm : CharmBase ):
179
184
super ().__init__ (parent = charm , key = "charm_state" )
@@ -185,12 +190,12 @@ def __init__(self, charm: CharmBase):
185
190
186
191
@property
187
192
def peer_relation (self ) -> Relation | None :
188
- """Get the cluster peer relation."""
193
+ """Cluster peer relation."""
189
194
return self .model .get_relation (PEER_RELATION )
190
195
191
196
@property
192
197
def peer_relation_units (self ) -> dict [Unit , DataPeerOtherUnitData ]:
193
- """Get unit data interface of all peer units from the cluster peer relation."""
198
+ """Unit data interface of all units in the cluster peer relation."""
194
199
if not self .peer_relation or not self .peer_relation .units :
195
200
return {}
196
201
@@ -201,7 +206,7 @@ def peer_relation_units(self) -> dict[Unit, DataPeerOtherUnitData]:
201
206
202
207
@property
203
208
def cluster (self ) -> ClusterContext :
204
- """Get the cluster context of the entire cassandra application ."""
209
+ """Cluster context."""
205
210
return ClusterContext (
206
211
relation = self .peer_relation ,
207
212
data_interface = self .peer_app_interface ,
@@ -210,7 +215,7 @@ def cluster(self) -> ClusterContext:
210
215
211
216
@property
212
217
def unit (self ) -> UnitContext :
213
- """Get the server state of this unit."""
218
+ """This unit context ."""
214
219
return UnitContext (
215
220
relation = self .peer_relation ,
216
221
data_interface = self .peer_unit_interface ,
@@ -219,24 +224,17 @@ def unit(self) -> UnitContext:
219
224
220
225
@property
221
226
def units (self ) -> set [UnitContext ]:
222
- """Get all nodes/units in the current peer relation, including this unit itself.
223
-
224
- Note: This is not to be confused with the list of cluster members.
225
-
226
- Returns:
227
- Set of CassandraUnitContexts with their unit data.
228
- """
229
- if not self .peer_relation :
230
- return set ()
227
+ """Contexts of all the units in the cluster peer relation, including this unit itself."""
228
+ return {self .unit , * self .other_units }
231
229
230
+ @property
231
+ def other_units (self ) -> set [UnitContext ]:
232
+ """Contexts of other units in the cluster peer relation."""
232
233
return {
233
- self .unit ,
234
- * (
235
- UnitContext (
236
- relation = self .peer_relation ,
237
- data_interface = data_interface ,
238
- component = unit ,
239
- )
240
- for unit , data_interface in self .peer_relation_units .items ()
241
- ),
234
+ UnitContext (
235
+ relation = self .peer_relation ,
236
+ data_interface = data_interface ,
237
+ component = unit ,
238
+ )
239
+ for unit , data_interface in self .peer_relation_units .items ()
242
240
}
0 commit comments