]> git.proxmox.com Git - ceph.git/blob - ceph/examples/librbd/hello_world.cc
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / examples / librbd / hello_world.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 * This is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License version 2.1, as published by the Free Software
9 * Foundation. See file COPYING.
10 */
11
12 // install the librados-dev and librbd package to get this
13 #include <rados/librados.hpp>
14 #include <rbd/librbd.hpp>
15 #include <iostream>
16 #include <string>
17 #include <sstream>
18
19 int main(int argc, const char **argv)
20 {
21 int ret = 0;
22
23 // we will use all of these below
24 const char *pool_name = "hello_world_pool";
25 std::string hello("hello world!");
26 std::string object_name("hello_object");
27 librados::IoCtx io_ctx;
28
29 // first, we create a Rados object and initialize it
30 librados::Rados rados;
31 {
32 ret = rados.init("admin"); // just use the client.admin keyring
33 if (ret < 0) { // let's handle any error that might have come back
34 std::cerr << "couldn't initialize rados! error " << ret << std::endl;
35 ret = EXIT_FAILURE;
36 goto out;
37 } else {
38 std::cout << "we just set up a rados cluster object" << std::endl;
39 }
40 }
41
42 /*
43 * Now we need to get the rados object its config info. It can
44 * parse argv for us to find the id, monitors, etc, so let's just
45 * use that.
46 */
47 {
48 ret = rados.conf_parse_argv(argc, argv);
49 if (ret < 0) {
50 // This really can't happen, but we need to check to be a good citizen.
51 std::cerr << "failed to parse config options! error " << ret << std::endl;
52 ret = EXIT_FAILURE;
53 goto out;
54 } else {
55 std::cout << "we just parsed our config options" << std::endl;
56 // We also want to apply the config file if the user specified
57 // one, and conf_parse_argv won't do that for us.
58 for (int i = 0; i < argc; ++i) {
59 if ((strcmp(argv[i], "-c") == 0) || (strcmp(argv[i], "--conf") == 0)) {
60 ret = rados.conf_read_file(argv[i+1]);
61 if (ret < 0) {
62 // This could fail if the config file is malformed, but it'd be hard.
63 std::cerr << "failed to parse config file " << argv[i+1]
64 << "! error" << ret << std::endl;
65 ret = EXIT_FAILURE;
66 goto out;
67 }
68 break;
69 }
70 }
71 }
72 }
73
74 /*
75 * next, we actually connect to the cluster
76 */
77 {
78 ret = rados.connect();
79 if (ret < 0) {
80 std::cerr << "couldn't connect to cluster! error " << ret << std::endl;
81 ret = EXIT_FAILURE;
82 goto out;
83 } else {
84 std::cout << "we just connected to the rados cluster" << std::endl;
85 }
86 }
87
88 /*
89 * let's create our own pool instead of scribbling over real data.
90 * Note that this command creates pools with default PG counts specified
91 * by the monitors, which may not be appropriate for real use -- it's fine
92 * for testing, though.
93 */
94 {
95 ret = rados.pool_create(pool_name);
96 if (ret < 0) {
97 std::cerr << "couldn't create pool! error " << ret << std::endl;
98 return EXIT_FAILURE;
99 } else {
100 std::cout << "we just created a new pool named " << pool_name << std::endl;
101 }
102 }
103
104 /*
105 * create an "IoCtx" which is used to do IO to a pool
106 */
107 {
108 ret = rados.ioctx_create(pool_name, io_ctx);
109 if (ret < 0) {
110 std::cerr << "couldn't set up ioctx! error " << ret << std::endl;
111 ret = EXIT_FAILURE;
112 goto out;
113 } else {
114 std::cout << "we just created an ioctx for our pool" << std::endl;
115 }
116 }
117
118 /*
119 * create an rbd image and write data to it
120 */
121 {
122 std::string name = "librbd_test";
123 uint64_t size = 2 << 20;
124 int order = 0;
125 librbd::RBD rbd;
126 librbd::Image image;
127
128 ret = rbd.create(io_ctx, name.c_str(), size, &order);
129 if (ret < 0) {
130 std::cerr << "couldn't create an rbd image! error " << ret << std::endl;
131 ret = EXIT_FAILURE;
132 goto out;
133 } else {
134 std::cout << "we just created an rbd image" << std::endl;
135 }
136
137 ret = rbd.open(io_ctx, image, name.c_str(), NULL);
138 if (ret < 0) {
139 std::cerr << "couldn't open the rbd image! error " << ret << std::endl;
140 ret = EXIT_FAILURE;
141 goto out;
142 } else {
143 std::cout << "we just opened the rbd image" << std::endl;
144 }
145
146 int TEST_IO_SIZE = 512;
147 char test_data[TEST_IO_SIZE + 1];
148 int i;
149
150 for (i = 0; i < TEST_IO_SIZE; ++i) {
151 test_data[i] = (char) (rand() % (126 - 33) + 33);
152 }
153 test_data[TEST_IO_SIZE] = '\0';
154
155 size_t len = strlen(test_data);
156 ceph::bufferlist bl;
157 bl.append(test_data, len);
158
159 ret = image.write(0, len, bl);
160 if (ret < 0) {
161 std::cerr << "couldn't write to the rbd image! error " << ret << std::endl;
162 ret = EXIT_FAILURE;
163 goto out;
164 } else {
165 std::cout << "we just wrote data to our rbd image " << std::endl;
166 }
167
168 /*
169 * let's read the image and compare it to the data we wrote
170 */
171 ceph::bufferlist bl_r;
172 int read;
173 read = image.read(0, TEST_IO_SIZE, bl_r);
174 if (read < 0) {
175 std::cerr << "we couldn't read data from the image! error" << std::endl;
176 ret = EXIT_FAILURE;
177 goto out;
178 }
179
180 std::string bl_res(bl_r.c_str(), read);
181
182 int res = memcmp(bl_res.c_str(), test_data, TEST_IO_SIZE);
183 if (res != 0) {
184 std::cerr << "what we read didn't match expected! error" << std::endl;
185 } else {
186 std::cout << "we read our data on the image successfully" << std::endl;
187 }
188
189 image.close();
190
191 /*
192 *let's now delete the image
193 */
194 ret = rbd.remove(io_ctx, name.c_str());
195 if (ret < 0) {
196 std::cerr << "failed to delete rbd image! error " << ret << std::endl;
197 ret = EXIT_FAILURE;
198 goto out;
199 } else {
200 std::cout << "we just deleted our rbd image " << std::endl;
201 }
202 }
203
204 ret = EXIT_SUCCESS;
205 out:
206 /*
207 * And now we're done, so let's remove our pool and then
208 * shut down the connection gracefully.
209 */
210 int delete_ret = rados.pool_delete(pool_name);
211 if (delete_ret < 0) {
212 // be careful not to
213 std::cerr << "We failed to delete our test pool!" << std::endl;
214 ret = EXIT_FAILURE;
215 }
216
217 rados.shutdown();
218
219 return ret;
220 }