]>
Commit | Line | Data |
---|---|---|
cc73685d | 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ |
3ceb2820 | 2 | |
1160ce89 CB |
3 | #include "config.h" |
4 | ||
7b22b3e9 | 5 | #include <inttypes.h> /* Required for PRIu64 to work. */ |
3ceb2820 CB |
6 | #include <stdint.h> |
7 | #include <stdio.h> | |
8 | #include <stdlib.h> | |
9 | #include <string.h> | |
10 | ||
3ceb2820 | 11 | #include "log.h" |
32068050 | 12 | #include "memory_utils.h" |
28d832c4 | 13 | #include "storage.h" |
f2d5a09d | 14 | #include "storage_utils.h" |
3ceb2820 CB |
15 | #include "utils.h" |
16 | ||
34498dea | 17 | #if !HAVE_STRLCPY |
58db1a61 | 18 | #include "strlcpy.h" |
43f984ea DJ |
19 | #endif |
20 | ||
10bc1861 | 21 | lxc_log_define(rbd, lxc); |
3ceb2820 | 22 | |
3b0e906f CB |
23 | struct rbd_args { |
24 | const char *osd_pool_name; | |
25 | const char *rbd_name; | |
26 | const char *size; | |
27 | }; | |
28 | ||
59eac805 | 29 | static int rbd_create_wrapper(void *data) |
3b0e906f CB |
30 | { |
31 | struct rbd_args *args = data; | |
32 | ||
33 | execlp("rbd", "rbd", "create", "--pool", args->osd_pool_name, | |
34 | args->rbd_name, "--size", args->size, (char *)NULL); | |
35 | ||
36 | return -1; | |
37 | } | |
38 | ||
59eac805 | 39 | static int rbd_map_wrapper(void *data) |
3b0e906f CB |
40 | { |
41 | struct rbd_args *args = data; | |
42 | ||
43 | execlp("rbd", "rbd", "map", "--pool", args->osd_pool_name, | |
44 | args->rbd_name, (char *)NULL); | |
45 | ||
46 | return -1; | |
47 | } | |
48 | ||
59eac805 | 49 | static int rbd_unmap_wrapper(void *data) |
3b0e906f CB |
50 | { |
51 | struct rbd_args *args = data; | |
52 | ||
53 | execlp("rbd", "rbd", "unmap", args->rbd_name, (char *)NULL); | |
54 | ||
55 | return -1; | |
56 | } | |
57 | ||
59eac805 | 58 | static int rbd_delete_wrapper(void *data) |
3b0e906f CB |
59 | { |
60 | struct rbd_args *args = data; | |
61 | ||
62 | execlp("rbd", "rbd", "rm", args->rbd_name, (char *)NULL); | |
63 | ||
64 | return -1; | |
65 | } | |
66 | ||
10bc1861 CB |
67 | int rbd_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, |
68 | const char *oldname, const char *cname, const char *oldpath, | |
69 | const char *lxcpath, int snap, uint64_t newsize, | |
70 | struct lxc_conf *conf) | |
3ceb2820 CB |
71 | { |
72 | ERROR("rbd clonepaths not implemented"); | |
73 | return -1; | |
74 | } | |
75 | ||
10bc1861 | 76 | int rbd_create(struct lxc_storage *bdev, const char *dest, const char *n, |
facdf925 | 77 | struct bdev_specs *specs, const struct lxc_conf *conf) |
3ceb2820 | 78 | { |
3b0e906f | 79 | const char *rbdpool, *fstype; |
3ceb2820 CB |
80 | uint64_t size; |
81 | int ret, len; | |
82 | char sz[24]; | |
a5b18cb1 | 83 | const char *cmd_args[2]; |
339de297 | 84 | char cmd_output[PATH_MAX]; |
3b0e906f CB |
85 | const char *rbdname = n; |
86 | struct rbd_args args = {0}; | |
3ceb2820 CB |
87 | |
88 | if (!specs) | |
89 | return -1; | |
90 | ||
91 | rbdpool = specs->rbd.rbdpool; | |
92 | if (!rbdpool) | |
93 | rbdpool = lxc_global_config_value("lxc.bdev.rbd.rbdpool"); | |
94 | ||
95 | if (specs->rbd.rbdname) | |
96 | rbdname = specs->rbd.rbdname; | |
97 | ||
98 | /* source device /dev/rbd/lxc/ctn */ | |
43bd0ebf | 99 | len = strlen(rbdpool) + strlen(rbdname) + 4 + 11; |
3ceb2820 | 100 | bdev->src = malloc(len); |
3b0e906f CB |
101 | if (!bdev->src) { |
102 | ERROR("Failed to allocate memory"); | |
3ceb2820 | 103 | return -1; |
3b0e906f | 104 | } |
3ceb2820 | 105 | |
43bd0ebf | 106 | ret = snprintf(bdev->src, len, "rbd:/dev/rbd/%s/%s", rbdpool, rbdname); |
3b0e906f CB |
107 | if (ret < 0 || ret >= len) { |
108 | ERROR("Failed to create string"); | |
3ceb2820 | 109 | return -1; |
3b0e906f | 110 | } |
3ceb2820 | 111 | |
7b22b3e9 | 112 | /* fssize is in bytes */ |
3ceb2820 CB |
113 | size = specs->fssize; |
114 | if (!size) | |
115 | size = DEFAULT_FS_SIZE; | |
116 | ||
7b22b3e9 CB |
117 | /* in megabytes for rbd tool */ |
118 | ret = snprintf(sz, 24, "%" PRIu64, size / 1024 / 1024); | |
3b0e906f CB |
119 | if (ret < 0 || ret >= 24) { |
120 | ERROR("Failed to create string"); | |
3ceb2820 | 121 | return -1; |
3ceb2820 | 122 | } |
3ceb2820 | 123 | |
3b0e906f CB |
124 | args.osd_pool_name = rbdpool; |
125 | args.rbd_name = rbdname; | |
126 | args.size = sz; | |
127 | ret = run_command(cmd_output, sizeof(cmd_output), rbd_create_wrapper, | |
128 | (void *)&args); | |
129 | if (ret < 0) { | |
130 | ERROR("Failed to create rbd storage volume \"%s\": %s", rbdname, | |
131 | cmd_output); | |
3ceb2820 | 132 | return -1; |
3ceb2820 | 133 | } |
3b0e906f CB |
134 | |
135 | ret = run_command(cmd_output, sizeof(cmd_output), rbd_map_wrapper, | |
136 | (void *)&args); | |
137 | if (ret < 0) { | |
138 | ERROR("Failed to map rbd storage volume \"%s\": %s", rbdname, | |
139 | cmd_output); | |
3ceb2820 | 140 | return -1; |
3b0e906f | 141 | } |
3ceb2820 CB |
142 | |
143 | fstype = specs->fstype; | |
144 | if (!fstype) | |
145 | fstype = DEFAULT_FSTYPE; | |
146 | ||
a5b18cb1 | 147 | cmd_args[0] = fstype; |
3b0e906f | 148 | cmd_args[1] = lxc_storage_get_path(bdev->src, bdev->type); |
a5b18cb1 CB |
149 | ret = run_command(cmd_output, sizeof(cmd_output), do_mkfs_exec_wrapper, |
150 | (void *)cmd_args); | |
3b0e906f CB |
151 | if (ret < 0) { |
152 | ERROR("Failed to map rbd storage volume \"%s\": %s", rbdname, | |
153 | cmd_output); | |
3ceb2820 | 154 | return -1; |
3b0e906f | 155 | } |
a5b18cb1 | 156 | |
3b0e906f CB |
157 | bdev->dest = strdup(dest); |
158 | if (!bdev->dest) { | |
159 | ERROR("Failed to duplicate string \"%s\"", dest); | |
3ceb2820 | 160 | return -1; |
3b0e906f | 161 | } |
3ceb2820 | 162 | |
539c3977 | 163 | ret = lxc_mkdir_p(bdev->dest, 0755); |
3b0e906f CB |
164 | if (ret < 0 && errno != EEXIST) { |
165 | ERROR("Failed to create directory \"%s\"", bdev->dest); | |
3ceb2820 CB |
166 | return -1; |
167 | } | |
168 | ||
3b0e906f | 169 | TRACE("Created rbd storage volume \"%s\"", bdev->dest); |
3ceb2820 CB |
170 | return 0; |
171 | } | |
172 | ||
10bc1861 | 173 | int rbd_destroy(struct lxc_storage *orig) |
3ceb2820 | 174 | { |
32068050 | 175 | __do_free char *rbdfullname = NULL; |
3b0e906f | 176 | int ret; |
41dc7155 | 177 | const char *src; |
339de297 | 178 | char cmd_output[PATH_MAX]; |
3b0e906f | 179 | struct rbd_args args = {0}; |
43f984ea | 180 | size_t len; |
3ceb2820 | 181 | |
43bd0ebf CB |
182 | src = lxc_storage_get_path(orig->src, orig->type); |
183 | if (file_exists(src)) { | |
3b0e906f CB |
184 | args.rbd_name = src; |
185 | ret = run_command(cmd_output, sizeof(cmd_output), | |
186 | rbd_unmap_wrapper, (void *)&args); | |
187 | if (ret < 0) { | |
188 | ERROR("Failed to map rbd storage volume \"%s\": %s", | |
189 | src, cmd_output); | |
3ceb2820 | 190 | return -1; |
3ceb2820 | 191 | } |
3ceb2820 CB |
192 | } |
193 | ||
43f984ea | 194 | len = strlen(src); |
32068050 | 195 | rbdfullname = must_realloc(NULL, len - 8); |
43f984ea | 196 | (void)strlcpy(rbdfullname, &src[9], len - 8); |
3b0e906f | 197 | args.rbd_name = rbdfullname; |
43f984ea | 198 | |
3b0e906f CB |
199 | ret = run_command(cmd_output, sizeof(cmd_output), |
200 | rbd_delete_wrapper, (void *)&args); | |
201 | if (ret < 0) { | |
202 | ERROR("Failed to delete rbd storage volume \"%s\": %s", | |
203 | rbdfullname, cmd_output); | |
3ceb2820 | 204 | return -1; |
3ceb2820 | 205 | } |
3b0e906f CB |
206 | |
207 | return 0; | |
3ceb2820 CB |
208 | } |
209 | ||
3d2ae1e2 | 210 | bool rbd_detect(const char *path) |
3ceb2820 | 211 | { |
f7ac4459 | 212 | if (!strncmp(path, "rbd:", 4)) |
3d2ae1e2 | 213 | return true; |
f7ac4459 CB |
214 | |
215 | if (!strncmp(path, "/dev/rbd/", 9)) | |
3d2ae1e2 | 216 | return true; |
f7ac4459 | 217 | |
3d2ae1e2 | 218 | return false; |
3ceb2820 CB |
219 | } |
220 | ||
10bc1861 | 221 | int rbd_mount(struct lxc_storage *bdev) |
3ceb2820 | 222 | { |
41dc7155 | 223 | const char *src; |
3b0e906f | 224 | |
3ceb2820 CB |
225 | if (strcmp(bdev->type, "rbd")) |
226 | return -22; | |
43bd0ebf | 227 | |
3ceb2820 CB |
228 | if (!bdev->src || !bdev->dest) |
229 | return -22; | |
230 | ||
43bd0ebf CB |
231 | src = lxc_storage_get_path(bdev->src, bdev->type); |
232 | if (!file_exists(src)) { | |
7b22b3e9 CB |
233 | /* If blkdev does not exist it should be mapped, because it is |
234 | * not persistent on reboot. | |
235 | */ | |
3ceb2820 CB |
236 | ERROR("Block device %s is not mapped.", bdev->src); |
237 | return -1; | |
238 | } | |
239 | ||
3b0e906f | 240 | return mount_unknown_fs(src, bdev->dest, bdev->mntopts); |
3ceb2820 CB |
241 | } |
242 | ||
10bc1861 | 243 | int rbd_umount(struct lxc_storage *bdev) |
3ceb2820 CB |
244 | { |
245 | if (strcmp(bdev->type, "rbd")) | |
246 | return -22; | |
43bd0ebf | 247 | |
3ceb2820 CB |
248 | if (!bdev->src || !bdev->dest) |
249 | return -22; | |
43bd0ebf | 250 | |
3ceb2820 CB |
251 | return umount(bdev->dest); |
252 | } |