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

Use data of ceph report for analysis instead of multiple sources #86

Merged
merged 4 commits into from
Oct 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
63 changes: 36 additions & 27 deletions src/rookify/modules/analyze_ceph/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,36 +7,45 @@


class AnalyzeCephHandler(ModuleHandler):
def _process_command(
def _process_command_result(
self, state_data: Any, command: str, value: Optional[Any] = None
) -> bool:
"""Helper method to process commands by either setting or checking state data."""
parts = command.split(" ")
current_level = state_data # the root of the data structure
"""
Helper method to process commands by either setting or checking state data.
"""

command_parts = command.split(" ")
state_structure_data = state_data # the root of the data structure

# Traverse the dictionary structure based on command parts
for idx, part in enumerate(parts):
if len(parts) == idx + 1: # Last part of the command
if value is not None:
current_level[part] = value
else:
return part in current_level
for idx, key in enumerate(command_parts):
# Last part of the command
if len(command_parts) == idx + 1:
if value is None:
return key in state_structure_data

state_structure_data[key] = value
else:
if part not in current_level:
current_level[part] = {}
current_level = current_level[part]
if key not in state_structure_data:
state_structure_data[key] = {}

state_structure_data = state_structure_data[key]

return True

def preflight(self) -> Any:
commands = ["mon dump", "osd dump", "device ls", "fs ls", "node ls"]
state = self.machine.get_preflight_state("AnalyzeCephHandler")

if getattr(state, "data", None) is not None:
return

commands = ["fs ls", "node ls", "report"]
state.data = {}

# Execute each command and store the result
for command in commands:
result = self.ceph.mon_command(command)
self._process_command(state.data, command, result)
self._process_command_result(state.data, command, result)

self.logger.info("AnalyzeCephHandler ran successfully.")

Expand All @@ -45,25 +54,25 @@ def get_readable_key_value_state(self) -> Dict[str, str]:

kv_state_data = OrderedDict()

if "mon" not in state.data or "dump" not in state.data["mon"]:
kv_state_data["ceph mon dump"] = "Not analyzed yet"
if "report" not in state.data:
kv_state_data["Ceph report"] = "Not analyzed yet"
else:
kv_state_data["ceph mon dump"] = self._get_readable_json_dump(
state.data["mon"]["dump"]
kv_state_data["Ceph report"] = self._get_readable_json_dump(
state.data["report"]
)

if "osd" not in state.data or "dump" not in state.data["osd"]:
kv_state_data["ceph osd dump"] = "Not analyzed yet"
if "node" not in state.data or "ls" not in state.data["node"]:
kv_state_data["Ceph node ls"] = "Not analyzed yet"
else:
kv_state_data["ceph osd dump"] = self._get_readable_json_dump(
state.data["osd"]["dump"]
kv_state_data["Ceph node ls"] = self._get_readable_json_dump(
state.data["node"]["ls"]
)

if "device" not in state.data or "ls" not in state.data["device"]:
kv_state_data["OSD devices"] = "Not analyzed yet"
if "fs" not in state.data or "ls" not in state.data["fs"]:
kv_state_data["Ceph fs ls"] = "Not analyzed yet"
else:
kv_state_data["OSD devices"] = self._get_readable_json_dump(
state.data["device"]["ls"]
kv_state_data["Ceph fs ls"] = self._get_readable_json_dump(
state.data["fs"]["ls"]
)

return kv_state_data
Expand Down
2 changes: 1 addition & 1 deletion src/rookify/modules/cephx_auth_config/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@


class CephXAuthHandler(ModuleHandler):
def preflight(self) -> Any:
def preflight(self) -> None:
if not self.is_cephx_set(self.ceph.conf_get("auth_cluster_required")):
raise ModuleException(
"Ceph config value auth_cluster_required does not contain cephx"
Expand Down
4 changes: 2 additions & 2 deletions src/rookify/modules/create_rook_resources/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def __create_configmap_definition(self) -> None:
configmap_mon_list = ""
mapping = {}

for mon in state_data["mon"]["dump"]["mons"]:
for mon in state_data["report"]["monmap"]["mons"]:
if configmap_mon_list != "":
configmap_mon_list += ","

Expand Down Expand Up @@ -120,7 +120,7 @@ def execute(self) -> None:
secret_data = {
"admin-secret": admin_auth["key"],
"cluster-name": self._config["rook"]["cluster"]["name"],
"fsid": state_data["mon"]["dump"]["fsid"],
"fsid": state_data["report"]["monmap"]["fsid"],
"mon-secret": mon_auth["key"],
}

Expand Down
4 changes: 3 additions & 1 deletion src/rookify/modules/migrate_mds_pools/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,9 @@ def get_readable_key_value_state(self) -> Dict[str, str]:
"MigrateMdsPoolsHandler", "migrated_mds_pools", default_value=[]
)

pools = self.machine.get_preflight_state("MigrateMdsPoolsHandler").pools
pools = self.machine.get_preflight_state_data(
"MigrateMdsPoolsHandler", "pools", default_value={}
)

kv_state_data = OrderedDict()

Expand Down
6 changes: 3 additions & 3 deletions src/rookify/modules/migrate_mons/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,18 @@ def execute(self) -> None:
"MigrateMonsHandler", "migrated_mons", default_value=[]
)

if len(migrated_mons) >= len(state_data["mon"]["dump"]["mons"]):
if len(migrated_mons) >= len(state_data["report"]["monmap"]["mons"]):
return

for mon in state_data["mon"]["dump"]["mons"]:
for mon in state_data["report"]["monmap"]["mons"]:
self._migrate_mon(mon)

def get_readable_key_value_state(self) -> Dict[str, str]:
state_data = self.machine.get_preflight_state("AnalyzeCephHandler").data

return {
"ceph mon daemons": self._get_readable_json_dump(
state_data["mon"]["dump"]["mons"]
state_data["report"]["monmap"]["mons"]
)
}

Expand Down
2 changes: 1 addition & 1 deletion src/rookify/modules/migrate_osd_pools/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def _get_filtered_osd_pools_list(self) -> List[Dict[str, Any]]:
state_data = self.machine.get_preflight_state("AnalyzeCephHandler").data

osd_pool_configurations = self.ceph.get_osd_pool_configurations_from_osd_dump(
state_data["osd"]["dump"]
state_data["report"]["osdmap"]
)

pools = []
Expand Down
13 changes: 11 additions & 2 deletions src/rookify/modules/migrate_osds/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,15 @@


class MigrateOSDsHandler(ModuleHandler):
REQUIRES = ["migrate_mons"]
REQUIRES = ["analyze_ceph", "migrate_mons"]

def _get_devices_of_hosts(self) -> Dict[str, Dict[str, str]]:
state_data = self.machine.get_preflight_state("AnalyzeCephHandler").data

osd_devices: Dict[str, Dict[str, str]] = {}
osd_metadata = {
str(osd_data["id"]): osd_data for osd_data in state_data["osd_metadata"]
}

for osd_host, osds in state_data["node"]["ls"]["osd"].items():
osd_devices[osd_host] = {}
Expand All @@ -23,7 +27,12 @@ def _get_devices_of_hosts(self) -> Dict[str, Dict[str, str]]:
From there we try to get the encrypted volume partition UUID for later use in Rook.
"""
for osd_id in osds:
osd_data = self.ceph.mon_command("osd metadata", id=osd_id)
if osd_id not in osd_metadata:
raise ModuleException(
"Found Ceph OSD ID {0} without metadata".format(osd_id)
)

osd_data = osd_metadata[osd_id]

result = self.ssh.command(
osd_host,
Expand Down
14 changes: 9 additions & 5 deletions src/rookify/modules/migrate_rgw_pools/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@ def preflight(self) -> None:
if len(zones) > 0:
return

service_data = self.ceph.mon_command("service dump")

rgw_daemons = service_data["services"].get("rgw", {}).get("daemons", {})
rgw_daemons = (
state_data["report"]["servicemap"]["services"]
.get("rgw", {})
.get("daemons", {})
)

for rgw_daemon in rgw_daemons.values():
if not isinstance(rgw_daemon, dict):
Expand All @@ -36,7 +38,7 @@ def preflight(self) -> None:
zones[zone_name] = {"osd_pools": {}, "rgw_count": 1}

osd_pools = self.ceph.get_osd_pool_configurations_from_osd_dump(
state_data["osd"]["dump"]
state_data["report"]["osdmap"]
)

for zone_name in zones:
Expand Down Expand Up @@ -76,7 +78,9 @@ def get_readable_key_value_state(self) -> Dict[str, str]:
"MigrateRgwPoolsHandler", "migrated_pools", default_value=[]
)

zones = self.machine.get_preflight_state("MigrateRgwPoolsHandler").zones
zones = self.machine.get_preflight_state_data(
"MigrateRgwPoolsHandler", "zones", default_value={}
)

kv_state_data = OrderedDict()

Expand Down
8 changes: 5 additions & 3 deletions src/rookify/modules/migrate_rgws/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,14 @@


class MigrateRgwsHandler(ModuleHandler):
REQUIRES = ["migrate_rgw_pools"]
REQUIRES = ["analyze_ceph", "migrate_rgw_pools"]

def _get_rgw_daemon_hosts(self) -> List[str]:
ceph_status = self.ceph.mon_command("status")
state_data = self.machine.get_preflight_state("AnalyzeCephHandler").data

rgw_daemons = ceph_status["servicemap"]["services"]["rgw"]["daemons"]
rgw_daemons = state_data["report"]["servicemap"]["services"]["rgw"]["daemons"]
rgw_daemon_hosts = []

if "summary" in rgw_daemons:
del rgw_daemons["summary"]

Expand All @@ -23,6 +24,7 @@ def _get_rgw_daemon_hosts(self) -> List[str]:
raise ModuleException(
"Unexpected ceph-rgw daemon metadata: {0}".format(rgw_daemon)
)

if rgw_daemon["metadata"]["hostname"] not in rgw_daemon_hosts:
rgw_daemon_hosts.append(rgw_daemon["metadata"]["hostname"])

Expand Down
Loading