Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / test / mon / PGMap.cc
1 // -*- mode:C; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3 /*
4  * Ceph - scalable distributed file system
5  *
6  * Copyright (C) 2014 Inktank <info@inktank.com>
7  *
8  * This is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public
10  * License version 2, as published by the Free Software
11  * Foundation.  See file COPYING.
12  */
13
14 #include "mon/PGMap.h"
15 #include "gtest/gtest.h"
16
17 #include "include/stringify.h"
18
19 TEST(pgmap, min_last_epoch_clean)
20 {
21   PGMap pg_map;
22   PGMap::Incremental inc;
23   osd_stat_t os;
24   pg_stat_t ps;
25
26   ps.last_epoch_clean = 999;
27   inc.pg_stat_updates[pg_t(9,9)] = ps;
28   inc.version = 1;
29   inc.update_stat(0, 123, os);
30   pg_map.apply_incremental(g_ceph_context, inc);
31   ASSERT_EQ(123u, pg_map.get_min_last_epoch_clean());
32
33   inc = PGMap::Incremental();
34   inc.version = 2;
35   inc.update_stat(1, 222, os);
36   pg_map.apply_incremental(g_ceph_context, inc);
37   ASSERT_EQ(123u, pg_map.get_min_last_epoch_clean());
38
39   inc = PGMap::Incremental();
40   inc.version = 3;
41   inc.update_stat(0, 222, os);
42   pg_map.apply_incremental(g_ceph_context, inc);
43   ASSERT_EQ(222u, pg_map.get_min_last_epoch_clean());
44
45   inc = PGMap::Incremental();
46   inc.version = 4;
47   inc.update_stat(0, 333, os);
48   inc.update_stat(1, 333, os);
49   pg_map.apply_incremental(g_ceph_context, inc);
50   ASSERT_EQ(333u, pg_map.get_min_last_epoch_clean());
51
52   ps.last_epoch_clean = 222;
53   inc = PGMap::Incremental();
54   inc.version = 5;
55   inc.pg_stat_updates[pg_t(1,1)] = ps;
56   pg_map.apply_incremental(g_ceph_context, inc);
57   ASSERT_EQ(222u, pg_map.get_min_last_epoch_clean());
58
59   ps.last_epoch_clean = 223;
60   inc = PGMap::Incremental();
61   inc.version = 6;
62   inc.pg_stat_updates[pg_t(1,1)] = ps;
63   pg_map.apply_incremental(g_ceph_context, inc);
64   ASSERT_EQ(223u, pg_map.get_min_last_epoch_clean());
65
66   ps.last_epoch_clean = 224;
67   inc = PGMap::Incremental();
68   inc.version = 7;
69   inc.pg_stat_updates[pg_t(2,2)] = ps;
70   pg_map.apply_incremental(g_ceph_context, inc);
71   ASSERT_EQ(223u, pg_map.get_min_last_epoch_clean());
72
73   ps.last_epoch_clean = 225;
74   inc = PGMap::Incremental();
75   inc.version = 8;
76   inc.pg_stat_updates[pg_t(1,1)] = ps;
77   pg_map.apply_incremental(g_ceph_context, inc);
78   ASSERT_EQ(224u, pg_map.get_min_last_epoch_clean());
79
80 }
81
82 TEST(pgmap, calc_stats)
83 {
84   bufferlist bl;
85   {
86     PGMap pg_map;
87     PGMap::Incremental inc;
88     osd_stat_t os;
89     pg_stat_t ps;
90
91     ps.last_epoch_clean = 999;
92     inc.pg_stat_updates[pg_t(9,9)] = ps;
93     inc.version = 1;
94     inc.update_stat(0, 123, os);
95     pg_map.apply_incremental(g_ceph_context, inc);
96     ASSERT_EQ(123u, pg_map.get_min_last_epoch_clean());
97     pg_map.encode(bl);
98   }
99   {
100     PGMap pg_map;
101     PGMap::Incremental inc;
102     osd_stat_t os;
103     pg_stat_t ps;
104
105     ps.last_epoch_clean = 999;
106     inc.pg_stat_updates[pg_t(9,9)] = ps;
107     inc.version = 1;
108     inc.update_stat(0, 321, os);
109     pg_map.apply_incremental(g_ceph_context, inc);
110     ASSERT_EQ(321u, pg_map.get_min_last_epoch_clean());
111     bufferlist::iterator p = bl.begin();
112     ::decode(pg_map, p);
113     ASSERT_EQ(123u, pg_map.get_min_last_epoch_clean());
114   }
115 }
116
117 namespace {
118   class CheckTextTable : public TextTable {
119   public:
120     CheckTextTable(bool verbose) {
121       for (int i = 0; i < 4; i++) {
122         define_column("", TextTable::LEFT, TextTable::LEFT);
123       }
124       if (verbose) {
125         for (int i = 0; i < 4; i++) {
126           define_column("", TextTable::LEFT, TextTable::LEFT);
127         }
128       }
129     }
130     const string& get(unsigned r, unsigned c) const {
131       assert(r < row.size());
132       assert(c < row[r].size());
133       return row[r][c];
134     }
135   };
136
137   // copied from PGMap.cc
138   string percentify(float a) {
139     stringstream ss;
140     if (a < 0.01)
141       ss << "0";
142     else
143       ss << std::fixed << std::setprecision(2) << a;
144     return ss.str();
145   }
146 }
147
148 // dump_object_stat_sum() is called by "ceph df" command
149 // with table, without formatter, verbose = true, not empty, avail > 0
150 TEST(pgmap, dump_object_stat_sum_0)
151 {
152   bool verbose = true;
153   CheckTextTable tbl(verbose);
154   object_stat_sum_t sum;
155   sum.num_bytes = 42 * 1024 * 1024;
156   sum.num_objects = 42;
157   sum.num_objects_degraded = 13; // there are 13 missings + not_yet_backfilled
158   sum.num_objects_dirty = 2;
159   sum.num_rd = 100;
160   sum.num_rd_kb = 123;
161   sum.num_wr = 101;
162   sum.num_wr_kb = 321;    
163
164   sum.calc_copies(3);           // assuming we have 3 copies for each obj
165   // nominal amount of space available for new objects in this pool
166   uint64_t avail = 2016 * 1024 * 1024;
167   pg_pool_t pool;
168   pool.quota_max_objects = 2000;
169   pool.quota_max_bytes = 2000 * 1024 * 1024;
170   pool.size = 2;
171   pool.type = pg_pool_t::TYPE_REPLICATED;
172   PGMap::dump_object_stat_sum(tbl, nullptr, sum, avail,
173                                   pool.get_size(), verbose, &pool);  
174   ASSERT_EQ(stringify(si_t(sum.num_bytes)), tbl.get(0, 0));
175   float copies_rate =
176     (static_cast<float>(sum.num_object_copies - sum.num_objects_degraded) /
177      sum.num_object_copies);
178   float used_bytes = sum.num_bytes * copies_rate * pool.get_size();
179   float used_percent = used_bytes / (used_bytes + avail) * 100;
180   unsigned col = 0;
181   ASSERT_EQ(stringify(si_t(sum.num_bytes)), tbl.get(0, col++));
182   ASSERT_EQ(percentify(used_percent), tbl.get(0, col++));
183   ASSERT_EQ(stringify(si_t(avail/pool.size)), tbl.get(0, col++));
184   ASSERT_EQ(stringify(sum.num_objects), tbl.get(0, col++));
185   ASSERT_EQ(stringify(si_t(sum.num_objects_dirty)), tbl.get(0, col++));
186   ASSERT_EQ(stringify(si_t(sum.num_rd)), tbl.get(0, col++));
187   ASSERT_EQ(stringify(si_t(sum.num_wr)), tbl.get(0, col++));
188   // we can use pool.size for raw_used_rate if it is a replica pool
189   uint64_t raw_bytes_used = sum.num_bytes * pool.get_size() * copies_rate;
190   ASSERT_EQ(stringify(si_t(raw_bytes_used)), tbl.get(0, col++));
191 }
192
193 // with table, without formatter, verbose = true, empty, avail > 0
194 TEST(pgmap, dump_object_stat_sum_1)
195 {
196   bool verbose = true;
197   CheckTextTable tbl(verbose);
198   object_stat_sum_t sum;        // zero by default
199   ASSERT_TRUE(sum.is_zero());
200   // nominal amount of space available for new objects in this pool
201   uint64_t avail = 2016 * 1024 * 1024;
202   pg_pool_t pool;
203   pool.quota_max_objects = 2000;
204   pool.quota_max_bytes = 2000 * 1024 * 1024;
205   pool.size = 2;
206   pool.type = pg_pool_t::TYPE_REPLICATED;
207   PGMap::dump_object_stat_sum(tbl, nullptr, sum, avail,
208                                   pool.get_size(), verbose, &pool);  
209   ASSERT_EQ(stringify(si_t(0)), tbl.get(0, 0));
210   unsigned col = 0;
211   ASSERT_EQ(stringify(si_t(0)), tbl.get(0, col++));
212   ASSERT_EQ(percentify(0), tbl.get(0, col++));
213   ASSERT_EQ(stringify(si_t(avail/pool.size)), tbl.get(0, col++));
214   ASSERT_EQ(stringify(0), tbl.get(0, col++));
215   ASSERT_EQ(stringify(si_t(0)), tbl.get(0, col++));
216   ASSERT_EQ(stringify(si_t(0)), tbl.get(0, col++));
217   ASSERT_EQ(stringify(si_t(0)), tbl.get(0, col++));
218   ASSERT_EQ(stringify(si_t(0)), tbl.get(0, col++));
219 }
220
221 // with table, without formatter, verbose = false, empty, avail = 0
222 TEST(pgmap, dump_object_stat_sum_2)
223 {
224   bool verbose = false;
225   CheckTextTable tbl(verbose);
226   object_stat_sum_t sum;        // zero by default
227   ASSERT_TRUE(sum.is_zero());
228   // nominal amount of space available for new objects in this pool
229   uint64_t avail = 0;
230   pg_pool_t pool;
231   pool.quota_max_objects = 2000;
232   pool.quota_max_bytes = 2000 * 1024 * 1024;
233   pool.size = 2;
234   pool.type = pg_pool_t::TYPE_REPLICATED;
235
236   PGMap::dump_object_stat_sum(tbl, nullptr, sum, avail,
237                                   pool.get_size(), verbose, &pool);  
238   ASSERT_EQ(stringify(si_t(0)), tbl.get(0, 0));
239   unsigned col = 0;
240   ASSERT_EQ(stringify(si_t(0)), tbl.get(0, col++));
241   ASSERT_EQ(percentify(0), tbl.get(0, col++));
242   ASSERT_EQ(stringify(si_t(avail/pool.size)), tbl.get(0, col++));
243   ASSERT_EQ(stringify(0), tbl.get(0, col++));
244 }