Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / librbd / api / Image.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3
4 #include "librbd/api/Image.h"
5 #include "include/rados/librados.hpp"
6 #include "common/dout.h"
7 #include "common/errno.h"
8 #include "cls/rbd/cls_rbd_client.h"
9 #include "librbd/ImageCtx.h"
10 #include "librbd/ImageState.h"
11
12 #define dout_subsys ceph_subsys_rbd
13 #undef dout_prefix
14 #define dout_prefix *_dout << "librbd::api::Image: " << __func__ << ": "
15
16 namespace librbd {
17 namespace api {
18
19 template <typename I>
20 int Image<I>::list_images(librados::IoCtx& io_ctx, ImageNameToIds *images) {
21   CephContext *cct = (CephContext *)io_ctx.cct();
22   ldout(cct, 20) << "io_ctx=" << &io_ctx << dendl;
23
24   // new format images are accessed by class methods
25   int r;
26   int max_read = 1024;
27   string last_read = "";
28   do {
29     map<string, string> images_page;
30     r = cls_client::dir_list(&io_ctx, RBD_DIRECTORY,
31                    last_read, max_read, &images_page);
32     if (r < 0 && r != -ENOENT) {
33       lderr(cct) << "error listing image in directory: "
34                  << cpp_strerror(r) << dendl;
35       return r;
36     } else if (r == -ENOENT) {
37       break;
38     }
39     for (map<string, string>::const_iterator it = images_page.begin();
40          it != images_page.end(); ++it) {
41       images->insert(*it);
42     }
43     if (!images_page.empty()) {
44       last_read = images_page.rbegin()->first;
45     }
46     r = images_page.size();
47   } while (r == max_read);
48
49   return 0;
50 }
51
52 template <typename I>
53 int Image<I>::list_children(I *ictx, const ParentSpec &parent_spec,
54                             PoolImageIds *pool_image_ids)
55 {
56   CephContext *cct = ictx->cct;
57   int r = ictx->state->refresh_if_required();
58   if (r < 0) {
59     return r;
60   }
61
62   // no children for non-layered or old format image
63   if (!ictx->test_features(RBD_FEATURE_LAYERING, ictx->snap_lock)) {
64     return 0;
65   }
66
67   pool_image_ids->clear();
68   // search all pools for children depending on this snapshot
69   librados::Rados rados(ictx->md_ctx);
70   std::list<std::pair<int64_t, std::string> > pools;
71   r = rados.pool_list2(pools);
72   if (r < 0) {
73     lderr(cct) << "error listing pools: " << cpp_strerror(r) << dendl;
74     return r;
75   }
76
77   for (auto it = pools.begin(); it != pools.end(); ++it) {
78     int64_t base_tier;
79     r = rados.pool_get_base_tier(it->first, &base_tier);
80     if (r == -ENOENT) {
81       ldout(cct, 1) << "pool " << it->second << " no longer exists" << dendl;
82       continue;
83     } else if (r < 0) {
84       lderr(cct) << "error retrieving base tier for pool " << it->second
85                  << dendl;
86       return r;
87     }
88     if (it->first != base_tier) {
89       // pool is a cache; skip it
90       continue;
91     }
92
93     IoCtx ioctx;
94     r = rados.ioctx_create2(it->first, ioctx);
95     if (r == -ENOENT) {
96       ldout(cct, 1) << "pool " << it->second << " no longer exists" << dendl;
97       continue;
98     } else if (r < 0) {
99       lderr(cct) << "error accessing child image pool " << it->second
100                  << dendl;
101       return r;
102     }
103
104     set<string> image_ids;
105     r = cls_client::get_children(&ioctx, RBD_CHILDREN, parent_spec,
106                                  image_ids);
107     if (r < 0 && r != -ENOENT) {
108       lderr(cct) << "error reading list of children from pool " << it->second
109            << dendl;
110       return r;
111     }
112     pool_image_ids->insert({*it, image_ids});
113   }
114
115   return 0;
116 }
117
118 } // namespace api
119 } // namespace librbd
120
121 template class librbd::api::Image<librbd::ImageCtx>;