Merge "Add ceph -s keywords"
This commit is contained in:
52
keywords/ceph/ceph_status_keywords.py
Normal file
52
keywords/ceph/ceph_status_keywords.py
Normal file
@@ -0,0 +1,52 @@
|
||||
from framework.ssh.ssh_connection import SSHConnection
|
||||
from framework.validation.validation import validate_equals_with_retry
|
||||
from keywords.base_keyword import BaseKeyword
|
||||
from keywords.ceph.object.ceph_status_output import CephStatusOutput
|
||||
|
||||
|
||||
class CephStatusKeywords(BaseKeyword):
|
||||
"""
|
||||
Class for ceph -s Keywords
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, ssh_connection: SSHConnection):
|
||||
self.ssh_connection = ssh_connection
|
||||
|
||||
def ceph_status(self) -> CephStatusOutput:
|
||||
"""
|
||||
Run ceph -s command
|
||||
|
||||
Args: None
|
||||
|
||||
Returns: CephStatusOutput
|
||||
|
||||
"""
|
||||
output = self.ssh_connection.send("ceph -s")
|
||||
self.validate_success_return_code(self.ssh_connection)
|
||||
ceph_status_output = CephStatusOutput(output)
|
||||
return ceph_status_output
|
||||
|
||||
def wait_for_ceph_health_status(self, expect_health_status: bool = None, timeout: int = 1800) -> bool:
|
||||
"""
|
||||
Waits timeout amount of time for ceph to be in the given status
|
||||
|
||||
Args:
|
||||
expect_health_status (bool): Ture (HEALTH_OK) or False (HEALTH_WARN)
|
||||
timeout (int): the timeout in secs
|
||||
|
||||
Returns:
|
||||
bool: True: ceph health status match expect status
|
||||
False: ceph health status not match expect status
|
||||
|
||||
"""
|
||||
if expect_health_status not in (True, False):
|
||||
raise ValueError(f"expect_health_status:{expect_health_status} is not valid.")
|
||||
|
||||
def get_ceph_health_status():
|
||||
output = self.ssh_connection.send("ceph -s")
|
||||
ceph_status_output = CephStatusOutput(output)
|
||||
return ceph_status_output.is_ceph_healthy()
|
||||
|
||||
msg = f"Current ceph health status should match expected status:{expect_health_status}"
|
||||
validate_equals_with_retry(get_ceph_health_status, expect_health_status, msg, timeout=timeout)
|
59
keywords/ceph/ceph_status_section_table_parser.py
Normal file
59
keywords/ceph/ceph_status_section_table_parser.py
Normal file
@@ -0,0 +1,59 @@
|
||||
import re
|
||||
|
||||
from framework.exceptions.keyword_exception import KeywordException
|
||||
|
||||
|
||||
class CephStatusSectionTableParser:
|
||||
"""
|
||||
Class for ceph -s section table parsing
|
||||
|
||||
Example:
|
||||
["health: HEALTH_WARN",
|
||||
"2 MDSs report slow metadata IOs",
|
||||
"Reduced data availability: 48 pgs inactive",
|
||||
"Degraded data redundancy: 66/196 objects degraded (33.673%), 11 pgs degraded, 48 pgs undersized"]
|
||||
|
||||
OR
|
||||
|
||||
["mon: 3 daemons, quorum a,b,c (age 2w)",
|
||||
"mgr: b(active, since 46s), standbys: c, a",
|
||||
"mds: 1/1 daemons up, 1 hot standby",
|
||||
"osd: 5 osds: 5 up (since 2w), 5 in (since 2w)"]
|
||||
"""
|
||||
|
||||
def __init__(self, ceph_status_section_output: list[str]):
|
||||
"""
|
||||
Constructor
|
||||
|
||||
Args:
|
||||
ceph_status_section_output (list[str]): a list of strings representing one section output of 'ceph -s' command
|
||||
"""
|
||||
self.ceph_status_section_output = ceph_status_section_output
|
||||
|
||||
def get_output_values_dict(self) -> {}:
|
||||
"""
|
||||
Getter for output values dict
|
||||
|
||||
Returns:
|
||||
{}: the output values dict
|
||||
|
||||
"""
|
||||
output_values_dict = {}
|
||||
for row in self.ceph_status_section_output:
|
||||
# Only health section has extra lines
|
||||
if "health" in output_values_dict:
|
||||
output_values_dict["health"] += "; " + row
|
||||
continue
|
||||
# splits the string at the first colon followed by any amount of whitespace.
|
||||
values = re.split(r":\s*", row, maxsplit=1)
|
||||
if len(values) == 2:
|
||||
key, value = values
|
||||
output_values_dict[key] = value
|
||||
else:
|
||||
# just a newline -- continue
|
||||
if not values or len(values) == 1:
|
||||
continue
|
||||
else:
|
||||
raise KeywordException(f"Line with values: {row} was not in the expected format")
|
||||
|
||||
return output_values_dict
|
26
keywords/ceph/object/ceph_status_cluster_object.py
Normal file
26
keywords/ceph/object/ceph_status_cluster_object.py
Normal file
@@ -0,0 +1,26 @@
|
||||
class CephClusterObject:
|
||||
"""
|
||||
Object to hold the values of Ceph Cluster Object
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.id: str = ""
|
||||
self.health: str = ""
|
||||
|
||||
def get_id(self) -> str:
|
||||
"""
|
||||
Getter for id
|
||||
|
||||
Returns: id
|
||||
|
||||
"""
|
||||
return self.id
|
||||
|
||||
def get_health(self) -> str:
|
||||
"""
|
||||
Getter for ceph health status
|
||||
|
||||
Returns: health
|
||||
|
||||
"""
|
||||
return self.health
|
51
keywords/ceph/object/ceph_status_cluster_output.py
Normal file
51
keywords/ceph/object/ceph_status_cluster_output.py
Normal file
@@ -0,0 +1,51 @@
|
||||
from keywords.ceph.ceph_status_section_table_parser import CephStatusSectionTableParser
|
||||
from keywords.ceph.object.ceph_status_cluster_object import CephClusterObject
|
||||
|
||||
|
||||
class CephClusterOutput:
|
||||
"""
|
||||
This class parses the output of Ceph Cluster
|
||||
|
||||
Example:
|
||||
id: 8abb43ce-6775-4a1a-99c4-12f37101410e
|
||||
health: HEALTH_WARN
|
||||
2 MDSs report slow metadata IOs
|
||||
Reduced data availability: 48 pgs inactive
|
||||
Degraded data redundancy: 66/196 objects degraded (33.673%), 11 pgs degraded, 48 pgs undersized
|
||||
|
||||
OR
|
||||
|
||||
id: 8abb43ce-6775-4a1a-99c4-12f37101410e
|
||||
health: HEALTH_OK
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, ceph_cluster_output: list[str]):
|
||||
"""
|
||||
Constructor
|
||||
|
||||
Create an internal CephClusterObject.
|
||||
|
||||
Args:
|
||||
ceph_cluster_output (list[str]): a list of strings representing the cluster output
|
||||
|
||||
"""
|
||||
ceph_table_parser = CephStatusSectionTableParser(ceph_cluster_output)
|
||||
output_values = ceph_table_parser.get_output_values_dict()
|
||||
self.ceph_cluster_object = CephClusterObject()
|
||||
|
||||
if "id" in output_values:
|
||||
self.ceph_cluster_object.id = output_values["id"]
|
||||
|
||||
if "health" in output_values:
|
||||
self.ceph_cluster_object.health = output_values["health"]
|
||||
|
||||
def get_ceph_cluster_object(self) -> CephClusterObject:
|
||||
"""
|
||||
Getter for CephClusterObject object.
|
||||
|
||||
Returns (CephClusterObject):
|
||||
A CephClusterObject
|
||||
|
||||
"""
|
||||
return self.ceph_cluster_object
|
56
keywords/ceph/object/ceph_status_data_object.py
Normal file
56
keywords/ceph/object/ceph_status_data_object.py
Normal file
@@ -0,0 +1,56 @@
|
||||
class CephDataObject:
|
||||
"""
|
||||
Object to hold the values of Ceph Data Object
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.volumes: str = ""
|
||||
self.pools: str = ""
|
||||
self.objects: str = ""
|
||||
self.usage: str = ""
|
||||
self.pgs: str = ""
|
||||
|
||||
def get_volumes(self) -> str:
|
||||
"""
|
||||
Getter for volumes
|
||||
|
||||
Returns: volumes
|
||||
|
||||
"""
|
||||
return self.volumes
|
||||
|
||||
def get_pools(self) -> str:
|
||||
"""
|
||||
Getter for pools
|
||||
|
||||
Returns: pools
|
||||
|
||||
"""
|
||||
return self.pools
|
||||
|
||||
def get_objects(self) -> str:
|
||||
"""
|
||||
Getter for objects
|
||||
|
||||
Returns: objects
|
||||
|
||||
"""
|
||||
return self.objects
|
||||
|
||||
def get_usage(self) -> str:
|
||||
"""
|
||||
Getter for usage
|
||||
|
||||
Returns: usage
|
||||
|
||||
"""
|
||||
return self.usage
|
||||
|
||||
def get_pgs(self) -> str:
|
||||
"""
|
||||
Getter for pgs
|
||||
|
||||
Returns: pgs
|
||||
|
||||
"""
|
||||
return self.pgs
|
56
keywords/ceph/object/ceph_status_data_output.py
Normal file
56
keywords/ceph/object/ceph_status_data_output.py
Normal file
@@ -0,0 +1,56 @@
|
||||
from keywords.ceph.ceph_status_section_table_parser import CephStatusSectionTableParser
|
||||
from keywords.ceph.object.ceph_status_data_object import CephDataObject
|
||||
|
||||
|
||||
class CephDataOutput:
|
||||
"""
|
||||
This class parses the output of Ceph Data
|
||||
|
||||
Example:
|
||||
data:
|
||||
volumes: 1/1 healthy
|
||||
pools: 4 pools, 112 pgs
|
||||
objects: 26 objects, 6.6 MiB
|
||||
usage: 400 MiB used, 2.2 TiB / 2.2 TiB avail
|
||||
pgs: 112 active+clean
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, ceph_data_output: list[str]):
|
||||
"""
|
||||
Constructor.
|
||||
|
||||
Create an internal DataObject.
|
||||
|
||||
Args:
|
||||
ceph_data_output (list[str]): a list of strings representing the data output
|
||||
|
||||
"""
|
||||
ceph_table_parser = CephStatusSectionTableParser(ceph_data_output)
|
||||
output_values = ceph_table_parser.get_output_values_dict()
|
||||
self.ceph_data_object = CephDataObject()
|
||||
|
||||
if "volumes" in output_values:
|
||||
self.ceph_data_object.volumes = output_values["volumes"]
|
||||
|
||||
if "pools" in output_values:
|
||||
self.ceph_data_object.pools = output_values["pools"]
|
||||
|
||||
if "objects" in output_values:
|
||||
self.ceph_data_object.objects = output_values["objects"]
|
||||
|
||||
if "usage" in output_values:
|
||||
self.ceph_data_object.usage = output_values["usage"]
|
||||
|
||||
if "pgs" in output_values:
|
||||
self.ceph_data_object.pgs = output_values["pgs"]
|
||||
|
||||
def get_ceph_data_object(self) -> CephDataObject:
|
||||
"""
|
||||
Getter for CephDataObject object.
|
||||
|
||||
Returns (CephDataObject):
|
||||
A CephDataObject
|
||||
|
||||
"""
|
||||
return self.ceph_data_object
|
16
keywords/ceph/object/ceph_status_io_object.py
Normal file
16
keywords/ceph/object/ceph_status_io_object.py
Normal file
@@ -0,0 +1,16 @@
|
||||
class CephIOObject:
|
||||
"""
|
||||
Object to hold the values of Ceph IO Object
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.client: str = ""
|
||||
|
||||
def get_client(self) -> str:
|
||||
"""
|
||||
Getter for client
|
||||
|
||||
Returns: client
|
||||
|
||||
"""
|
||||
return self.client
|
40
keywords/ceph/object/ceph_status_io_output.py
Normal file
40
keywords/ceph/object/ceph_status_io_output.py
Normal file
@@ -0,0 +1,40 @@
|
||||
from keywords.ceph.ceph_status_section_table_parser import CephStatusSectionTableParser
|
||||
from keywords.ceph.object.ceph_status_io_object import CephIOObject
|
||||
|
||||
|
||||
class CephIOOutput:
|
||||
"""
|
||||
This class parses the output of Ceph IO
|
||||
|
||||
Example:
|
||||
io:
|
||||
client: 853 B/s rd, 1 op/s rd, 0 op/s wr
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, ceph_io_output: list[str]):
|
||||
"""
|
||||
Constructor.
|
||||
|
||||
Create an internal CephIOObject.
|
||||
|
||||
Args:
|
||||
ceph_io_output (list[str]): a list of strings representing the io output
|
||||
|
||||
"""
|
||||
ceph_table_parser = CephStatusSectionTableParser(ceph_io_output)
|
||||
output_values = ceph_table_parser.get_output_values_dict()
|
||||
self.ceph_io_object = CephIOObject()
|
||||
|
||||
if "client" in output_values:
|
||||
self.ceph_io_object.client = output_values["client"]
|
||||
|
||||
def get_ceph_io_object(self) -> CephIOObject:
|
||||
"""
|
||||
Getter for CephIOObject object.
|
||||
|
||||
Returns (CephIOObject):
|
||||
A CephIOObject
|
||||
|
||||
"""
|
||||
return self.ceph_io_object
|
186
keywords/ceph/object/ceph_status_output.py
Normal file
186
keywords/ceph/object/ceph_status_output.py
Normal file
@@ -0,0 +1,186 @@
|
||||
import re
|
||||
|
||||
from keywords.ceph.object.ceph_status_cluster_output import CephClusterOutput
|
||||
from keywords.ceph.object.ceph_status_data_output import CephDataOutput
|
||||
from keywords.ceph.object.ceph_status_io_output import CephIOOutput
|
||||
from keywords.ceph.object.ceph_status_services_output import CephServicesOutput
|
||||
|
||||
|
||||
class CephStatusOutput:
|
||||
"""
|
||||
This class parses the output of command ceph -s
|
||||
|
||||
Example:
|
||||
cluster:
|
||||
id: 8abb43ce-6775-4a1a-99c4-12f37101410e
|
||||
health: HEALTH_OK
|
||||
|
||||
services:
|
||||
mon: 3 daemons, quorum a,b,c (age 3w)
|
||||
mgr: b(active, since 24h), standbys: c, a
|
||||
mds: 1/1 daemons up, 1 hot standby
|
||||
osd: 5 osds: 5 up (since 2w), 5 in (since 2w)
|
||||
|
||||
data:
|
||||
volumes: 1/1 healthy
|
||||
pools: 4 pools, 112 pgs
|
||||
objects: 26 objects, 6.6 MiB
|
||||
usage: 401 MiB used, 2.2 TiB / 2.2 TiB avail
|
||||
pgs: 112 active+clean
|
||||
|
||||
io:
|
||||
client: 1.2 KiB/s rd, 2 op/s rd, 0 op/s wr
|
||||
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, ceph_s_output: list[str]):
|
||||
"""
|
||||
Create a list of ceph objects for the given output
|
||||
|
||||
Args:
|
||||
ceph_s_output (list[str]): a list of strings representing the output of the ceph -s command
|
||||
|
||||
"""
|
||||
self.ceph_cluster_output: CephClusterOutput = None
|
||||
self.ceph_services_output: CephServicesOutput = None
|
||||
self.ceph_data_output: CephDataOutput = None
|
||||
self.ceph_io_output: CephIOOutput = None
|
||||
|
||||
section_name_list = ["cluster:", "services:", "data:", "io:"]
|
||||
section_object = ""
|
||||
body_str = []
|
||||
for line in ceph_s_output:
|
||||
# remove front extra space of a line
|
||||
line = line.lstrip()
|
||||
# skip empty lines
|
||||
if line.strip() == "":
|
||||
continue
|
||||
# get section name
|
||||
elif any(section in line for section in section_name_list):
|
||||
# We have completed a section content, now create it.
|
||||
if section_object:
|
||||
self.create_section_object(section_object, body_str)
|
||||
# We are starting a new section.
|
||||
# remove : and \n
|
||||
section_object = line.replace(":", "").replace("\n", "")
|
||||
body_str = []
|
||||
else:
|
||||
# This line is part of the current section
|
||||
# remove end '\n'
|
||||
line = line.rstrip("\n")
|
||||
body_str.append(line)
|
||||
|
||||
# Create the last section
|
||||
self.create_section_object(section_object, body_str)
|
||||
|
||||
def create_section_object(self, section_object: str, body_str: list[str]):
|
||||
"""
|
||||
Creates the ceph section object
|
||||
|
||||
Args:
|
||||
section_object (str): the object to be created
|
||||
body_str (list[str]): the body of the section
|
||||
|
||||
"""
|
||||
if "cluster" in section_object:
|
||||
self.ceph_cluster_output = CephClusterOutput(body_str)
|
||||
|
||||
if "services" in section_object:
|
||||
self.ceph_services_output = CephServicesOutput(body_str)
|
||||
|
||||
if "data" in section_object:
|
||||
self.ceph_data_output = CephDataOutput(body_str)
|
||||
|
||||
if "io" in section_object:
|
||||
self.ceph_io_output = CephIOOutput(body_str)
|
||||
|
||||
def get_ceph_cluster_output(self) -> CephClusterOutput:
|
||||
"""
|
||||
Getter for the ceph cluster output
|
||||
|
||||
Returns:
|
||||
CephClusterOutput: a CephClusterOutput object
|
||||
|
||||
"""
|
||||
return self.ceph_cluster_output
|
||||
|
||||
def get_ceph_services_output(self) -> CephServicesOutput:
|
||||
"""
|
||||
Getter for the services output
|
||||
|
||||
Returns:
|
||||
CephServicesOutput: a CephServicesOutput object
|
||||
|
||||
"""
|
||||
return self.ceph_services_output
|
||||
|
||||
def get_ceph_data_output(self) -> CephDataOutput:
|
||||
"""
|
||||
Getter for the data output
|
||||
|
||||
Returns:
|
||||
CephDataOutput: a CephDataOutput object
|
||||
|
||||
"""
|
||||
return self.ceph_data_output
|
||||
|
||||
def get_ceph_io_output(self) -> CephIOOutput:
|
||||
"""
|
||||
Getter for the io output
|
||||
|
||||
Returns:
|
||||
CephIOOutput: a CephIOOutput object
|
||||
|
||||
"""
|
||||
return self.ceph_io_output
|
||||
|
||||
def is_ceph_healthy(self) -> bool:
|
||||
"""
|
||||
Check whether ceph is healthy
|
||||
|
||||
Args: None
|
||||
|
||||
Returns:
|
||||
bool:
|
||||
If ceph health is ok, return True
|
||||
If ceph health is not ok, return False
|
||||
|
||||
"""
|
||||
ceph_health_status_msg = self.ceph_cluster_output.get_ceph_cluster_object().get_health()
|
||||
if "HEALTH_OK" in ceph_health_status_msg:
|
||||
return True
|
||||
elif "HEALTH_WARN" in ceph_health_status_msg:
|
||||
return False
|
||||
else:
|
||||
raise ValueError("Ceph health status msg should content either HEALTH_OK or HEALTH_WARN")
|
||||
|
||||
def get_ceph_osd_count(self) -> int:
|
||||
"""
|
||||
Get osd number
|
||||
|
||||
Args: None
|
||||
|
||||
Returns (int):
|
||||
osd_number
|
||||
|
||||
"""
|
||||
osd_msg = self.ceph_services_output.get_ceph_services_object().get_osd()
|
||||
match = re.search(r"\d+", osd_msg)
|
||||
osd_number = int(match.group())
|
||||
return osd_number
|
||||
|
||||
def get_ceph_mon_count(self) -> int:
|
||||
"""
|
||||
Get mons number
|
||||
|
||||
Args: None
|
||||
|
||||
Returns (int):
|
||||
mons_number
|
||||
|
||||
"""
|
||||
mons_msg = self.ceph_services_output.get_ceph_services_object().get_mon()
|
||||
match = re.search(r"\d+", mons_msg)
|
||||
mons_number = int(match.group())
|
||||
return mons_number
|
46
keywords/ceph/object/ceph_status_services_object.py
Normal file
46
keywords/ceph/object/ceph_status_services_object.py
Normal file
@@ -0,0 +1,46 @@
|
||||
class CephServicesObject:
|
||||
"""
|
||||
Object to hold the values of Ceph Services Object
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.mon: str = ""
|
||||
self.mgr: str = ""
|
||||
self.mds: str = ""
|
||||
self.osd: str = ""
|
||||
|
||||
def get_mon(self) -> str:
|
||||
"""
|
||||
Getter for mon
|
||||
|
||||
Returns: mon
|
||||
|
||||
"""
|
||||
return self.mon
|
||||
|
||||
def get_mgr(self) -> str:
|
||||
"""
|
||||
Getter for mgr
|
||||
|
||||
Returns: mgr
|
||||
|
||||
"""
|
||||
return self.mgr
|
||||
|
||||
def get_mds(self) -> str:
|
||||
"""
|
||||
Getter for mds
|
||||
|
||||
Returns: mds
|
||||
|
||||
"""
|
||||
return self.mds
|
||||
|
||||
def get_osd(self) -> str:
|
||||
"""
|
||||
Getter for osd
|
||||
|
||||
Returns: osd
|
||||
|
||||
"""
|
||||
return self.osd
|
52
keywords/ceph/object/ceph_status_services_output.py
Normal file
52
keywords/ceph/object/ceph_status_services_output.py
Normal file
@@ -0,0 +1,52 @@
|
||||
from keywords.ceph.ceph_status_section_table_parser import CephStatusSectionTableParser
|
||||
from keywords.ceph.object.ceph_status_services_object import CephServicesObject
|
||||
|
||||
|
||||
class CephServicesOutput:
|
||||
"""
|
||||
This class parses the output of Services
|
||||
|
||||
Example:
|
||||
services:
|
||||
mon: 3 daemons, quorum a,b,c (age 3w)
|
||||
mgr: b(active, since 19h), standbys: c, a
|
||||
mds: 1/1 daemons up, 1 hot standby
|
||||
osd: 5 osds: 5 up (since 2w), 5 in (since 2w)
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, ceph_services_output: list[str]):
|
||||
"""
|
||||
Constructor.
|
||||
|
||||
Create an internal CephServicesObject.
|
||||
|
||||
Args:
|
||||
ceph_services_output (list[str]): a list of strings representing the services output
|
||||
|
||||
"""
|
||||
ceph_table_parser = CephStatusSectionTableParser(ceph_services_output)
|
||||
output_values = ceph_table_parser.get_output_values_dict()
|
||||
self.ceph_services_object = CephServicesObject()
|
||||
|
||||
if "mon" in output_values:
|
||||
self.ceph_services_object.mon = output_values["mon"]
|
||||
|
||||
if "mgr" in output_values:
|
||||
self.ceph_services_object.mgr = output_values["mgr"]
|
||||
|
||||
if "mds" in output_values:
|
||||
self.ceph_services_object.mds = output_values["mds"]
|
||||
|
||||
if "osd" in output_values:
|
||||
self.ceph_services_object.osd = output_values["osd"]
|
||||
|
||||
def get_ceph_services_object(self) -> CephServicesObject:
|
||||
"""
|
||||
Getter for CephServicesObject object.
|
||||
|
||||
Returns (CephServicesObject):
|
||||
A CephServicesObject
|
||||
|
||||
"""
|
||||
return self.ceph_services_object
|
84
unit_tests/parser/ceph/ceph_status_table_parser_test.py
Normal file
84
unit_tests/parser/ceph/ceph_status_table_parser_test.py
Normal file
@@ -0,0 +1,84 @@
|
||||
from keywords.ceph.object.ceph_status_output import CephStatusOutput
|
||||
|
||||
# fmt: off
|
||||
ceph_s_health_warning = [
|
||||
" cluster:\n",
|
||||
" id: 001ab3d8-1f02-4294-b594-e2b216b9b2dc\n",
|
||||
" health: HEALTH_WARN\n",
|
||||
" 2 MDSs report slow metadata IOs\n",
|
||||
" Reduced data availability: 48 pgs inactive\n",
|
||||
" Degraded data redundancy: 66/196 objects degraded (33.673%), 11 pgs degraded, 48 pgs undersized\n",
|
||||
" \n",
|
||||
" services:\n",
|
||||
" mon: 2 daemons, quorum a,b,c (age 4w)\n",
|
||||
" mgr: b(active, since 9d), standbys: c, a\n",
|
||||
" mds: 1/1 daemons up, 1 hot standby\n",
|
||||
" osd: 3 osds: 3 up (since 3w), 3 in (since 3w)\n",
|
||||
" \n",
|
||||
" data:\n",
|
||||
" volumes: 1/1 healthy\n",
|
||||
" pools: 4 pools, 112 pgs\n",
|
||||
" objects: 27 objects, 9.1 MiB\n",
|
||||
" usage: 425 MiB used, 2.2 TiB / 2.2 TiB avail\n",
|
||||
" pgs: 112 active+clean\n",
|
||||
" \n",
|
||||
" io:\n",
|
||||
" client: 1.2 KiB/s rd, 2 op/s rd, 0 op/s wr\n",
|
||||
" \n"
|
||||
]
|
||||
|
||||
# fmt: off
|
||||
ceph_s_health_ok = [
|
||||
" cluster:\n",
|
||||
" id: 8abb43ce-6775-4a1a-99c4-12f37101410e\n",
|
||||
" health: HEALTH_OK\n",
|
||||
" \n",
|
||||
" services:\n",
|
||||
" mon: 3 daemons, quorum a,b,c (age 4w)\n",
|
||||
" mgr: b(active, since 9d), standbys: c, a\n",
|
||||
" mds: 1/1 daemons up, 1 hot standby\n",
|
||||
" osd: 5 osds: 5 up (since 3w), 5 in (since 3w)\n",
|
||||
" \n",
|
||||
" data:\n",
|
||||
" volumes: 1/1 healthy\n",
|
||||
" pools: 4 pools, 112 pgs\n",
|
||||
" objects: 27 objects, 9.1 MiB\n",
|
||||
" usage: 425 MiB used, 2.2 TiB / 2.2 TiB avail\n",
|
||||
" pgs: 112 active+clean\n",
|
||||
" \n",
|
||||
" io:\n",
|
||||
" client: 1.2 KiB/s rd, 2 op/s rd, 0 op/s wr\n",
|
||||
" \n"
|
||||
]
|
||||
|
||||
|
||||
def test_ceph_status_output():
|
||||
"""
|
||||
Tests ceph_status_output functions
|
||||
|
||||
include:
|
||||
is_ceph_healthy()
|
||||
get_ceph_osd_count()
|
||||
get_ceph_mon_count()
|
||||
|
||||
"""
|
||||
ceph_s_health_ok_output = CephStatusOutput(ceph_s_health_ok)
|
||||
cluster_object = ceph_s_health_ok_output.get_ceph_cluster_output().get_ceph_cluster_object()
|
||||
assert cluster_object.get_id() == "8abb43ce-6775-4a1a-99c4-12f37101410e"
|
||||
assert cluster_object.get_health() == "HEALTH_OK"
|
||||
assert ceph_s_health_ok_output.get_ceph_osd_count() == 5
|
||||
assert ceph_s_health_ok_output.get_ceph_mon_count() == 3
|
||||
|
||||
ceph_s_health_status = ceph_s_health_ok_output.is_ceph_healthy()
|
||||
if not ceph_s_health_status:
|
||||
raise ValueError("Error output")
|
||||
|
||||
ceph_s_health_warn_output = CephStatusOutput(ceph_s_health_warning)
|
||||
cluster_object = ceph_s_health_warn_output.get_ceph_cluster_output().get_ceph_cluster_object()
|
||||
assert cluster_object.get_id() == "001ab3d8-1f02-4294-b594-e2b216b9b2dc"
|
||||
assert cluster_object.get_health() == "HEALTH_WARN; 2 MDSs report slow metadata IOs; Reduced data availability: 48 pgs inactive; Degraded data redundancy: 66/196 objects degraded (33.673%), 11 pgs degraded, 48 pgs undersized"
|
||||
assert ceph_s_health_warn_output.get_ceph_osd_count() == 3
|
||||
assert ceph_s_health_warn_output.get_ceph_mon_count() == 2
|
||||
ceph_s_health_status = ceph_s_health_warn_output.is_ceph_healthy()
|
||||
if ceph_s_health_status:
|
||||
raise ValueError("Error output")
|
Reference in New Issue
Block a user