/*
* Copyright (C) 2015-2017 Red Hat, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
* Author: Gris Ge
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define FAIL(rc, out, ...) \
do { \
rc = EXIT_FAILURE; \
fprintf(stderr, "FAIL: "__VA_ARGS__ ); \
goto out; \
} while(0)
#define PASS(...) fprintf(stdout, "PASS: "__VA_ARGS__ );
#define FILE_NAME_SIZE 256
#define TMO 60000 /* Forcing timeout to 60 seconds */
int test_paths(struct dmmp_path_group *mp_pg)
{
struct dmmp_path **mp_ps = NULL;
uint32_t mp_p_count = 0;
uint32_t i = 0;
const char *blk_name = NULL;
int rc = EXIT_SUCCESS;
dmmp_path_array_get(mp_pg, &mp_ps, &mp_p_count);
if (mp_p_count == 0)
FAIL(rc, out, "dmmp_path_array_get(): Got no path\n");
for (i = 0; i < mp_p_count; ++i) {
blk_name = dmmp_path_blk_name_get(mp_ps[i]);
if (blk_name == NULL)
FAIL(rc, out, "dmmp_path_blk_name_get(): Got NULL\n");
PASS("dmmp_path_blk_name_get(): %s\n", blk_name);
PASS("dmmp_path_status_get(): %" PRIu32 " -- %s\n",
dmmp_path_status_get(mp_ps[i]),
dmmp_path_status_str(dmmp_path_status_get(mp_ps[i])));
}
out:
return rc;
}
int test_path_groups(struct dmmp_mpath *dmmp_mp)
{
struct dmmp_path_group **dmmp_pgs = NULL;
uint32_t dmmp_pg_count = 0;
uint32_t i = 0;
int rc = EXIT_SUCCESS;
dmmp_path_group_array_get(dmmp_mp, &dmmp_pgs, &dmmp_pg_count);
if ((dmmp_pg_count == 0) && (dmmp_pgs != NULL))
FAIL(rc, out, "dmmp_path_group_array_get(): mp_pgs is not NULL "
"but mp_pg_count is 0\n");
if ((dmmp_pg_count != 0) && (dmmp_pgs == NULL))
FAIL(rc, out, "dmmp_path_group_array_get(): mp_pgs is NULL "
"but mp_pg_count is not 0\n");
if (dmmp_pg_count == 0)
FAIL(rc, out, "dmmp_path_group_array_get(): "
"Got 0 path group\n");
PASS("dmmp_path_group_array_get(): Got %" PRIu32 " path groups\n",
dmmp_pg_count);
for (i = 0; i < dmmp_pg_count; ++i) {
PASS("dmmp_path_group_id_get(): %" PRIu32 "\n",
dmmp_path_group_id_get(dmmp_pgs[i]));
PASS("dmmp_path_group_priority_get(): %" PRIu32 "\n",
dmmp_path_group_priority_get(dmmp_pgs[i]));
PASS("dmmp_path_group_status_get(): %" PRIu32 " -- %s\n",
dmmp_path_group_status_get(dmmp_pgs[i]),
dmmp_path_group_status_str
(dmmp_path_group_status_get(dmmp_pgs[i])));
PASS("dmmp_path_group_selector_get(): %s\n",
dmmp_path_group_selector_get(dmmp_pgs[i]));
rc = test_paths(dmmp_pgs[i]);
if (rc != 0)
goto out;
}
out:
return rc;
}
int main(int argc, char *argv[])
{
struct dmmp_context *ctx = NULL;
struct dmmp_mpath **dmmp_mps = NULL;
uint32_t dmmp_mp_count = 0;
uint32_t old_dmmp_mp_count = 0;
const char *name = NULL;
const char *wwid = NULL;
const char *kdev = NULL;
uint32_t i = 0;
int rc = EXIT_SUCCESS;
const char *old_name = NULL;
bool found = false;
ctx = dmmp_context_new();
dmmp_context_log_priority_set(ctx, DMMP_LOG_PRIORITY_DEBUG);
dmmp_context_userdata_set(ctx, ctx);
dmmp_context_userdata_set(ctx, NULL);
dmmp_context_timeout_set(ctx, TMO);
if (dmmp_context_timeout_get(ctx) != TMO)
FAIL(rc, out, "dmmp_context_timeout_set(): Failed to set "
"timeout to %u\n", TMO);
if (dmmp_mpath_array_get(ctx, &dmmp_mps, &dmmp_mp_count) != 0)
FAIL(rc, out, "dmmp_mpath_array_get() failed: %s\n",
dmmp_last_error_msg(ctx));
if (dmmp_mp_count == 0)
FAIL(rc, out, "dmmp_mpath_array_get(): "
"Got no multipath devices\n");
PASS("dmmp_mpath_array_get(): Got %" PRIu32 " mpath\n", dmmp_mp_count);
for (i = 0; i < dmmp_mp_count; ++i) {
name = dmmp_mpath_name_get(dmmp_mps[i]);
wwid = dmmp_mpath_wwid_get(dmmp_mps[i]);
kdev = dmmp_mpath_kdev_name_get(dmmp_mps[i]);
if ((name == NULL) ||(wwid == NULL) || (kdev == NULL))
FAIL(rc, out,
"dmmp_mpath_array_get(): Got NULL name or wwid");
PASS("dmmp_mpath_array_get(): Got mpath(%s): %s %s\n",
kdev, name, wwid);
rc = test_path_groups(dmmp_mps[i]);
if (rc != 0)
goto out;
}
old_name = strdup(name);
if (old_name == NULL)
FAIL(rc, out, "strdup(): no memory\n");
old_dmmp_mp_count = dmmp_mp_count;
dmmp_mpath_array_free(dmmp_mps, dmmp_mp_count);
if (dmmp_flush_mpath(ctx, old_name) != DMMP_OK)
FAIL(rc, out, "dmmp_flush_mpath(): failed %s\n",
dmmp_last_error_msg(ctx));
PASS("dmmp_flush_mpath(): OK\n");
if (dmmp_reconfig(ctx) != DMMP_OK)
FAIL(rc, out, "dmmp_reconfig() failed: %s\n",
dmmp_last_error_msg(ctx));
PASS("dmmp_reconfig(): OK\n");
if (dmmp_mpath_array_get(ctx, &dmmp_mps, &dmmp_mp_count) != 0)
FAIL(rc, out, "dmmp_mpath_array_get() failed: %s\n",
dmmp_last_error_msg(ctx));
if (dmmp_mp_count == 0)
FAIL(rc, out, "dmmp_mpath_array_get(): "
"Got no multipath devices\n");
if (dmmp_mp_count != old_dmmp_mp_count)
FAIL(rc, out, "Got different mpath count after reconfig: "
"old %" PRIu32 ", new %" PRIu32 "\n", old_dmmp_mp_count,
dmmp_mp_count);
for (i = 0; i < dmmp_mp_count; ++i) {
if (strcmp(old_name, dmmp_mpath_name_get(dmmp_mps[i])) == 0) {
found = true;
break;
}
}
if (found == false)
FAIL(rc, out, "dmmp_reconfig() does not recreate deleted "
"mpath %s\n", old_name);
out:
dmmp_context_free(ctx);
exit(rc);
}