From 6a71648d7e300191e21edbac56bc657fcdc9b7a7 Mon Sep 17 00:00:00 2001 From: Owen Synge Date: Mon, 5 Sep 2016 17:03:56 +0200 Subject: [PATCH 1/5] ceph_cfg.model:Add 'ceph osd df' output We need a place for storing the output of 'ceph osd df' Signed-off-by: Owen Synge --- ceph_cfg/model.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ceph_cfg/model.py b/ceph_cfg/model.py index f8ab6e8..1dc8ad2 100644 --- a/ceph_cfg/model.py +++ b/ceph_cfg/model.py @@ -58,6 +58,8 @@ def __init__(self, **kwargs): self.mon_status = None # Remote connection details self.connection = connection() + # Stores safe version of 'ceph osd df' + self.cluster_df = None def kargs_apply(self, **kwargs): From 69fd2701d3739dc97aaf9c4bef6face3d3efc60d Mon Sep 17 00:00:00 2001 From: Owen Synge Date: Mon, 5 Sep 2016 17:05:04 +0200 Subject: [PATCH 2/5] ceph_cfg.presenter:Output 'ceph osd df' User output of 'ceph osd df' Signed-off-by: Owen Synge --- ceph_cfg/presenter.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/ceph_cfg/presenter.py b/ceph_cfg/presenter.py index f0bb1a0..1cd17c2 100644 --- a/ceph_cfg/presenter.py +++ b/ceph_cfg/presenter.py @@ -3,6 +3,16 @@ log = logging.getLogger(__name__) +class Error(Exception): + """ + Error + """ + + def __str__(self): + doc = self.__doc__.strip() + return ': '.join([doc] + [str(a) for a in self.args]) + + class mdl_presentor(): """ Since presentation should be clean to the end user @@ -349,3 +359,21 @@ def ceph_version(self): def cephfs_list(self): return self.model.cephfs_list + + + def df_osd(self, osd_number): + if self.model.cluster_df is None: + msg = "Programming error : self.model.cluster_df is None" + log.error(msg) + raise(msg) + osd_details = self.model.cluster_df.get("osd") + if osd_details is None: + msg = "Programming error : self.model.cluster_df[osd] is None" + log.error(msg) + raise(msg) + details = osd_details.get(osd_number) + if details is None: + msg = "Osd '{number}' not found".format(number=osd_number) + log.error(msg) + raise(msg) + return details From 4b7b68eba7718a85583c3cc80a80d967ca050235 Mon Sep 17 00:00:00 2001 From: Owen Synge Date: Mon, 5 Sep 2016 17:06:26 +0200 Subject: [PATCH 3/5] ceph_cfg.ops_cluster:Get 'ceph osd df' and place in model Present sanitised output of 'ceph osd df' to model Signed-off-by: Owen Synge --- ceph_cfg/ops_cluster.py | 70 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/ceph_cfg/ops_cluster.py b/ceph_cfg/ops_cluster.py index d11c2ba..30a6c86 100644 --- a/ceph_cfg/ops_cluster.py +++ b/ceph_cfg/ops_cluster.py @@ -58,3 +58,73 @@ def status_refresh(self): output["stderr"]) ) self.model.cluster_status = json.loads(output["stdout"].strip()) + + + def _df_node_to_osd_dict(self, node): + node_type = node.get("type") + if node_type != "osd": + return None + osd_id = node.get("id") + osd_name = node.get("name") + osd_weight_crush = node.get("crush_weight") + osd_weight = node.get("reweight") + osd_kb_total = node.get("kb") + osd_kb_used = node.get("kb_used") + osd_kb_avail = node.get("kb_avail") + osd_pgs = node.get("pgs") + osd_utilization = node.get("utilization") + return { + "id" : osd_id, + "name" : osd_name, + "weight_crush" : osd_weight_crush, + "weight" : osd_weight, + "kb_total" : osd_kb_total, + "kb_used" : osd_kb_used, + "kb_avail" : osd_kb_avail, + "pgs" : osd_pgs, + "utilization" : osd_utilization + } + + + def df(self): + prefix_arguments = [ + util_which.which_ceph.path + ] + postfix_arguments = [ + 'osd', + 'df', + '-f', + 'json' + ] + connection_arguments = self.connection.arguments_get() + arguments = prefix_arguments + connection_arguments + postfix_arguments + output = utils.execute_local_command(arguments) + if output["retcode"] != 0: + raise Error("Failed executing '%s' Error rc=%s, stdout=%s stderr=%s" % ( + " ".join(arguments), + output["retcode"], + output["stdout"], + output["stderr"]) + ) + df_dict = json.loads(output["stdout"]) + nodes_list = df_dict.get("nodes") + osd_details = {} + if not nodes_list is None: + for node in nodes_list: + osd_dict = self._df_node_to_osd_dict(node) + if not osd_dict is None: + osd_details[osd_dict.get("id")] = osd_dict + + summary_raw = df_dict.get("summary") + summary_model = {} + if not summary_raw is None: + summary_model["kb_total"] = summary_raw.get("total_kb") + summary_model["kb_used"] = summary_raw.get("kb_used") + summary_model["kb_avail"] = summary_raw.get("total_kb_avail") + summary_model["utilization_average"] = summary_raw.get("average_utilization") + stored_model = { + 'osd' : osd_details, + 'summary' : summary_model + } + self.model.cluster_df = stored_model + return self.model.cluster_df From a1b66e528d30886b5f7421d7198a3319df25e591 Mon Sep 17 00:00:00 2001 From: Owen Synge Date: Mon, 5 Sep 2016 17:08:10 +0200 Subject: [PATCH 4/5] ceph_cfg.init: Provide osd_df method Present sanitised output of 'ceph osd df' to user Signed-off-by: Owen Synge --- ceph_cfg/__init__.py | 70 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/ceph_cfg/__init__.py b/ceph_cfg/__init__.py index 63c087c..f55d93d 100644 --- a/ceph_cfg/__init__.py +++ b/ceph_cfg/__init__.py @@ -25,6 +25,13 @@ from . import keyring_use from . import ops_osd + +try: # check whether python knows about 'basestring' + basestring +except NameError: # no, it doesn't (it's Python3); use 'str' instead + basestring=str + + log = logging.getLogger(__name__) @@ -231,6 +238,43 @@ def osd_reweight(**kwargs): return ops_osd.reweight(**kwargs) +def osd_df(**kwargs): + """ + OSD disk space + + Args: + **kwargs: Arbitrary keyword arguments. + cluster_name : Set the cluster name. Defaults to "ceph". + cluster_uuid : Set the cluster date will be added too. Defaults to + the value found in local config. + osd_number : OSD number to query. + """ + osd_number_input = kwargs.get("osd_number") + if osd_number_input is None: + raise Error("osd_number is not specified") + osd_number_as_int = None + if isinstance(osd_number_input, int): + osd_number_as_int = osd_number_input + if isinstance(osd_number_input, basestring): + osd_number_as_int = int(osd_number_input.strip()) + if osd_number_as_int is None: + raise Error("osd_number could not be converted to int") + mdl = model.model(**kwargs) + u = mdl_updater.model_updater(mdl) + u.symlinks_refresh() + u.defaults_refresh() + u.partitions_all_refresh() + u.discover_partitions_refresh() + u.defaults_refresh() + u.load_confg(mdl.cluster_name) + u.mon_members_refresh() + # Validate input + cluster_ops = ops_cluster.ops_cluster(mdl) + cluster_ops.df() + p = presenter.mdl_presentor(mdl) + return p.df_osd(osd_number_as_int) + + def keyring_create(**kwargs): """ Create keyring for cluster @@ -1042,6 +1086,32 @@ def cephfs_ls(**kwargs): return p.cephfs_list() +def cluster_df(**kwargs): + """ + Cluster disk space + + Args: + **kwargs: Arbitrary keyword arguments. + cluster_name : Set the cluster name. Defaults to "ceph". + cluster_uuid : Set the cluster date will be added too. Defaults to + the value found in local config. + """ + mdl = model.model(**kwargs) + u = mdl_updater.model_updater(mdl) + u.symlinks_refresh() + u.defaults_refresh() + u.partitions_all_refresh() + u.discover_partitions_refresh() + u.defaults_refresh() + u.load_confg(mdl.cluster_name) + u.mon_members_refresh() + # Validate input + cluster_ops = ops_cluster.ops_cluster(mdl) + cluster_ops.df() + p = presenter.mdl_presentor(mdl) + return p.df() + + def cephfs_add(fs_name, **kwargs): """ Make new cephfs file system From a8b1f0cf63906e11afa7e8b76bff961470c5f06a Mon Sep 17 00:00:00 2001 From: Owen Synge Date: Mon, 5 Sep 2016 18:03:46 +0200 Subject: [PATCH 5/5] ceph_cfg.presenter: Provide df method Present sanitised output of 'ceph osd df' to user Signed-off-by: Owen Synge --- ceph_cfg/presenter.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/ceph_cfg/presenter.py b/ceph_cfg/presenter.py index 1cd17c2..98f1440 100644 --- a/ceph_cfg/presenter.py +++ b/ceph_cfg/presenter.py @@ -377,3 +377,11 @@ def df_osd(self, osd_number): log.error(msg) raise(msg) return details + + + def df(self): + if self.model.cluster_df is None: + msg = "Programming error : self.model.cluster_df is None" + log.error(msg) + raise(msg) + return self.model.cluster_df