summaryrefslogtreecommitdiffstats
path: root/src/mgr/ServiceMap.h
blob: c0cd65c8b7e86e9eaabe383700a6a2d5fb22b721 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab

#pragma once

#include <string>
#include <map>
#include <list>
#include <sstream>

#include "include/utime.h"
#include "include/buffer.h"
#include "msg/msg_types.h"

namespace ceph {
  class Formatter;
}

struct ServiceMap {
  struct Daemon {
    uint64_t gid = 0;
    entity_addr_t addr;
    epoch_t start_epoch = 0;   ///< epoch first registered
    utime_t start_stamp;       ///< timestamp daemon started/registered
    std::map<std::string,std::string> metadata;  ///< static metadata
    std::map<std::string,std::string> task_status; ///< running task status

    void encode(bufferlist& bl, uint64_t features) const;
    void decode(bufferlist::const_iterator& p);
    void dump(Formatter *f) const;
    static void generate_test_instances(std::list<Daemon*>& ls);
  };

  struct Service {
    map<std::string,Daemon> daemons;
    std::string summary;   ///< summary status string for 'ceph -s'

    void encode(bufferlist& bl, uint64_t features) const;
    void decode(bufferlist::const_iterator& p);
    void dump(Formatter *f) const;
    static void generate_test_instances(std::list<Service*>& ls);

    std::string get_summary() const {
      if (summary.size()) {
	return summary;
      }
      if (daemons.empty()) {
	return "no daemons active";
      }
      std::ostringstream ss;
      ss << daemons.size() << (daemons.size() > 1 ? " daemons" : " daemon")
	 << " active";

      if (!daemons.empty()) {
	ss << " (";
	for (auto p = daemons.begin(); p != daemons.end(); ++p) {
	  if (p != daemons.begin()) {
	    ss << ", ";
	  }
	  ss << p->first;
	}
	ss << ")";
      }

      return ss.str();
    }

    std::string get_task_summary(const std::string_view task_prefix) const {
      // contruct a map similar to:
      //     {"service1 status" -> {"service1.0" -> "running"}}
      //     {"service2 status" -> {"service2.0" -> "idle"},
      //                           {"service2.1" -> "running"}}
      std::map<std::string, std::map<std::string, std::string>> by_task;
      for (const auto &p : daemons) {
        std::stringstream d;
        d << task_prefix << "." << p.first;
        for (const auto &q : p.second.task_status) {
          auto p1 = by_task.emplace(q.first, std::map<std::string, std::string>{}).first;
          auto p2 = p1->second.emplace(d.str(), std::string()).first;
          p2->second = q.second;
        }
      }

      std::stringstream ss;
      for (const auto &p : by_task) {
        ss << "\n    " << p.first << ":";
        for (auto q : p.second) {
          ss << "\n        " << q.first << ": " << q.second;
        }
      }

      return ss.str();
    }

    void count_metadata(const std::string& field,
			std::map<std::string,int> *out) const {
      for (auto& p : daemons) {
	auto q = p.second.metadata.find(field);
	if (q == p.second.metadata.end()) {
	  (*out)["unknown"]++;
	} else {
	  (*out)[q->second]++;
	}
      }
    }

  };

  epoch_t epoch = 0;
  utime_t modified;
  map<std::string,Service> services;

  void encode(bufferlist& bl, uint64_t features) const;
  void decode(bufferlist::const_iterator& p);
  void dump(Formatter *f) const;
  static void generate_test_instances(std::list<ServiceMap*>& ls);

  std::pair<Daemon*,bool> get_daemon(const std::string& service,
				     const std::string& daemon) {
    auto& s = services[service];
    auto [d, added] = s.daemons.try_emplace(daemon);
    return {&d->second, added};
  }

  bool rm_daemon(const std::string& service,
		 const std::string& daemon) {
    auto p = services.find(service);
    if (p == services.end()) {
      return false;
    }
    auto q = p->second.daemons.find(daemon);
    if (q == p->second.daemons.end()) {
      return false;
    }
    p->second.daemons.erase(q);
    if (p->second.daemons.empty()) {
      services.erase(p);
    }
    return true;
  }

  static inline bool is_normal_ceph_entity(std::string_view type) {
    if (type == "osd" ||
        type == "client" ||
        type == "mon" ||
        type == "mds" ||
        type == "mgr") {
      return true;
    }

    return false;
  }
};
WRITE_CLASS_ENCODER_FEATURES(ServiceMap)
WRITE_CLASS_ENCODER_FEATURES(ServiceMap::Service)
WRITE_CLASS_ENCODER_FEATURES(ServiceMap::Daemon)