diff --git a/cfg.mk b/cfg.mk index e5442f5929..08ed55f90f 100644 --- a/cfg.mk +++ b/cfg.mk @@ -773,7 +773,7 @@ exclude_file_name_regexp--sc_prohibit_xmlURI = ^src/util/viruri\.c$$ exclude_file_name_regexp--sc_prohibit_return_as_function = \.py$$ -_virsh_includes=(edit|domain-monitor|domain|volume|pool|network|interface|nwfilter) +_virsh_includes=(edit|domain-monitor|domain|volume|pool|network|interface|nwfilter|secret) exclude_file_name_regexp--sc_require_config_h = ^(examples/|tools/virsh-$(_virsh_includes)\.c$$) exclude_file_name_regexp--sc_require_config_h_first = ^(examples/|tools/virsh-$(_virsh_includes)\.c$$) diff --git a/po/POTFILES.in b/po/POTFILES.in index 5d0e6a338c..76357ce6f1 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -184,6 +184,7 @@ tools/virsh-interface.c tools/virsh-network.c tools/virsh-nwfilter.c tools/virsh-pool.c +tools/virsh-secret.c tools/virsh-volume.c tools/virt-host-validate-common.c tools/virt-host-validate-lxc.c diff --git a/tools/virsh-secret.c b/tools/virsh-secret.c new file mode 100644 index 0000000000..5020028e1f --- /dev/null +++ b/tools/virsh-secret.c @@ -0,0 +1,358 @@ +/* + * virsh-secret.c: Commands to manage secret + * + * Copyright (C) 2005, 2007-2012 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; If not, see + * . + * + * Daniel Veillard + * Karel Zak + * Daniel P. Berrange + * + */ + +static virSecretPtr +vshCommandOptSecret(vshControl *ctl, const vshCmd *cmd, const char **name) +{ + virSecretPtr secret = NULL; + const char *n = NULL; + const char *optname = "secret"; + + if (!cmd_has_option(ctl, cmd, optname)) + return NULL; + + if (vshCommandOptString(cmd, optname, &n) <= 0) + return NULL; + + vshDebug(ctl, VSH_ERR_DEBUG, + "%s: found option <%s>: %s\n", cmd->def->name, optname, n); + + if (name != NULL) + *name = n; + + secret = virSecretLookupByUUIDString(ctl->conn, n); + + if (secret == NULL) + vshError(ctl, _("failed to get secret '%s'"), n); + + return secret; +} + +/* + * "secret-define" command + */ +static const vshCmdInfo info_secret_define[] = { + {"help", N_("define or modify a secret from an XML file")}, + {"desc", N_("Define or modify a secret.")}, + {NULL, NULL} +}; + +static const vshCmdOptDef opts_secret_define[] = { + {"file", VSH_OT_DATA, VSH_OFLAG_REQ, N_("file containing secret attributes in XML")}, + {NULL, 0, 0, NULL} +}; + +static bool +cmdSecretDefine(vshControl *ctl, const vshCmd *cmd) +{ + const char *from = NULL; + char *buffer; + virSecretPtr res; + char uuid[VIR_UUID_STRING_BUFLEN]; + + if (!vshConnectionUsability(ctl, ctl->conn)) + return false; + + if (vshCommandOptString(cmd, "file", &from) <= 0) + return false; + + if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0) + return false; + + res = virSecretDefineXML(ctl->conn, buffer, 0); + VIR_FREE(buffer); + + if (res == NULL) { + vshError(ctl, _("Failed to set attributes from %s"), from); + return false; + } + if (virSecretGetUUIDString(res, &(uuid[0])) < 0) { + vshError(ctl, "%s", _("Failed to get UUID of created secret")); + virSecretFree(res); + return false; + } + vshPrint(ctl, _("Secret %s created\n"), uuid); + virSecretFree(res); + return true; +} + +/* + * "secret-dumpxml" command + */ +static const vshCmdInfo info_secret_dumpxml[] = { + {"help", N_("secret attributes in XML")}, + {"desc", N_("Output attributes of a secret as an XML dump to stdout.")}, + {NULL, NULL} +}; + +static const vshCmdOptDef opts_secret_dumpxml[] = { + {"secret", VSH_OT_DATA, VSH_OFLAG_REQ, N_("secret UUID")}, + {NULL, 0, 0, NULL} +}; + +static bool +cmdSecretDumpXML(vshControl *ctl, const vshCmd *cmd) +{ + virSecretPtr secret; + bool ret = false; + char *xml; + + if (!vshConnectionUsability(ctl, ctl->conn)) + return false; + + secret = vshCommandOptSecret(ctl, cmd, NULL); + if (secret == NULL) + return false; + + xml = virSecretGetXMLDesc(secret, 0); + if (xml == NULL) + goto cleanup; + vshPrint(ctl, "%s", xml); + VIR_FREE(xml); + ret = true; + +cleanup: + virSecretFree(secret); + return ret; +} + +/* + * "secret-set-value" command + */ +static const vshCmdInfo info_secret_set_value[] = { + {"help", N_("set a secret value")}, + {"desc", N_("Set a secret value.")}, + {NULL, NULL} +}; + +static const vshCmdOptDef opts_secret_set_value[] = { + {"secret", VSH_OT_DATA, VSH_OFLAG_REQ, N_("secret UUID")}, + {"base64", VSH_OT_DATA, VSH_OFLAG_REQ, N_("base64-encoded secret value")}, + {NULL, 0, 0, NULL} +}; + +static bool +cmdSecretSetValue(vshControl *ctl, const vshCmd *cmd) +{ + virSecretPtr secret; + size_t value_size; + const char *base64 = NULL; + char *value; + int res; + bool ret = false; + + if (!vshConnectionUsability(ctl, ctl->conn)) + return false; + + secret = vshCommandOptSecret(ctl, cmd, NULL); + if (secret == NULL) + return false; + + if (vshCommandOptString(cmd, "base64", &base64) <= 0) + goto cleanup; + + if (!base64_decode_alloc(base64, strlen(base64), &value, &value_size)) { + vshError(ctl, "%s", _("Invalid base64 data")); + goto cleanup; + } + if (value == NULL) { + vshError(ctl, "%s", _("Failed to allocate memory")); + return false; + } + + res = virSecretSetValue(secret, (unsigned char *)value, value_size, 0); + memset(value, 0, value_size); + VIR_FREE(value); + + if (res != 0) { + vshError(ctl, "%s", _("Failed to set secret value")); + goto cleanup; + } + vshPrint(ctl, "%s", _("Secret value set\n")); + ret = true; + +cleanup: + virSecretFree(secret); + return ret; +} + +/* + * "secret-get-value" command + */ +static const vshCmdInfo info_secret_get_value[] = { + {"help", N_("Output a secret value")}, + {"desc", N_("Output a secret value to stdout.")}, + {NULL, NULL} +}; + +static const vshCmdOptDef opts_secret_get_value[] = { + {"secret", VSH_OT_DATA, VSH_OFLAG_REQ, N_("secret UUID")}, + {NULL, 0, 0, NULL} +}; + +static bool +cmdSecretGetValue(vshControl *ctl, const vshCmd *cmd) +{ + virSecretPtr secret; + char *base64; + unsigned char *value; + size_t value_size; + bool ret = false; + + if (!vshConnectionUsability(ctl, ctl->conn)) + return false; + + secret = vshCommandOptSecret(ctl, cmd, NULL); + if (secret == NULL) + return false; + + value = virSecretGetValue(secret, &value_size, 0); + if (value == NULL) + goto cleanup; + + base64_encode_alloc((char *)value, value_size, &base64); + memset(value, 0, value_size); + VIR_FREE(value); + + if (base64 == NULL) { + vshError(ctl, "%s", _("Failed to allocate memory")); + goto cleanup; + } + vshPrint(ctl, "%s", base64); + memset(base64, 0, strlen(base64)); + VIR_FREE(base64); + ret = true; + +cleanup: + virSecretFree(secret); + return ret; +} + +/* + * "secret-undefine" command + */ +static const vshCmdInfo info_secret_undefine[] = { + {"help", N_("undefine a secret")}, + {"desc", N_("Undefine a secret.")}, + {NULL, NULL} +}; + +static const vshCmdOptDef opts_secret_undefine[] = { + {"secret", VSH_OT_DATA, VSH_OFLAG_REQ, N_("secret UUID")}, + {NULL, 0, 0, NULL} +}; + +static bool +cmdSecretUndefine(vshControl *ctl, const vshCmd *cmd) +{ + virSecretPtr secret; + bool ret = false; + const char *uuid; + + if (!vshConnectionUsability(ctl, ctl->conn)) + return false; + + secret = vshCommandOptSecret(ctl, cmd, &uuid); + if (secret == NULL) + return false; + + if (virSecretUndefine(secret) < 0) { + vshError(ctl, _("Failed to delete secret %s"), uuid); + goto cleanup; + } + vshPrint(ctl, _("Secret %s deleted\n"), uuid); + ret = true; + +cleanup: + virSecretFree(secret); + return ret; +} + +/* + * "secret-list" command + */ +static const vshCmdInfo info_secret_list[] = { + {"help", N_("list secrets")}, + {"desc", N_("Returns a list of secrets")}, + {NULL, NULL} +}; + +static bool +cmdSecretList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) +{ + int maxuuids = 0, i; + char **uuids = NULL; + + if (!vshConnectionUsability(ctl, ctl->conn)) + return false; + + maxuuids = virConnectNumOfSecrets(ctl->conn); + if (maxuuids < 0) { + vshError(ctl, "%s", _("Failed to list secrets")); + return false; + } + uuids = vshMalloc(ctl, sizeof(*uuids) * maxuuids); + + maxuuids = virConnectListSecrets(ctl->conn, uuids, maxuuids); + if (maxuuids < 0) { + vshError(ctl, "%s", _("Failed to list secrets")); + VIR_FREE(uuids); + return false; + } + + qsort(uuids, maxuuids, sizeof(char *), vshNameSorter); + + vshPrintExtra(ctl, "%-36s %s\n", _("UUID"), _("Usage")); + vshPrintExtra(ctl, "-----------------------------------------------------------\n"); + + for (i = 0; i < maxuuids; i++) { + virSecretPtr sec = virSecretLookupByUUIDString(ctl->conn, uuids[i]); + const char *usageType = NULL; + + if (!sec) { + VIR_FREE(uuids[i]); + continue; + } + + switch (virSecretGetUsageType(sec)) { + case VIR_SECRET_USAGE_TYPE_VOLUME: + usageType = _("Volume"); + break; + } + + if (usageType) { + vshPrint(ctl, "%-36s %s %s\n", + uuids[i], usageType, + virSecretGetUsageID(sec)); + } else { + vshPrint(ctl, "%-36s %s\n", + uuids[i], _("Unused")); + } + virSecretFree(sec); + VIR_FREE(uuids[i]); + } + VIR_FREE(uuids); + return true; +} diff --git a/tools/virsh.c b/tools/virsh.c index 7cd5b82e2c..72b8a0a584 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -338,9 +338,6 @@ static virDomainPtr vshCommandOptDomainBy(vshControl *ctl, const vshCmd *cmd, #define vshCommandOptDomain(_ctl, _cmd, _name) \ vshCommandOptDomainBy(_ctl, _cmd, _name, VSH_BYID|VSH_BYUUID|VSH_BYNAME) -static virSecretPtr vshCommandOptSecret(vshControl *ctl, const vshCmd *cmd, - const char **name); - static void vshPrintExtra(vshControl *ctl, const char *format, ...) ATTRIBUTE_FMT_PRINTF(2, 3); static void vshDebug(vshControl *ctl, int level, const char *format, ...) @@ -1340,314 +1337,6 @@ cmdNodeDeviceDestroy(vshControl *ctl, const vshCmd *cmd) return ret; } -/* - * "secret-define" command - */ -static const vshCmdInfo info_secret_define[] = { - {"help", N_("define or modify a secret from an XML file")}, - {"desc", N_("Define or modify a secret.")}, - {NULL, NULL} -}; - -static const vshCmdOptDef opts_secret_define[] = { - {"file", VSH_OT_DATA, VSH_OFLAG_REQ, N_("file containing secret attributes in XML")}, - {NULL, 0, 0, NULL} -}; - -static bool -cmdSecretDefine(vshControl *ctl, const vshCmd *cmd) -{ - const char *from = NULL; - char *buffer; - virSecretPtr res; - char uuid[VIR_UUID_STRING_BUFLEN]; - - if (!vshConnectionUsability(ctl, ctl->conn)) - return false; - - if (vshCommandOptString(cmd, "file", &from) <= 0) - return false; - - if (virFileReadAll(from, VIRSH_MAX_XML_FILE, &buffer) < 0) - return false; - - res = virSecretDefineXML(ctl->conn, buffer, 0); - VIR_FREE(buffer); - - if (res == NULL) { - vshError(ctl, _("Failed to set attributes from %s"), from); - return false; - } - if (virSecretGetUUIDString(res, &(uuid[0])) < 0) { - vshError(ctl, "%s", _("Failed to get UUID of created secret")); - virSecretFree(res); - return false; - } - vshPrint(ctl, _("Secret %s created\n"), uuid); - virSecretFree(res); - return true; -} - -/* - * "secret-dumpxml" command - */ -static const vshCmdInfo info_secret_dumpxml[] = { - {"help", N_("secret attributes in XML")}, - {"desc", N_("Output attributes of a secret as an XML dump to stdout.")}, - {NULL, NULL} -}; - -static const vshCmdOptDef opts_secret_dumpxml[] = { - {"secret", VSH_OT_DATA, VSH_OFLAG_REQ, N_("secret UUID")}, - {NULL, 0, 0, NULL} -}; - -static bool -cmdSecretDumpXML(vshControl *ctl, const vshCmd *cmd) -{ - virSecretPtr secret; - bool ret = false; - char *xml; - - if (!vshConnectionUsability(ctl, ctl->conn)) - return false; - - secret = vshCommandOptSecret(ctl, cmd, NULL); - if (secret == NULL) - return false; - - xml = virSecretGetXMLDesc(secret, 0); - if (xml == NULL) - goto cleanup; - vshPrint(ctl, "%s", xml); - VIR_FREE(xml); - ret = true; - -cleanup: - virSecretFree(secret); - return ret; -} - -/* - * "secret-set-value" command - */ -static const vshCmdInfo info_secret_set_value[] = { - {"help", N_("set a secret value")}, - {"desc", N_("Set a secret value.")}, - {NULL, NULL} -}; - -static const vshCmdOptDef opts_secret_set_value[] = { - {"secret", VSH_OT_DATA, VSH_OFLAG_REQ, N_("secret UUID")}, - {"base64", VSH_OT_DATA, VSH_OFLAG_REQ, N_("base64-encoded secret value")}, - {NULL, 0, 0, NULL} -}; - -static bool -cmdSecretSetValue(vshControl *ctl, const vshCmd *cmd) -{ - virSecretPtr secret; - size_t value_size; - const char *base64 = NULL; - char *value; - int res; - bool ret = false; - - if (!vshConnectionUsability(ctl, ctl->conn)) - return false; - - secret = vshCommandOptSecret(ctl, cmd, NULL); - if (secret == NULL) - return false; - - if (vshCommandOptString(cmd, "base64", &base64) <= 0) - goto cleanup; - - if (!base64_decode_alloc(base64, strlen(base64), &value, &value_size)) { - vshError(ctl, "%s", _("Invalid base64 data")); - goto cleanup; - } - if (value == NULL) { - vshError(ctl, "%s", _("Failed to allocate memory")); - return false; - } - - res = virSecretSetValue(secret, (unsigned char *)value, value_size, 0); - memset(value, 0, value_size); - VIR_FREE(value); - - if (res != 0) { - vshError(ctl, "%s", _("Failed to set secret value")); - goto cleanup; - } - vshPrint(ctl, "%s", _("Secret value set\n")); - ret = true; - -cleanup: - virSecretFree(secret); - return ret; -} - -/* - * "secret-get-value" command - */ -static const vshCmdInfo info_secret_get_value[] = { - {"help", N_("Output a secret value")}, - {"desc", N_("Output a secret value to stdout.")}, - {NULL, NULL} -}; - -static const vshCmdOptDef opts_secret_get_value[] = { - {"secret", VSH_OT_DATA, VSH_OFLAG_REQ, N_("secret UUID")}, - {NULL, 0, 0, NULL} -}; - -static bool -cmdSecretGetValue(vshControl *ctl, const vshCmd *cmd) -{ - virSecretPtr secret; - char *base64; - unsigned char *value; - size_t value_size; - bool ret = false; - - if (!vshConnectionUsability(ctl, ctl->conn)) - return false; - - secret = vshCommandOptSecret(ctl, cmd, NULL); - if (secret == NULL) - return false; - - value = virSecretGetValue(secret, &value_size, 0); - if (value == NULL) - goto cleanup; - - base64_encode_alloc((char *)value, value_size, &base64); - memset(value, 0, value_size); - VIR_FREE(value); - - if (base64 == NULL) { - vshError(ctl, "%s", _("Failed to allocate memory")); - goto cleanup; - } - vshPrint(ctl, "%s", base64); - memset(base64, 0, strlen(base64)); - VIR_FREE(base64); - ret = true; - -cleanup: - virSecretFree(secret); - return ret; -} - -/* - * "secret-undefine" command - */ -static const vshCmdInfo info_secret_undefine[] = { - {"help", N_("undefine a secret")}, - {"desc", N_("Undefine a secret.")}, - {NULL, NULL} -}; - -static const vshCmdOptDef opts_secret_undefine[] = { - {"secret", VSH_OT_DATA, VSH_OFLAG_REQ, N_("secret UUID")}, - {NULL, 0, 0, NULL} -}; - -static bool -cmdSecretUndefine(vshControl *ctl, const vshCmd *cmd) -{ - virSecretPtr secret; - bool ret = false; - const char *uuid; - - if (!vshConnectionUsability(ctl, ctl->conn)) - return false; - - secret = vshCommandOptSecret(ctl, cmd, &uuid); - if (secret == NULL) - return false; - - if (virSecretUndefine(secret) < 0) { - vshError(ctl, _("Failed to delete secret %s"), uuid); - goto cleanup; - } - vshPrint(ctl, _("Secret %s deleted\n"), uuid); - ret = true; - -cleanup: - virSecretFree(secret); - return ret; -} - -/* - * "secret-list" command - */ -static const vshCmdInfo info_secret_list[] = { - {"help", N_("list secrets")}, - {"desc", N_("Returns a list of secrets")}, - {NULL, NULL} -}; - -static bool -cmdSecretList(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED) -{ - int maxuuids = 0, i; - char **uuids = NULL; - - if (!vshConnectionUsability(ctl, ctl->conn)) - return false; - - maxuuids = virConnectNumOfSecrets(ctl->conn); - if (maxuuids < 0) { - vshError(ctl, "%s", _("Failed to list secrets")); - return false; - } - uuids = vshMalloc(ctl, sizeof(*uuids) * maxuuids); - - maxuuids = virConnectListSecrets(ctl->conn, uuids, maxuuids); - if (maxuuids < 0) { - vshError(ctl, "%s", _("Failed to list secrets")); - VIR_FREE(uuids); - return false; - } - - qsort(uuids, maxuuids, sizeof(char *), vshNameSorter); - - vshPrintExtra(ctl, "%-36s %s\n", _("UUID"), _("Usage")); - vshPrintExtra(ctl, "-----------------------------------------------------------\n"); - - for (i = 0; i < maxuuids; i++) { - virSecretPtr sec = virSecretLookupByUUIDString(ctl->conn, uuids[i]); - const char *usageType = NULL; - - if (!sec) { - VIR_FREE(uuids[i]); - continue; - } - - switch (virSecretGetUsageType(sec)) { - case VIR_SECRET_USAGE_TYPE_VOLUME: - usageType = _("Volume"); - break; - } - - if (usageType) { - vshPrint(ctl, "%-36s %s %s\n", - uuids[i], usageType, - virSecretGetUsageID(sec)); - } else { - vshPrint(ctl, "%-36s %s\n", - uuids[i], _("Unused")); - } - virSecretFree(sec); - VIR_FREE(uuids[i]); - } - VIR_FREE(uuids); - return true; -} - - /* * "version" command */ @@ -4880,33 +4569,6 @@ vshCommandOptDomainBy(vshControl *ctl, const vshCmd *cmd, return dom; } -static virSecretPtr -vshCommandOptSecret(vshControl *ctl, const vshCmd *cmd, const char **name) -{ - virSecretPtr secret = NULL; - const char *n = NULL; - const char *optname = "secret"; - - if (!cmd_has_option(ctl, cmd, optname)) - return NULL; - - if (vshCommandOptString(cmd, optname, &n) <= 0) - return NULL; - - vshDebug(ctl, VSH_ERR_DEBUG, - "%s: found option <%s>: %s\n", cmd->def->name, optname, n); - - if (name != NULL) - *name = n; - - secret = virSecretLookupByUUIDString(ctl->conn, n); - - if (secret == NULL) - vshError(ctl, _("failed to get secret '%s'"), n); - - return secret; -} - /* * Executes command(s) and returns return code from last command */ @@ -6493,6 +6155,8 @@ static const vshCmdDef nwfilterCmds[] = { {NULL, NULL, NULL, NULL, 0} }; +#include "virsh-secret.c" + static const vshCmdDef secretCmds[] = { {"secret-define", cmdSecretDefine, opts_secret_define, info_secret_define, 0},