[libvirt] [PATCH] storage: netfs: Handle backend errors
Ján Tomko
jtomko at redhat.com
Mon Apr 14 16:47:26 UTC 2014
On 04/09/2014 08:42 PM, John Ferlan wrote:
> Commit id '18642d10' caused a virt-test regression for NFS backend
> storage error path checks when running the command:
>
> 'virsh find-storage-pool-sources-as netfs Unknown '
>
> when the host did not have Gluster installed. Prior to the commit,
> the test would fail with the error:
>
> error: internal error: Child process (/usr/sbin/showmount --no-headers
> --exports Unknown) unexpected exit status 1: clnt_create: RPC: Unknown host
>
> After the commit, the error would be ignored, the call would succeed,
> and an empty list of pool sources returned. This was tucked into the
> commit message as an expected outcome.
>
> When the target host does not have a GLUSTER_CLI this is a regression
> over the previous release. Furthermore, even if Gluster CLI was present,
> but had a failure to get devices, the API would return a failure even if
> the NFS backend had found devices.
>
> Add code to handle the error conditions.
> - If NFS fails
> - If there is no Gluster CLI, then jump to cleanup/failure.
> - If there is a Gluster CLI, then message the NFS
> failure and continue with the Gluster checks.
>
> - If Gluster fails
> - If NFS had failed, then jump to cleanup/failure.
> - Message the Gluster failure and continue on.
>
> - If only one fails, fetch and return a list of source devices
> even if it's empty
>
> Signed-off-by: John Ferlan <jferlan at redhat.com>
> ---
> src/storage/storage_backend.c | 14 +++++++++++++
> src/storage/storage_backend.h | 1 +
> src/storage/storage_backend_fs.c | 43 +++++++++++++++++++++++++++++++++++-----
> 3 files changed, 53 insertions(+), 5 deletions(-)
>
> diff --git a/src/storage/storage_backend.c b/src/storage/storage_backend.c
> index b56fefe..4d73902 100644
> --- a/src/storage/storage_backend.c
> +++ b/src/storage/storage_backend.c
> @@ -1643,6 +1643,13 @@ virStorageBackendStablePath(virStoragePoolObjPtr pool,
> }
>
> #ifdef GLUSTER_CLI
> +bool
> +virStorageBackendHaveGlusterCLI(void)
> +{
> + return true;
> +}
> +
> +
> int
> virStorageBackendFindGlusterPoolSources(const char *host,
> int pooltype,
> @@ -1721,6 +1728,13 @@ virStorageBackendFindGlusterPoolSources(const char *host,
> return ret;
> }
> #else /* #ifdef GLUSTER_CLI */
> +bool
> +virStorageBackendHaveGlusterCLI(void)
> +{
> + return false;
> +}
> +
> +
> int
> virStorageBackendFindGlusterPoolSources(const char *host ATTRIBUTE_UNUSED,
> int pooltype ATTRIBUTE_UNUSED,
IMHO it's more readable to use GLUSTER_CLI directly, since we're not doing any
runtime detection.
> diff --git a/src/storage/storage_backend.h b/src/storage/storage_backend.h
> index 4f95000..41eed97 100644
> --- a/src/storage/storage_backend.h
> +++ b/src/storage/storage_backend.h
> @@ -87,6 +87,7 @@ int virStorageBackendFindFSImageTool(char **tool);
> virStorageBackendBuildVolFrom
> virStorageBackendFSImageToolTypeToFunc(int tool_type);
>
> +bool virStorageBackendHaveGlusterCLI(void);
> int virStorageBackendFindGlusterPoolSources(const char *host,
> int pooltype,
> virStoragePoolSourceListPtr list);
> diff --git a/src/storage/storage_backend_fs.c b/src/storage/storage_backend_fs.c
> index 4e4a7ae..f3d4a6d 100644
> --- a/src/storage/storage_backend_fs.c
> +++ b/src/storage/storage_backend_fs.c
> @@ -238,9 +238,11 @@ virStorageBackendFileSystemNetFindPoolSourcesFunc(char **const groups,
> }
>
>
> -static void
> +static int
> virStorageBackendFileSystemNetFindNFSPoolSources(virNetfsDiscoverState *state)
> {
> + int ret = -1;
> +
> /*
> * # showmount --no-headers -e HOSTNAME
> * /tmp *
> @@ -267,9 +269,13 @@ virStorageBackendFileSystemNetFindNFSPoolSources(virNetfsDiscoverState *state)
> if (virCommandRunRegex(cmd, 1, regexes, vars,
> virStorageBackendFileSystemNetFindPoolSourcesFunc,
> state, NULL) < 0)
> - virResetLastError();
> + goto cleanup;
>
> + ret = 0;
> +
> + cleanup:
> virCommandFree(cmd);
> + return ret;
> }
>
>
> @@ -289,6 +295,7 @@ virStorageBackendFileSystemNetFindPoolSources(virConnectPtr conn ATTRIBUTE_UNUSE
> virStoragePoolSourcePtr source = NULL;
> char *ret = NULL;
> size_t i;
> + bool failNFS = false;
>
> virCheckFlags(0, NULL);
>
> @@ -310,12 +317,38 @@ virStorageBackendFileSystemNetFindPoolSources(virConnectPtr conn ATTRIBUTE_UNUSE
>
> state.host = source->hosts[0].name;
>
> - virStorageBackendFileSystemNetFindNFSPoolSources(&state);
> + if (virStorageBackendFileSystemNetFindNFSPoolSources(&state) < 0) {
> + virErrorPtr err;
> + /* If no Gluster CLI, then force error right here */
> + if (!virStorageBackendHaveGlusterCLI())
> + goto cleanup;
> +
> + /* If we have a Gluster CLI, then message the error, clean it out,
> + * and move onto the Gluster code
> + */
> + err = virGetLastError();
> + VIR_ERROR(_("Failed to get NFS pool sources: '%s'"),
> + err != NULL ? err->message: _("unknown error"));
This takes the last logged error and logs it again with a prefix.
> + virResetLastError();
IMO we can leave the error set even if we return 0.
> + failNFS = true;
> + }
>
> if (virStorageBackendFindGlusterPoolSources(state.host,
> VIR_STORAGE_POOL_NETFS_GLUSTERFS,
> - &state.list) < 0)
> - goto cleanup;
> + &state.list) < 0) {
> + virErrorPtr err;
> + /* If NFS failed as well, then force the error right here */
> + if (failNFS)
> + goto cleanup;
> +
> + /* Otherwise, NFS passed, so we message the Gluster error, clean
> + * it out, and generate the source list (even if it's empty)
> + */
FindGlusterPoolSources doesn't report errors when the command returns non-zero.
> + err = virGetLastError();
> + VIR_ERROR(_("Failed to get Gluster pool sources: '%s'"),
> + err != NULL ? err->message: _("unknown error"));
> + virResetLastError();
> + }
>
The whole hunk would IMHO look simpler as:
bool fail = false;
if (FindNFSPoolSources() < 0)
fail = true;
#ifdef GLUSTER_CLI
if (FindGlusterPoolSources() < 0)
fail = true;
else
fail = false;
#endif
if (fail)
goto cleanup;
/* optionally */
else
virResetLastError();
(Though if we add more network backends, we would need a virBitmap to store
all the fails :-))
Jan
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: OpenPGP digital signature
URL: <http://listman.redhat.com/archives/libvir-list/attachments/20140414/b22d4a3b/attachment-0001.sig>
More information about the libvir-list
mailing list