X-Git-Url: http://git.annexia.org/?p=libguestfs.git;a=blobdiff_plain;f=daemon%2Fmd.c;h=5a4d8154f254b8352bf3df6bb2606719a158f9e0;hp=257bd0f0209ea49d28fb6f40bb0cad4dd5664f6e;hb=2d5841133a199619d56d026ad9ea4e97791f4a8f;hpb=00a0fab50b3803be8db5b7d9fa0869a70b0da556 diff --git a/daemon/md.c b/daemon/md.c index 257bd0f..5a4d815 100644 --- a/daemon/md.c +++ b/daemon/md.c @@ -27,6 +27,7 @@ #include "daemon.h" #include "actions.h" #include "optgroups.h" +#include "c-ctype.h" int optgroup_mdadm_available (void) @@ -49,9 +50,9 @@ count_bits (uint64_t bitmap) /* Takes optional arguments, consult optargs_bitmask. */ int -do_mdadm_create (const char *name, char *const *devices, - int64_t missingbitmap, int nrdevices, int spare, - int64_t chunk, const char *level) +do_md_create (const char *name, char *const *devices, + int64_t missingbitmap, int nrdevices, int spare, + int64_t chunk, const char *level) { char nrdevices_s[32]; char spare_s[32]; @@ -62,10 +63,10 @@ do_mdadm_create (const char *name, char *const *devices, uint64_t umissingbitmap = (uint64_t) missingbitmap; /* Check the optional parameters and set defaults where appropriate. */ - if (!(optargs_bitmask & GUESTFS_MDADM_CREATE_MISSINGBITMAP_BITMASK)) + if (!(optargs_bitmask & GUESTFS_MD_CREATE_MISSINGBITMAP_BITMASK)) umissingbitmap = 0; - if (optargs_bitmask & GUESTFS_MDADM_CREATE_SPARE_BITMASK) { + if (optargs_bitmask & GUESTFS_MD_CREATE_SPARE_BITMASK) { if (spare < 0) { reply_with_error ("spare must not be negative"); return -1; @@ -74,7 +75,7 @@ do_mdadm_create (const char *name, char *const *devices, else spare = 0; - if (optargs_bitmask & GUESTFS_MDADM_CREATE_NRDEVICES_BITMASK) { + if (optargs_bitmask & GUESTFS_MD_CREATE_NRDEVICES_BITMASK) { if (nrdevices < 2) { reply_with_error ("nrdevices is less than 2"); return -1; @@ -83,7 +84,7 @@ do_mdadm_create (const char *name, char *const *devices, else nrdevices = count_strings (devices) + count_bits (umissingbitmap); - if (optargs_bitmask & GUESTFS_MDADM_CREATE_LEVEL_BITMASK) { + if (optargs_bitmask & GUESTFS_MD_CREATE_LEVEL_BITMASK) { if (STRNEQ (level, "linear") && STRNEQ (level, "raid0") && STRNEQ (level, "0") && STRNEQ (level, "stripe") && STRNEQ (level, "raid1") && STRNEQ (level, "1") && @@ -99,7 +100,7 @@ do_mdadm_create (const char *name, char *const *devices, else level = "raid1"; - if (optargs_bitmask & GUESTFS_MDADM_CREATE_CHUNK_BITMASK) { + if (optargs_bitmask & GUESTFS_MD_CREATE_CHUNK_BITMASK) { /* chunk is bytes in the libguestfs API, but K when we pass it to mdadm */ if ((chunk & 1023) != 0) { reply_with_error ("chunk size must be a multiple of 1024 bytes"); @@ -130,12 +131,12 @@ do_mdadm_create (const char *name, char *const *devices, ADD_ARG (argv, i, "--raid-devices"); snprintf (nrdevices_s, sizeof nrdevices_s, "%d", nrdevices); ADD_ARG (argv, i, nrdevices_s); - if (optargs_bitmask & GUESTFS_MDADM_CREATE_SPARE_BITMASK) { + if (optargs_bitmask & GUESTFS_MD_CREATE_SPARE_BITMASK) { ADD_ARG (argv, i, "--spare-devices"); snprintf (spare_s, sizeof spare_s, "%d", spare); ADD_ARG (argv, i, spare_s); } - if (optargs_bitmask & GUESTFS_MDADM_CREATE_CHUNK_BITMASK) { + if (optargs_bitmask & GUESTFS_MD_CREATE_CHUNK_BITMASK) { ADD_ARG (argv, i, "--chunk"); snprintf (chunk_s, sizeof chunk_s, "%" PRIi64, chunk / 1024); ADD_ARG (argv, i, chunk_s); @@ -230,3 +231,98 @@ error: if (r != NULL) free_strings (r); return NULL; } + +char ** +do_md_detail(const char *md) +{ + int r; + + char *out = NULL, *err = NULL; + char **lines = NULL; + + char **ret = NULL; + int size = 0, alloc = 0; + + const char *mdadm[] = { "mdadm", "-D", "--export", md, NULL }; + r = commandv(&out, &err, mdadm); + if (r == -1) { + reply_with_error("%s", err); + goto error; + } + + /* Split the command output into lines */ + lines = split_lines(out); + if (lines == NULL) { + reply_with_perror("malloc"); + goto error; + } + + /* Parse the output of mdadm -D --export: + * MD_LEVEL=raid1 + * MD_DEVICES=2 + * MD_METADATA=1.0 + * MD_UUID=cfa81b59:b6cfbd53:3f02085b:58f4a2e1 + * MD_NAME=localhost.localdomain:0 + */ + for (char **i = lines; *i != NULL; i++) { + char *line = *i; + + /* Skip blank lines (shouldn't happen) */ + if (line[0] == '\0') continue; + + /* Split the line in 2 at the equals sign */ + char *eq = strchr(line, '='); + if (eq) { + *eq = '\0'; eq++; + + /* Remove the MD_ prefix from the key and translate the remainder to lower + * case */ + if (STRPREFIX(line, "MD_")) { + line += 3; + for (char *j = line; *j != '\0'; j++) { + *j = c_tolower(*j); + } + } + + /* Add the key/value pair to the output */ + if (add_string(&ret, &size, &alloc, line) == -1 || + add_string(&ret, &size, &alloc, eq) == -1) goto error; + } else { + /* Ignore lines with no equals sign (shouldn't happen). Log to stderr so + * it will show up in LIBGUESTFS_DEBUG. */ + fprintf(stderr, "md-detail: unexpected mdadm output ignored: %s", line); + } + } + + free(out); + free(err); + free(lines); /* We freed the contained strings when we freed out */ + + if (add_string(&ret, &size, &alloc, NULL) == -1) return NULL; + + return ret; + +error: + free(out); + free(err); + if (lines) free(lines); + if (ret) free_strings(ret); + + return NULL; +} + +int +do_md_stop(const char *md) +{ + int r; + char *err = NULL; + + const char *mdadm[] = { "mdadm", "--stop", md, NULL}; + r = commandv(NULL, &err, mdadm); + if (r == -1) { + reply_with_error("%s", err); + free(err); + return -1; + } + return 0; +}