Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DPE-2648] POC Remove shards #262

Merged
merged 51 commits into from
Oct 9, 2023
Merged
Show file tree
Hide file tree
Changes from 49 commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
ac24eed
charm can start as shard or config server
MiaAltieri Sep 13, 2023
f8ff8a1
mongos, shard, and config server all start without error
MiaAltieri Sep 14, 2023
9b64f31
use correct snap
MiaAltieri Sep 15, 2023
c167fad
Merge branch 'main' into start-shard-config-mongos
MiaAltieri Sep 15, 2023
11f3c65
fmt + lint
MiaAltieri Sep 15, 2023
4bf9d5f
update error processing
MiaAltieri Sep 15, 2023
e924c00
bump lib patch
MiaAltieri Sep 15, 2023
51a22ec
Merge branch 'main' into start-shard-config-mongos
MiaAltieri Sep 15, 2023
d1f0a0d
enable auth
MiaAltieri Sep 18, 2023
06af49a
mongos should be run on 0.0.0.0
MiaAltieri Sep 19, 2023
363db5f
addressing PR comments
MiaAltieri Sep 19, 2023
c4c0c27
Merge branch 'main' into start-shard-config-mongos
MiaAltieri Sep 19, 2023
ac78ed3
PR comments
MiaAltieri Sep 19, 2023
49cba1b
Merge branch 'main' into start-shard-config-mongos
MiaAltieri Sep 19, 2023
563f049
correct ip binding
MiaAltieri Sep 19, 2023
67964c7
Merge branch 'start-shard-config-mongos' into start-mongos-auth
MiaAltieri Sep 19, 2023
e8aaeb5
mongos and config server now start correctly, and mongos has auth ena…
MiaAltieri Sep 19, 2023
0598dde
cleaning up code
MiaAltieri Sep 19, 2023
7c64ce0
fix unit tests
MiaAltieri Sep 19, 2023
666f3dc
Merge branch '6/edge' into start-mongos-auth
MiaAltieri Sep 20, 2023
58d91fa
don't publish 6/edge changes to 5/edge
MiaAltieri Sep 20, 2023
80c8bf9
revert changes on init admin user
MiaAltieri Sep 20, 2023
02fcf7c
add new lib
MiaAltieri Sep 20, 2023
ff83789
set up basic relation structure
MiaAltieri Sep 20, 2023
426cff8
operator password and keyfile now shared from config server
MiaAltieri Sep 21, 2023
af99322
fixes + working with replicas now
MiaAltieri Sep 21, 2023
caef63d
add docstrings
MiaAltieri Sep 21, 2023
38b7b8f
unit, lint, fmt
MiaAltieri Sep 21, 2023
766a59b
simplify function for tox
MiaAltieri Sep 21, 2023
e6dff94
Merge branch '6/edge' into share-secrets
MiaAltieri Sep 21, 2023
a9f6cd6
personal nits
MiaAltieri Sep 21, 2023
0a432ea
PR comments
MiaAltieri Sep 22, 2023
059356f
propogating passwords of internal db users happens automatically
MiaAltieri Sep 22, 2023
bed71ce
fix bug in role retrieval
MiaAltieri Sep 25, 2023
b86259f
revert changes to set operator password
MiaAltieri Sep 27, 2023
315eaa5
Merge branch '6/edge' into share-secrets
MiaAltieri Sep 27, 2023
3f5d3d2
lint + fmt
MiaAltieri Sep 27, 2023
b8ca419
add shard works
MiaAltieri Sep 28, 2023
7f4da07
cleaning
MiaAltieri Sep 28, 2023
a940412
create lib file in charmcraft
MiaAltieri Sep 28, 2023
34b904e
shard removed from cluster
MiaAltieri Sep 29, 2023
15348ed
format + lint
MiaAltieri Sep 29, 2023
01f6b35
updates for new linter
MiaAltieri Oct 4, 2023
359a890
add context for future work
MiaAltieri Oct 4, 2023
7757e3f
correct drained fucntion
MiaAltieri Oct 4, 2023
1dd7952
fixing shard-removal
MiaAltieri Oct 5, 2023
35475d8
Merge branch '6/edge' into remove-shards
MiaAltieri Oct 5, 2023
f05d515
departed cannot access relation.units
MiaAltieri Oct 5, 2023
8f9176c
relation departed events will occur when units are removed, instead l…
MiaAltieri Oct 5, 2023
e8d7167
small fixes
MiaAltieri Oct 6, 2023
c5d49c2
pr comments
MiaAltieri Oct 6, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 81 additions & 4 deletions lib/charms/mongodb/v0/mongos.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@

import logging
from dataclasses import dataclass
from typing import Optional, Set
from typing import Dict, Optional, Set
from urllib.parse import quote_plus

from charms.mongodb.v0.mongodb import NotReadyError
from pymongo import MongoClient
from pymongo.errors import PyMongoError

from config import Config
MiaAltieri marked this conversation as resolved.
Show resolved Hide resolved

Expand Down Expand Up @@ -65,8 +65,16 @@ def uri(self):
)


class NotReadyError(PyMongoError):
"""Raised when not all replica set members healthy or finished initial sync."""
class RemovePrimaryShardError(Exception):
"""Raised when there is an attempt to remove the primary shard."""


class ShardNotInClusterError(Exception):
"""Raised when shard is not present in cluster, but it is expected to be."""


class ShardNotPlannedForRemovalError(Exception):
"""Raised when it is expected that a shard is planned for removal, but it is not."""


class MongosConnection:
Expand Down Expand Up @@ -158,6 +166,75 @@ def add_shard(self, shard_name, shard_hosts, shard_port=Config.MONGODB_PORT):
logger.info("Adding shard %s", shard_name)
self.client.admin.command("addShard", shard_url)

def remove_shard(self, shard_name: str) -> None:
"""Removes shard from the cluster.

Raises:
ConfigurationError, OperationFailure, NotReadyError,
RemovePrimaryShardError
"""
sc_status = self.client.admin.command("listShards")
# It is necessary to call removeShard multiple times on a shard to guarantee removal.
# Allow re-removal of shards that are currently draining.
if self._is_any_draining(sc_status, ignore_shard=shard_name):
cannot_remove_shard = (
f"cannot remove shard {shard_name} from cluster, another shard is draining"
)
logger.info(cannot_remove_shard)
MiaAltieri marked this conversation as resolved.
Show resolved Hide resolved
raise NotReadyError(cannot_remove_shard)

# TODO Follow up PR, there is no MongoDB command to retrieve primary shard, this is
# possible with mongosh.
primary_shard = False
if primary_shard:
MiaAltieri marked this conversation as resolved.
Show resolved Hide resolved
# TODO Future PR, support removing Primary Shard if there are no unsharded collections
# on it. All sharded collections should perform `MovePrimary`
cannot_remove_primary_shard = (
f"Shard {shard_name} is the primary shard, cannot remove."
)
logger.error(cannot_remove_primary_shard)
raise RemovePrimaryShardError(cannot_remove_primary_shard)

logger.info("Attempting to remove shard %s", shard_name)
self.client.admin.command("removeShard", shard_name)
logger.info("Shard %s, now draining", shard_name)
MiaAltieri marked this conversation as resolved.
Show resolved Hide resolved

def _is_shard_draining(self, shard_name: str) -> bool:
"""Reports if a given shard is currently in the draining state.

Raises:
ConfigurationError, OperationFailure, ShardNotInClusterError,
ShardNotPlannedForRemovalError
"""
sc_status = self.client.admin.command("listShards")
for shard in sc_status["shards"]:
if shard["_id"] == shard_name:
MiaAltieri marked this conversation as resolved.
Show resolved Hide resolved
if "draining" not in shard:
raise ShardNotPlannedForRemovalError(
f"Shard {shard_name} has not been marked for removal",
)
return shard["draining"]

raise ShardNotInClusterError(
f"Shard {shard_name} not in cluster, could not retrieve draining status"
)

@staticmethod
def _is_any_draining(sc_status: Dict, ignore_shard: str = "") -> bool:
"""Returns true if any shard members is draining.

Checks if any members in sharded cluster are draining data.

Args:
sc_status: current state of shard cluster status as reported by mongos.
ignore_shard: shard to ignore
"""
return any(
# check draining status of all shards except the one to be ignored.
shard.get("draining", False) if shard["_id"] != ignore_shard else False
for shard in sc_status["shards"]
)

@staticmethod
def _hostname_from_hostport(hostname: str) -> str:
"""Return hostname part from MongoDB returned.
Expand Down
Loading