mongo-charms-single-kernel 1.8.7__py3-none-any.whl → 1.8.9__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of mongo-charms-single-kernel might be problematic. Click here for more details.
- {mongo_charms_single_kernel-1.8.7.dist-info → mongo_charms_single_kernel-1.8.9.dist-info}/METADATA +1 -1
- {mongo_charms_single_kernel-1.8.7.dist-info → mongo_charms_single_kernel-1.8.9.dist-info}/RECORD +30 -28
- single_kernel_mongo/config/literals.py +8 -3
- single_kernel_mongo/config/models.py +12 -0
- single_kernel_mongo/config/relations.py +2 -1
- single_kernel_mongo/config/statuses.py +127 -20
- single_kernel_mongo/core/operator.py +68 -1
- single_kernel_mongo/core/structured_config.py +2 -0
- single_kernel_mongo/core/workload.py +10 -4
- single_kernel_mongo/events/cluster.py +5 -0
- single_kernel_mongo/events/sharding.py +3 -1
- single_kernel_mongo/events/tls.py +183 -157
- single_kernel_mongo/exceptions.py +0 -8
- single_kernel_mongo/lib/charms/operator_libs_linux/v1/systemd.py +288 -0
- single_kernel_mongo/lib/charms/tls_certificates_interface/v4/tls_certificates.py +1995 -0
- single_kernel_mongo/managers/cluster.py +70 -28
- single_kernel_mongo/managers/config.py +14 -8
- single_kernel_mongo/managers/mongo.py +1 -1
- single_kernel_mongo/managers/mongodb_operator.py +53 -56
- single_kernel_mongo/managers/mongos_operator.py +18 -20
- single_kernel_mongo/managers/sharding.py +154 -127
- single_kernel_mongo/managers/tls.py +223 -206
- single_kernel_mongo/state/charm_state.py +39 -16
- single_kernel_mongo/state/cluster_state.py +8 -0
- single_kernel_mongo/state/config_server_state.py +9 -0
- single_kernel_mongo/state/tls_state.py +39 -12
- single_kernel_mongo/templates/enable-transparent-huge-pages.service.j2 +14 -0
- single_kernel_mongo/utils/helpers.py +4 -19
- single_kernel_mongo/lib/charms/tls_certificates_interface/v3/tls_certificates.py +0 -2123
- {mongo_charms_single_kernel-1.8.7.dist-info → mongo_charms_single_kernel-1.8.9.dist-info}/WHEEL +0 -0
- {mongo_charms_single_kernel-1.8.7.dist-info → mongo_charms_single_kernel-1.8.9.dist-info}/licenses/LICENSE +0 -0
|
@@ -105,6 +105,9 @@ class ClusterProvider(Object):
|
|
|
105
105
|
if int_tls_ca := self.state.tls.get_secret(label_name=SECRET_CA_LABEL, internal=True):
|
|
106
106
|
relation_data[ClusterStateKeys.INT_CA_SECRET.value] = int_tls_ca
|
|
107
107
|
|
|
108
|
+
if ext_tls_ca := self.state.tls.get_secret(label_name=SECRET_CA_LABEL, internal=False):
|
|
109
|
+
relation_data[ClusterStateKeys.EXT_CA_SECRET.value] = ext_tls_ca
|
|
110
|
+
|
|
108
111
|
if hashed_data := self.dependent.ldap_manager.get_hash():
|
|
109
112
|
relation_data[ClusterStateKeys.LDAP_HASH.value] = hashed_data
|
|
110
113
|
|
|
@@ -253,19 +256,19 @@ class ClusterRequirer(Object):
|
|
|
253
256
|
|
|
254
257
|
def assert_pass_hook_checks(self) -> None:
|
|
255
258
|
"""Runs pre-hook checks, raises if one fails."""
|
|
256
|
-
|
|
257
|
-
match (
|
|
259
|
+
mongos_peer_tls, config_server_peer_tls = self.mongos_and_config_server_peer_tls_status()
|
|
260
|
+
match (mongos_peer_tls, config_server_peer_tls):
|
|
258
261
|
case False, True:
|
|
259
262
|
raise DeferrableFailedHookChecksError(
|
|
260
|
-
"Config-Server uses TLS but mongos does not. Please synchronise encryption method."
|
|
263
|
+
"Config-Server uses peer TLS but mongos does not. Please synchronise encryption method."
|
|
261
264
|
)
|
|
262
265
|
case True, False:
|
|
263
266
|
raise DeferrableFailedHookChecksError(
|
|
264
|
-
"Mongos uses TLS but config-server does not. Please synchronise encryption method."
|
|
267
|
+
"Mongos uses peer TLS but config-server does not. Please synchronise encryption method."
|
|
265
268
|
)
|
|
266
269
|
case _:
|
|
267
270
|
pass
|
|
268
|
-
if self.
|
|
271
|
+
if self.dependent.tls_manager.is_waiting_for_a_cert():
|
|
269
272
|
raise DeferrableFailedHookChecksError(
|
|
270
273
|
"Mongos was waiting for config-server to enable TLS. Wait for TLS to be enabled until starting mongos."
|
|
271
274
|
)
|
|
@@ -431,10 +434,10 @@ class ClusterRequirer(Object):
|
|
|
431
434
|
with MongoConnection(self.state.mongo_config) as mongo:
|
|
432
435
|
mongo.drop_user(mongo.config.username)
|
|
433
436
|
|
|
434
|
-
def
|
|
435
|
-
"""Returns true if both the mongos and the config-server use the same CA.
|
|
437
|
+
def is_peer_ca_compatible(self) -> bool:
|
|
438
|
+
"""Returns true if both the mongos and the config-server use the same peer CA.
|
|
436
439
|
|
|
437
|
-
Using the same CA is a requirement for sharded clusters.
|
|
440
|
+
Using the same peer CA is a requirement for sharded clusters.
|
|
438
441
|
"""
|
|
439
442
|
if not self.state.mongos_cluster_relation:
|
|
440
443
|
return True
|
|
@@ -445,38 +448,77 @@ class ClusterRequirer(Object):
|
|
|
445
448
|
|
|
446
449
|
return config_server_tls_ca == mongos_tls_ca
|
|
447
450
|
|
|
448
|
-
def
|
|
449
|
-
"""Returns
|
|
450
|
-
if not self.state.tls_relation:
|
|
451
|
-
return False
|
|
452
|
-
mongos_tls_ca = self.state.tls.get_secret(internal=True, label_name=SECRET_CA_LABEL)
|
|
451
|
+
def is_client_ca_compatible(self) -> bool:
|
|
452
|
+
"""Returns true if both the mongos and the config-server use the same client CA.
|
|
453
453
|
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
454
|
+
Using the same client CA is a requirement for sharded clusters.
|
|
455
|
+
"""
|
|
456
|
+
if not self.state.mongos_cluster_relation:
|
|
457
|
+
return True
|
|
458
|
+
config_server_tls_ca = self.state.cluster.external_ca_secret
|
|
459
|
+
mongos_tls_ca = self.state.tls.get_secret(internal=False, label_name=SECRET_CA_LABEL)
|
|
460
|
+
if not config_server_tls_ca or not mongos_tls_ca:
|
|
461
|
+
return True
|
|
457
462
|
|
|
458
|
-
|
|
459
|
-
|
|
463
|
+
return config_server_tls_ca == mongos_tls_ca
|
|
464
|
+
|
|
465
|
+
def mongos_and_config_server_peer_tls_status(self) -> tuple[bool, bool]:
|
|
466
|
+
"""Returns the peer TLS integration status for mongos and config-server."""
|
|
460
467
|
if self.state.mongos_cluster_relation:
|
|
461
|
-
mongos_has_tls = self.state.
|
|
468
|
+
mongos_has_tls = self.state.peer_tls_relation is not None
|
|
462
469
|
config_server_has_tls = self.state.cluster.internal_ca_secret is not None
|
|
463
470
|
return mongos_has_tls, config_server_has_tls
|
|
464
471
|
|
|
465
472
|
return False, False
|
|
466
473
|
|
|
467
|
-
def
|
|
468
|
-
"""
|
|
469
|
-
|
|
470
|
-
|
|
474
|
+
def mongos_and_config_server_client_tls_status(self) -> tuple[bool, bool]:
|
|
475
|
+
"""Returns the client TLS integration status for mongos and config-server."""
|
|
476
|
+
if self.state.mongos_cluster_relation:
|
|
477
|
+
mongos_has_tls = self.state.client_tls_relation is not None
|
|
478
|
+
config_server_has_tls = self.state.cluster.external_ca_secret is not None
|
|
479
|
+
return mongos_has_tls, config_server_has_tls
|
|
480
|
+
|
|
481
|
+
return False, False
|
|
482
|
+
|
|
483
|
+
def get_tls_status(self, internal: bool):
|
|
484
|
+
"""Computes the TLS status for the scope.
|
|
485
|
+
|
|
486
|
+
Args:
|
|
487
|
+
internal: (bool) if true, represents the internal TLS, otherwise external TLS.
|
|
488
|
+
"""
|
|
489
|
+
if internal:
|
|
490
|
+
shard_tls, config_server_tls = self.mongos_and_config_server_peer_tls_status()
|
|
491
|
+
is_ca_compatible = self.is_peer_ca_compatible()
|
|
492
|
+
else:
|
|
493
|
+
shard_tls, config_server_tls = self.mongos_and_config_server_client_tls_status()
|
|
494
|
+
is_ca_compatible = self.is_client_ca_compatible()
|
|
495
|
+
|
|
496
|
+
match (shard_tls, config_server_tls):
|
|
471
497
|
case False, True:
|
|
472
|
-
|
|
498
|
+
logger.warning(
|
|
499
|
+
"Config-Server uses peer TLS but mongos does not. Please synchronise encryption method."
|
|
500
|
+
)
|
|
501
|
+
return MongosStatuses.missing_tls(internal=internal)
|
|
473
502
|
case True, False:
|
|
474
|
-
|
|
503
|
+
logger.warning(
|
|
504
|
+
"Mongos uses peer TLS but config-server does not. Please synchronise encryption method."
|
|
505
|
+
)
|
|
506
|
+
return MongosStatuses.invalid_tls(internal=internal)
|
|
475
507
|
case _:
|
|
476
508
|
pass
|
|
477
|
-
|
|
509
|
+
|
|
510
|
+
if not is_ca_compatible:
|
|
478
511
|
logger.error(
|
|
479
|
-
"
|
|
512
|
+
"Mongos is integrated to a different CA than the config server. Please use the same CA for all cluster components."
|
|
480
513
|
)
|
|
481
|
-
return MongosStatuses.
|
|
514
|
+
return MongosStatuses.incompatible_ca(internal=internal)
|
|
515
|
+
|
|
482
516
|
return None
|
|
517
|
+
|
|
518
|
+
def tls_statuses(self) -> list[StatusObject]:
|
|
519
|
+
"""Return statuses relevant to TLS."""
|
|
520
|
+
statuses = []
|
|
521
|
+
for internal in True, False:
|
|
522
|
+
if status := self.get_tls_status(internal=internal):
|
|
523
|
+
statuses.append(status)
|
|
524
|
+
return statuses
|
|
@@ -269,7 +269,7 @@ class MongoConfigManager(FileBasedConfigManager, ABC):
|
|
|
269
269
|
self.binding_ips,
|
|
270
270
|
self.port_parameter,
|
|
271
271
|
self.auth_parameter,
|
|
272
|
-
self.
|
|
272
|
+
self.client_tls_parameters,
|
|
273
273
|
self.log_options,
|
|
274
274
|
self.audit_options,
|
|
275
275
|
self.ldap_parameters,
|
|
@@ -332,16 +332,20 @@ class MongoConfigManager(FileBasedConfigManager, ABC):
|
|
|
332
332
|
def auth_parameter(self) -> dict[str, Any]:
|
|
333
333
|
"""The auth mode."""
|
|
334
334
|
cmd = {"security": {"authorization": "enabled"}} if self.auth else {}
|
|
335
|
-
if self.state.tls.
|
|
335
|
+
if self.state.tls.peer_enabled:
|
|
336
336
|
return always_merger.merge(
|
|
337
337
|
cmd,
|
|
338
338
|
{
|
|
339
339
|
"security": {"clusterAuthMode": "x509"},
|
|
340
340
|
"net": {
|
|
341
341
|
"tls": {
|
|
342
|
+
"mode": "preferTLS",
|
|
342
343
|
"allowInvalidCertificates": True,
|
|
343
|
-
"
|
|
344
|
+
"certificateKeyFile": f"{self.workload.paths.int_pem_file}",
|
|
345
|
+
"CAFile": f"{self.workload.paths.int_ca_file}",
|
|
346
|
+
"disabledProtocols": "TLS1_0,TLS1_1",
|
|
344
347
|
"clusterFile": f"{self.workload.paths.int_pem_file}",
|
|
348
|
+
"clusterCAFile": f"{self.workload.paths.int_ca_file}",
|
|
345
349
|
"clusterAuthX509": {
|
|
346
350
|
"attributes": f"O={self.state.get_subject_name()}",
|
|
347
351
|
},
|
|
@@ -360,10 +364,11 @@ class MongoConfigManager(FileBasedConfigManager, ABC):
|
|
|
360
364
|
)
|
|
361
365
|
|
|
362
366
|
@property
|
|
363
|
-
def
|
|
364
|
-
"""The TLS
|
|
365
|
-
|
|
366
|
-
|
|
367
|
+
def client_tls_parameters(self) -> dict[str, Any]:
|
|
368
|
+
"""The client TLS parameters."""
|
|
369
|
+
params = {}
|
|
370
|
+
if self.state.tls.client_enabled:
|
|
371
|
+
params = {
|
|
367
372
|
"net": {
|
|
368
373
|
"tls": {
|
|
369
374
|
"CAFile": f"{self.workload.paths.ext_ca_file}",
|
|
@@ -373,7 +378,8 @@ class MongoConfigManager(FileBasedConfigManager, ABC):
|
|
|
373
378
|
}
|
|
374
379
|
},
|
|
375
380
|
}
|
|
376
|
-
|
|
381
|
+
|
|
382
|
+
return params
|
|
377
383
|
|
|
378
384
|
@property
|
|
379
385
|
@abstractmethod
|
|
@@ -530,7 +530,7 @@ class MongoManager(Object, ManagerStatusProtocol):
|
|
|
530
530
|
return charm_statuses
|
|
531
531
|
|
|
532
532
|
except ServerSelectionTimeoutError as e:
|
|
533
|
-
# Usually it is
|
|
533
|
+
# Usually it is due to ReplicaSetNoPrimary
|
|
534
534
|
logger.debug(f"Got error {e} while checking replica set status")
|
|
535
535
|
return [MongodStatuses.WAITING_ELECTION.value]
|
|
536
536
|
except AutoReconnect as e:
|
|
@@ -13,10 +13,7 @@ import charm_refresh
|
|
|
13
13
|
from data_platform_helpers.advanced_statuses.models import StatusObject
|
|
14
14
|
from data_platform_helpers.advanced_statuses.protocol import ManagerStatusProtocol
|
|
15
15
|
from data_platform_helpers.advanced_statuses.types import Scope as DPHScope
|
|
16
|
-
from data_platform_helpers.version_check import
|
|
17
|
-
CrossAppVersionChecker,
|
|
18
|
-
get_charm_revision,
|
|
19
|
-
)
|
|
16
|
+
from data_platform_helpers.version_check import CrossAppVersionChecker, get_charm_revision
|
|
20
17
|
from ops.framework import Object
|
|
21
18
|
from ops.model import Container, ModelError, SecretNotFoundError, Unit
|
|
22
19
|
from pymongo.errors import OperationFailure, PyMongoError, ServerSelectionTimeoutError
|
|
@@ -25,7 +22,6 @@ from typing_extensions import override
|
|
|
25
22
|
|
|
26
23
|
from single_kernel_mongo.config.literals import (
|
|
27
24
|
FEATURE_VERSION,
|
|
28
|
-
OS_REQUIREMENTS,
|
|
29
25
|
CharmKind,
|
|
30
26
|
MongoPorts,
|
|
31
27
|
Scope,
|
|
@@ -37,7 +33,10 @@ from single_kernel_mongo.config.models import (
|
|
|
37
33
|
PasswordManagementContext,
|
|
38
34
|
PasswordManagementState,
|
|
39
35
|
)
|
|
40
|
-
from single_kernel_mongo.config.relations import
|
|
36
|
+
from single_kernel_mongo.config.relations import (
|
|
37
|
+
ExternalRequirerRelations,
|
|
38
|
+
RelationNames,
|
|
39
|
+
)
|
|
41
40
|
from single_kernel_mongo.config.statuses import (
|
|
42
41
|
BackupStatuses,
|
|
43
42
|
CharmStatuses,
|
|
@@ -51,19 +50,14 @@ from single_kernel_mongo.core.kubernetes_upgrades_v3 import KubernetesMongoDBRef
|
|
|
51
50
|
from single_kernel_mongo.core.machine_upgrades_v3 import MachineMongoDBRefresh
|
|
52
51
|
from single_kernel_mongo.core.operator import OperatorProtocol
|
|
53
52
|
from single_kernel_mongo.core.secrets import generate_secret_label
|
|
54
|
-
from single_kernel_mongo.core.structured_config import MongoDBRoles
|
|
53
|
+
from single_kernel_mongo.core.structured_config import MongoDBCharmConfig, MongoDBRoles
|
|
55
54
|
from single_kernel_mongo.core.version_checker import VersionChecker
|
|
56
|
-
from single_kernel_mongo.events.backups import
|
|
57
|
-
BackupEventsHandler,
|
|
58
|
-
)
|
|
55
|
+
from single_kernel_mongo.events.backups import BackupEventsHandler
|
|
59
56
|
from single_kernel_mongo.events.cluster import ClusterConfigServerEventHandler
|
|
60
57
|
from single_kernel_mongo.events.database import DatabaseEventsHandler
|
|
61
58
|
from single_kernel_mongo.events.ldap import LDAPEventHandler
|
|
62
59
|
from single_kernel_mongo.events.primary_action import PrimaryActionHandler
|
|
63
|
-
from single_kernel_mongo.events.sharding import
|
|
64
|
-
ConfigServerEventHandler,
|
|
65
|
-
ShardEventHandler,
|
|
66
|
-
)
|
|
60
|
+
from single_kernel_mongo.events.sharding import ConfigServerEventHandler, ShardEventHandler
|
|
67
61
|
from single_kernel_mongo.events.tls import TLSEventsHandler
|
|
68
62
|
from single_kernel_mongo.exceptions import (
|
|
69
63
|
BalancerNotEnabledError,
|
|
@@ -103,10 +97,7 @@ from single_kernel_mongo.managers.tls import TLSManager
|
|
|
103
97
|
from single_kernel_mongo.managers.upgrade_v3 import MongoDBUpgradesManager
|
|
104
98
|
from single_kernel_mongo.managers.upgrade_v3_status import MongoDBUpgradesStatusManager
|
|
105
99
|
from single_kernel_mongo.state.charm_state import CharmState
|
|
106
|
-
from single_kernel_mongo.utils.helpers import
|
|
107
|
-
is_valid_ldap_options,
|
|
108
|
-
is_valid_ldapusertodnmapping,
|
|
109
|
-
)
|
|
100
|
+
from single_kernel_mongo.utils.helpers import is_valid_ldap_options, is_valid_ldapusertodnmapping
|
|
110
101
|
from single_kernel_mongo.utils.mongo_connection import MongoConnection, NotReadyError
|
|
111
102
|
from single_kernel_mongo.utils.mongodb_users import (
|
|
112
103
|
BackupUser,
|
|
@@ -179,12 +170,7 @@ class MongoDBOperator(OperatorProtocol, Object):
|
|
|
179
170
|
self.state,
|
|
180
171
|
container,
|
|
181
172
|
)
|
|
182
|
-
self.tls_manager = TLSManager(
|
|
183
|
-
self,
|
|
184
|
-
self.workload,
|
|
185
|
-
self.state,
|
|
186
|
-
self.substrate,
|
|
187
|
-
)
|
|
173
|
+
self.tls_manager = TLSManager(self, self.workload, self.state)
|
|
188
174
|
self.mongo_manager = MongoManager(
|
|
189
175
|
self,
|
|
190
176
|
self.workload,
|
|
@@ -340,15 +326,15 @@ class MongoDBOperator(OperatorProtocol, Object):
|
|
|
340
326
|
return
|
|
341
327
|
logger.info("Restarting workloads")
|
|
342
328
|
# always apply the current charm revision's config
|
|
343
|
-
self.
|
|
344
|
-
self.
|
|
329
|
+
self._configure_workloads()
|
|
330
|
+
self.start_charm_services()
|
|
345
331
|
|
|
346
332
|
self.state.unit_peer_data.current_revision = self.cross_app_version_checker.version
|
|
347
333
|
|
|
348
|
-
if self.
|
|
349
|
-
self.
|
|
334
|
+
if self.name == CharmKind.MONGOD:
|
|
335
|
+
self._restart_related_services()
|
|
350
336
|
|
|
351
|
-
if self.
|
|
337
|
+
if self.mongo_manager.mongod_ready():
|
|
352
338
|
try:
|
|
353
339
|
self.upgrades_manager.wait_for_cluster_healthy()
|
|
354
340
|
refresh.next_unit_allowed_to_refresh = True
|
|
@@ -357,7 +343,8 @@ class MongoDBOperator(OperatorProtocol, Object):
|
|
|
357
343
|
return
|
|
358
344
|
|
|
359
345
|
@property
|
|
360
|
-
|
|
346
|
+
@override
|
|
347
|
+
def config(self) -> MongoDBCharmConfig:
|
|
361
348
|
"""Returns the actual config."""
|
|
362
349
|
return self.charm.parsed_config
|
|
363
350
|
|
|
@@ -405,6 +392,7 @@ class MongoDBOperator(OperatorProtocol, Object):
|
|
|
405
392
|
return (
|
|
406
393
|
self,
|
|
407
394
|
self.mongo_manager,
|
|
395
|
+
self.tls_manager,
|
|
408
396
|
self.shard_manager,
|
|
409
397
|
self.config_server_manager,
|
|
410
398
|
self.backup_manager,
|
|
@@ -499,7 +487,9 @@ class MongoDBOperator(OperatorProtocol, Object):
|
|
|
499
487
|
except (NotReadyError, PyMongoError, WorkloadExecError) as e:
|
|
500
488
|
logger.error(f"Deferring on start: error={e}")
|
|
501
489
|
self.state.statuses.add(
|
|
502
|
-
MongodStatuses.WAITING_REPL_SET_INIT.value,
|
|
490
|
+
MongodStatuses.WAITING_REPL_SET_INIT.value,
|
|
491
|
+
scope="unit",
|
|
492
|
+
component=self.name,
|
|
503
493
|
)
|
|
504
494
|
raise
|
|
505
495
|
|
|
@@ -891,22 +881,17 @@ class MongoDBOperator(OperatorProtocol, Object):
|
|
|
891
881
|
@override
|
|
892
882
|
def update_status(self) -> None:
|
|
893
883
|
"""Status update Handler."""
|
|
894
|
-
# TODO update the usage of this once the spec is approved and we have a consistent way of
|
|
895
|
-
# handling statuses
|
|
896
884
|
if self.basic_statuses():
|
|
897
885
|
logger.info("Early return invalid statuses.")
|
|
898
886
|
return
|
|
899
887
|
|
|
888
|
+
if self.state.is_role(MongoDBRoles.SHARD) and self._should_skip_because_of_incomplete_tls():
|
|
889
|
+
return
|
|
890
|
+
|
|
900
891
|
if self.cluster_version_checker.get_cluster_mismatched_revision_status():
|
|
901
892
|
logger.info("Early return, cluster mismatch version.")
|
|
902
893
|
return
|
|
903
894
|
|
|
904
|
-
if self.state.is_role(MongoDBRoles.SHARD):
|
|
905
|
-
shard_has_tls, config_server_has_tls = self.shard_manager.tls_status()
|
|
906
|
-
if config_server_has_tls and not shard_has_tls:
|
|
907
|
-
logger.info("Shard is missing TLS.")
|
|
908
|
-
return
|
|
909
|
-
|
|
910
895
|
if not self.mongo_manager.mongod_ready():
|
|
911
896
|
logger.info("Mongod not ready.")
|
|
912
897
|
return
|
|
@@ -1013,19 +998,6 @@ class MongoDBOperator(OperatorProtocol, Object):
|
|
|
1013
998
|
logger.exception(f"Failed to open port: {e}")
|
|
1014
999
|
raise
|
|
1015
1000
|
|
|
1016
|
-
def _set_os_config(self) -> None:
|
|
1017
|
-
"""Sets sysctl config for mongodb."""
|
|
1018
|
-
try:
|
|
1019
|
-
self.sysctl_config.configure(OS_REQUIREMENTS)
|
|
1020
|
-
except (sysctl.ApplyError, sysctl.ValidationError, sysctl.CommandError) as e:
|
|
1021
|
-
# we allow events to continue in the case that we are not able to correctly configure
|
|
1022
|
-
# sysctl config, since we can still run the workload with wrong sysctl parameters
|
|
1023
|
-
# even if it is not optimal.
|
|
1024
|
-
logger.error(f"Error setting values on sysctl: {e.message}")
|
|
1025
|
-
# containers share the kernel with the host system, and some sysctl parameters are
|
|
1026
|
-
# set at kernel level.
|
|
1027
|
-
logger.warning("sysctl params cannot be set. Is the machine running on a container?")
|
|
1028
|
-
|
|
1029
1001
|
@property
|
|
1030
1002
|
def primary_unit_name(self) -> str | None:
|
|
1031
1003
|
"""Retrieves the primary unit with the primary replica."""
|
|
@@ -1080,7 +1052,9 @@ class MongoDBOperator(OperatorProtocol, Object):
|
|
|
1080
1052
|
except WorkloadServiceError as e:
|
|
1081
1053
|
logger.error("An exception occurred when starting mongod agent, error: %s.", str(e))
|
|
1082
1054
|
self.charm.state.statuses.add(
|
|
1083
|
-
MongoDBStatuses.WAITING_FOR_MONGODB_START.value,
|
|
1055
|
+
MongoDBStatuses.WAITING_FOR_MONGODB_START.value,
|
|
1056
|
+
scope="unit",
|
|
1057
|
+
component=self.name,
|
|
1084
1058
|
)
|
|
1085
1059
|
raise
|
|
1086
1060
|
|
|
@@ -1100,7 +1074,9 @@ class MongoDBOperator(OperatorProtocol, Object):
|
|
|
1100
1074
|
self.backup_manager.configure_and_restart()
|
|
1101
1075
|
except WorkloadServiceError:
|
|
1102
1076
|
self.state.statuses.add(
|
|
1103
|
-
BackupStatuses.WAITING_FOR_PBM_START.value,
|
|
1077
|
+
BackupStatuses.WAITING_FOR_PBM_START.value,
|
|
1078
|
+
scope="unit",
|
|
1079
|
+
component=self.name,
|
|
1104
1080
|
)
|
|
1105
1081
|
raise
|
|
1106
1082
|
|
|
@@ -1141,7 +1117,10 @@ class MongoDBOperator(OperatorProtocol, Object):
|
|
|
1141
1117
|
logger.error("Charm is in sharding mode. Does not support %s interface.", rel_name)
|
|
1142
1118
|
return MongoDBStatuses.INVALID_CFG_SRV_ON_SHARD_REL.value
|
|
1143
1119
|
if self.state.is_role(MongoDBRoles.CONFIG_SERVER) and rel_name == RelationNames.SHARDING:
|
|
1144
|
-
logger.error(
|
|
1120
|
+
logger.error(
|
|
1121
|
+
"Charm is in config-server mode. Does not support %s interface.",
|
|
1122
|
+
rel_name,
|
|
1123
|
+
)
|
|
1145
1124
|
return MongoDBStatuses.INVALID_SHARD_ON_CFG_SRV_REL.value
|
|
1146
1125
|
if not self.state.is_role(MongoDBRoles.CONFIG_SERVER) and rel_name == RelationNames.CLUSTER:
|
|
1147
1126
|
logger.error("Charm is not a config-server, cannot integrate mongos")
|
|
@@ -1161,7 +1140,9 @@ class MongoDBOperator(OperatorProtocol, Object):
|
|
|
1161
1140
|
self.build_local_tls_directory()
|
|
1162
1141
|
|
|
1163
1142
|
# Push TLS files if necessary
|
|
1164
|
-
|
|
1143
|
+
for internal in [True, False]:
|
|
1144
|
+
self.tls_manager.push_tls_files_to_workload(internal)
|
|
1145
|
+
|
|
1165
1146
|
self.ldap_manager.save_certificates(self.state.ldap.chain)
|
|
1166
1147
|
|
|
1167
1148
|
# Update licenses
|
|
@@ -1379,3 +1360,19 @@ class MongoDBOperator(OperatorProtocol, Object):
|
|
|
1379
1360
|
scope="app",
|
|
1380
1361
|
component=self.name,
|
|
1381
1362
|
)
|
|
1363
|
+
|
|
1364
|
+
def _should_skip_because_of_incomplete_tls(self) -> bool:
|
|
1365
|
+
"""Checks if the update status hook needs skipping due to an incomplete TLS integration."""
|
|
1366
|
+
shard_has_peer_tls, config_server_has_peer_tls = (
|
|
1367
|
+
self.shard_manager.shard_and_config_server_peer_tls_status()
|
|
1368
|
+
)
|
|
1369
|
+
if config_server_has_peer_tls and not shard_has_peer_tls:
|
|
1370
|
+
logger.info("Shard is missing peer TLS.")
|
|
1371
|
+
return True
|
|
1372
|
+
shard_has_client_tls, config_server_has_client_tls = (
|
|
1373
|
+
self.shard_manager.shard_and_config_server_client_tls_status()
|
|
1374
|
+
)
|
|
1375
|
+
if config_server_has_client_tls and not shard_has_client_tls:
|
|
1376
|
+
logger.info("Shard is missing client TLS.")
|
|
1377
|
+
return True
|
|
1378
|
+
return False
|
|
@@ -46,6 +46,7 @@ from single_kernel_mongo.exceptions import (
|
|
|
46
46
|
from single_kernel_mongo.lib.charms.data_platform_libs.v0.data_interfaces import (
|
|
47
47
|
DatabaseProviderData,
|
|
48
48
|
)
|
|
49
|
+
from single_kernel_mongo.lib.charms.operator_libs_linux.v0 import sysctl
|
|
49
50
|
from single_kernel_mongo.managers.cluster import ClusterRequirer
|
|
50
51
|
from single_kernel_mongo.managers.config import MongosConfigManager
|
|
51
52
|
from single_kernel_mongo.managers.k8s import K8sManager
|
|
@@ -103,12 +104,7 @@ class MongosOperator(OperatorProtocol, Object):
|
|
|
103
104
|
self.state,
|
|
104
105
|
self.substrate,
|
|
105
106
|
)
|
|
106
|
-
self.tls_manager = TLSManager(
|
|
107
|
-
self,
|
|
108
|
-
self.workload,
|
|
109
|
-
self.state,
|
|
110
|
-
self.substrate,
|
|
111
|
-
)
|
|
107
|
+
self.tls_manager = TLSManager(self, self.workload, self.state)
|
|
112
108
|
self.cluster_manager = ClusterRequirer(
|
|
113
109
|
self, self.workload, self.state, self.substrate, RelationNames.CLUSTER
|
|
114
110
|
)
|
|
@@ -152,6 +148,7 @@ class MongosOperator(OperatorProtocol, Object):
|
|
|
152
148
|
ExternalRequirerRelations.LDAP,
|
|
153
149
|
ExternalRequirerRelations.LDAP_CERT,
|
|
154
150
|
)
|
|
151
|
+
self.sysctl_config = sysctl.Config(name=self.charm.app.name)
|
|
155
152
|
|
|
156
153
|
pod_name = self.model.unit.name.replace("/", "-")
|
|
157
154
|
self.k8s = K8sManager(pod_name, self.model.name)
|
|
@@ -199,9 +196,10 @@ class MongosOperator(OperatorProtocol, Object):
|
|
|
199
196
|
@property
|
|
200
197
|
def components(self) -> tuple[ManagerStatusProtocol, ...]:
|
|
201
198
|
"""The ordered list of components for this operator."""
|
|
202
|
-
return (self, self.ldap_manager, self.upgrades_status_manager)
|
|
199
|
+
return (self, self.tls_manager, self.ldap_manager, self.upgrades_status_manager)
|
|
203
200
|
|
|
204
201
|
@property
|
|
202
|
+
@override
|
|
205
203
|
def config(self) -> MongosCharmConfig:
|
|
206
204
|
"""Returns the actual config."""
|
|
207
205
|
return self.charm.parsed_config
|
|
@@ -220,8 +218,8 @@ class MongosOperator(OperatorProtocol, Object):
|
|
|
220
218
|
# Instantiate the local directory for k8s
|
|
221
219
|
self.build_local_tls_directory()
|
|
222
220
|
|
|
223
|
-
|
|
224
|
-
|
|
221
|
+
for internal in [True, False]:
|
|
222
|
+
self.tls_manager.push_tls_files_to_workload(internal)
|
|
225
223
|
|
|
226
224
|
# Save LDAP certificates
|
|
227
225
|
self.ldap_manager.save_certificates(self.state.ldap.chain)
|
|
@@ -299,8 +297,7 @@ class MongosOperator(OperatorProtocol, Object):
|
|
|
299
297
|
component=self.name,
|
|
300
298
|
)
|
|
301
299
|
self.update_k8s_external_services()
|
|
302
|
-
|
|
303
|
-
self.tls_manager.update_tls_sans()
|
|
300
|
+
self.tls_events.refresh_certificates()
|
|
304
301
|
self.share_connection_info()
|
|
305
302
|
|
|
306
303
|
@override
|
|
@@ -343,7 +340,7 @@ class MongosOperator(OperatorProtocol, Object):
|
|
|
343
340
|
# our SANS as necessary.
|
|
344
341
|
# The connection info will be updated when we receive the new certificates.
|
|
345
342
|
if self.substrate == Substrates.K8S:
|
|
346
|
-
self.
|
|
343
|
+
self.tls_events.refresh_certificates()
|
|
347
344
|
|
|
348
345
|
@override
|
|
349
346
|
def new_peer(self) -> None:
|
|
@@ -388,11 +385,10 @@ class MongosOperator(OperatorProtocol, Object):
|
|
|
388
385
|
self.mongos_config_manager.configure_and_restart(force=force)
|
|
389
386
|
except WorkloadServiceError as e:
|
|
390
387
|
logger.error("An exception occurred when starting mongos agent, error: %s.", str(e))
|
|
391
|
-
self.charm.
|
|
388
|
+
self.charm.state.statuses.add(
|
|
392
389
|
MongosStatuses.WAITING_FOR_MONGOS_START.value,
|
|
393
390
|
scope="unit",
|
|
394
|
-
|
|
395
|
-
component_name=self.name,
|
|
391
|
+
component=self.name,
|
|
396
392
|
)
|
|
397
393
|
raise
|
|
398
394
|
|
|
@@ -577,8 +573,9 @@ class MongosOperator(OperatorProtocol, Object):
|
|
|
577
573
|
)
|
|
578
574
|
return False
|
|
579
575
|
|
|
580
|
-
if
|
|
581
|
-
|
|
576
|
+
if statuses := self.cluster_manager.tls_statuses():
|
|
577
|
+
for status in statuses:
|
|
578
|
+
logger.info(f"Invalid TLS integration: {status.message}")
|
|
582
579
|
return False
|
|
583
580
|
|
|
584
581
|
if not self.is_mongos_running():
|
|
@@ -616,10 +613,11 @@ class MongosOperator(OperatorProtocol, Object):
|
|
|
616
613
|
# don't bother checking remaining statuses if no config-server is present
|
|
617
614
|
return charm_statuses
|
|
618
615
|
|
|
619
|
-
if
|
|
620
|
-
|
|
616
|
+
if statuses := self.cluster_manager.tls_statuses():
|
|
617
|
+
for status in statuses:
|
|
618
|
+
logger.info(f"Invalid TLS integration: {status.message}")
|
|
621
619
|
# if TLS is misconfigured we will get redherrings on the remaining messages
|
|
622
|
-
charm_statuses
|
|
620
|
+
charm_statuses += statuses
|
|
623
621
|
return charm_statuses
|
|
624
622
|
|
|
625
623
|
if self.state.mongos_cluster_relation and not self.state.cluster.config_server_uri:
|