mirror of
https://git.proxmox.com/git/mirror_lxc
synced 2025-04-28 12:52:23 +00:00
256 lines
5.4 KiB
C
256 lines
5.4 KiB
C
/* SPDX-License-Identifier: LGPL-2.1+ */
|
|
|
|
#ifndef _GNU_SOURCE
|
|
#define _GNU_SOURCE 1
|
|
#endif
|
|
#define __STDC_FORMAT_MACROS /* Required for PRIu64 to work. */
|
|
#include <inttypes.h> /* Required for PRIu64 to work. */
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "config.h"
|
|
#include "log.h"
|
|
#include "memory_utils.h"
|
|
#include "storage.h"
|
|
#include "storage_utils.h"
|
|
#include "utils.h"
|
|
|
|
#ifndef HAVE_STRLCPY
|
|
#include "include/strlcpy.h"
|
|
#endif
|
|
|
|
lxc_log_define(rbd, lxc);
|
|
|
|
struct rbd_args {
|
|
const char *osd_pool_name;
|
|
const char *rbd_name;
|
|
const char *size;
|
|
};
|
|
|
|
int rbd_create_wrapper(void *data)
|
|
{
|
|
struct rbd_args *args = data;
|
|
|
|
execlp("rbd", "rbd", "create", "--pool", args->osd_pool_name,
|
|
args->rbd_name, "--size", args->size, (char *)NULL);
|
|
|
|
return -1;
|
|
}
|
|
|
|
int rbd_map_wrapper(void *data)
|
|
{
|
|
struct rbd_args *args = data;
|
|
|
|
execlp("rbd", "rbd", "map", "--pool", args->osd_pool_name,
|
|
args->rbd_name, (char *)NULL);
|
|
|
|
return -1;
|
|
}
|
|
|
|
int rbd_unmap_wrapper(void *data)
|
|
{
|
|
struct rbd_args *args = data;
|
|
|
|
execlp("rbd", "rbd", "unmap", args->rbd_name, (char *)NULL);
|
|
|
|
return -1;
|
|
}
|
|
|
|
int rbd_delete_wrapper(void *data)
|
|
{
|
|
struct rbd_args *args = data;
|
|
|
|
execlp("rbd", "rbd", "rm", args->rbd_name, (char *)NULL);
|
|
|
|
return -1;
|
|
}
|
|
|
|
int rbd_clonepaths(struct lxc_storage *orig, struct lxc_storage *new,
|
|
const char *oldname, const char *cname, const char *oldpath,
|
|
const char *lxcpath, int snap, uint64_t newsize,
|
|
struct lxc_conf *conf)
|
|
{
|
|
ERROR("rbd clonepaths not implemented");
|
|
return -1;
|
|
}
|
|
|
|
int rbd_create(struct lxc_storage *bdev, const char *dest, const char *n,
|
|
struct bdev_specs *specs)
|
|
{
|
|
const char *rbdpool, *fstype;
|
|
uint64_t size;
|
|
int ret, len;
|
|
char sz[24];
|
|
const char *cmd_args[2];
|
|
char cmd_output[PATH_MAX];
|
|
const char *rbdname = n;
|
|
struct rbd_args args = {0};
|
|
|
|
if (!specs)
|
|
return -1;
|
|
|
|
rbdpool = specs->rbd.rbdpool;
|
|
if (!rbdpool)
|
|
rbdpool = lxc_global_config_value("lxc.bdev.rbd.rbdpool");
|
|
|
|
if (specs->rbd.rbdname)
|
|
rbdname = specs->rbd.rbdname;
|
|
|
|
/* source device /dev/rbd/lxc/ctn */
|
|
len = strlen(rbdpool) + strlen(rbdname) + 4 + 11;
|
|
bdev->src = malloc(len);
|
|
if (!bdev->src) {
|
|
ERROR("Failed to allocate memory");
|
|
return -1;
|
|
}
|
|
|
|
ret = snprintf(bdev->src, len, "rbd:/dev/rbd/%s/%s", rbdpool, rbdname);
|
|
if (ret < 0 || ret >= len) {
|
|
ERROR("Failed to create string");
|
|
return -1;
|
|
}
|
|
|
|
/* fssize is in bytes */
|
|
size = specs->fssize;
|
|
if (!size)
|
|
size = DEFAULT_FS_SIZE;
|
|
|
|
/* in megabytes for rbd tool */
|
|
ret = snprintf(sz, 24, "%" PRIu64, size / 1024 / 1024);
|
|
if (ret < 0 || ret >= 24) {
|
|
ERROR("Failed to create string");
|
|
return -1;
|
|
}
|
|
|
|
args.osd_pool_name = rbdpool;
|
|
args.rbd_name = rbdname;
|
|
args.size = sz;
|
|
ret = run_command(cmd_output, sizeof(cmd_output), rbd_create_wrapper,
|
|
(void *)&args);
|
|
if (ret < 0) {
|
|
ERROR("Failed to create rbd storage volume \"%s\": %s", rbdname,
|
|
cmd_output);
|
|
return -1;
|
|
}
|
|
|
|
ret = run_command(cmd_output, sizeof(cmd_output), rbd_map_wrapper,
|
|
(void *)&args);
|
|
if (ret < 0) {
|
|
ERROR("Failed to map rbd storage volume \"%s\": %s", rbdname,
|
|
cmd_output);
|
|
return -1;
|
|
}
|
|
|
|
fstype = specs->fstype;
|
|
if (!fstype)
|
|
fstype = DEFAULT_FSTYPE;
|
|
|
|
cmd_args[0] = fstype;
|
|
cmd_args[1] = lxc_storage_get_path(bdev->src, bdev->type);
|
|
ret = run_command(cmd_output, sizeof(cmd_output), do_mkfs_exec_wrapper,
|
|
(void *)cmd_args);
|
|
if (ret < 0) {
|
|
ERROR("Failed to map rbd storage volume \"%s\": %s", rbdname,
|
|
cmd_output);
|
|
return -1;
|
|
}
|
|
|
|
bdev->dest = strdup(dest);
|
|
if (!bdev->dest) {
|
|
ERROR("Failed to duplicate string \"%s\"", dest);
|
|
return -1;
|
|
}
|
|
|
|
ret = mkdir_p(bdev->dest, 0755);
|
|
if (ret < 0 && errno != EEXIST) {
|
|
ERROR("Failed to create directory \"%s\"", bdev->dest);
|
|
return -1;
|
|
}
|
|
|
|
TRACE("Created rbd storage volume \"%s\"", bdev->dest);
|
|
return 0;
|
|
}
|
|
|
|
int rbd_destroy(struct lxc_storage *orig)
|
|
{
|
|
__do_free char *rbdfullname = NULL;
|
|
int ret;
|
|
const char *src;
|
|
char cmd_output[PATH_MAX];
|
|
struct rbd_args args = {0};
|
|
size_t len;
|
|
|
|
src = lxc_storage_get_path(orig->src, orig->type);
|
|
if (file_exists(src)) {
|
|
args.rbd_name = src;
|
|
ret = run_command(cmd_output, sizeof(cmd_output),
|
|
rbd_unmap_wrapper, (void *)&args);
|
|
if (ret < 0) {
|
|
ERROR("Failed to map rbd storage volume \"%s\": %s",
|
|
src, cmd_output);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
len = strlen(src);
|
|
rbdfullname = must_realloc(NULL, len - 8);
|
|
(void)strlcpy(rbdfullname, &src[9], len - 8);
|
|
args.rbd_name = rbdfullname;
|
|
|
|
ret = run_command(cmd_output, sizeof(cmd_output),
|
|
rbd_delete_wrapper, (void *)&args);
|
|
if (ret < 0) {
|
|
ERROR("Failed to delete rbd storage volume \"%s\": %s",
|
|
rbdfullname, cmd_output);
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
bool rbd_detect(const char *path)
|
|
{
|
|
if (!strncmp(path, "rbd:", 4))
|
|
return true;
|
|
|
|
if (!strncmp(path, "/dev/rbd/", 9))
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
int rbd_mount(struct lxc_storage *bdev)
|
|
{
|
|
const char *src;
|
|
|
|
if (strcmp(bdev->type, "rbd"))
|
|
return -22;
|
|
|
|
if (!bdev->src || !bdev->dest)
|
|
return -22;
|
|
|
|
src = lxc_storage_get_path(bdev->src, bdev->type);
|
|
if (!file_exists(src)) {
|
|
/* If blkdev does not exist it should be mapped, because it is
|
|
* not persistent on reboot.
|
|
*/
|
|
ERROR("Block device %s is not mapped.", bdev->src);
|
|
return -1;
|
|
}
|
|
|
|
return mount_unknown_fs(src, bdev->dest, bdev->mntopts);
|
|
}
|
|
|
|
int rbd_umount(struct lxc_storage *bdev)
|
|
{
|
|
if (strcmp(bdev->type, "rbd"))
|
|
return -22;
|
|
|
|
if (!bdev->src || !bdev->dest)
|
|
return -22;
|
|
|
|
return umount(bdev->dest);
|
|
}
|