Beispiel #1
0
/* Parse replicator site element */
static int _add_site(struct lv_segment *seg,
		     const char *key,
		     const struct dm_config_node *sn)
{
	struct dm_pool *mem = seg->lv->vg->vgmem;
	const struct dm_config_node *cn;
	struct replicator_site *rsite;

	if (!(rsite = _get_site(seg->lv, key)))
		return_0;

	if (!dm_config_find_node(sn, "site_index"))
		return SEG_LOG_ERROR("Mandatory site_index is missing for");

	rsite->state = _get_state(sn, "state", REPLICATOR_STATE_PASSIVE);
	rsite->site_index = _get_config_uint32(sn, "site_index", 0);
	if (rsite->site_index > seg->rsite_index_highest)
		return SEG_LOG_ERROR("site_index=%d > highest_site_index=%d for",
				     rsite->site_index, seg->rsite_index_highest);

	rsite->fall_behind_data = _get_config_uint64(sn, "fall_behind_data", 0);
	rsite->fall_behind_ios = _get_config_uint32(sn, "fall_behind_ios", 0);
	rsite->fall_behind_timeout = _get_config_uint32(sn, "fall_behind_timeout", 0);
	rsite->op_mode = DM_REPLICATOR_SYNC;

	if (rsite->fall_behind_data ||
	    rsite->fall_behind_ios ||
	    rsite->fall_behind_timeout) {
		if (rsite->fall_behind_data && rsite->fall_behind_ios)
			return SEG_LOG_ERROR("Defined both fall_behind_data "
					     "and fall_behind_ios in");

		if (rsite->fall_behind_data && rsite->fall_behind_timeout)
			return SEG_LOG_ERROR("Defined both fall_behind_data "
					     "and fall_behind_timeout in");

		if (rsite->fall_behind_ios && rsite->fall_behind_timeout)
			return SEG_LOG_ERROR("Defined both fall_behind_ios "
					     "and fall_behind_timeout in");

		rsite->op_mode = _get_op_mode(sn, "operation_mode",
					      rsite->op_mode);
	}

	if ((cn = dm_config_find_node(sn, "volume_group"))) {
		if (!cn->v || cn->v->type != DM_CFG_STRING)
			return SEG_LOG_ERROR("volume_group must be a string in");

		if (!(rsite->vg_name = dm_pool_strdup(mem, cn->v->v.str)))
			return_0;

	} else if (rsite->site_index != 0)
		return SEG_LOG_ERROR("volume_group is mandatory for remote site in");

	return 1;
}
Beispiel #2
0
/* Destructively merge a new config tree into an existing one */
int merge_config_tree(struct cmd_context *cmd, struct dm_config_tree *cft,
		      struct dm_config_tree *newdata, config_merge_t merge_type)
{
	struct dm_config_node *root = cft->root;
	struct dm_config_node *cn, *nextn, *oldn, *cn2;
	const struct dm_config_node *tn;
	struct config_source *cs, *csn;

	for (cn = newdata->root; cn; cn = nextn) {
		nextn = cn->sib;
		if (merge_type == CONFIG_MERGE_TYPE_TAGS) {
			/* Ignore tags section */
			if (!strcmp(cn->key, "tags"))
				continue;
			/* If there's a tags node, skip if host tags don't match */
			if ((tn = dm_config_find_node(cn->child, "tags"))) {
				if (!_match_host_tags(&cmd->tags, tn))
					continue;
			}
		}
		if (!(oldn = dm_config_find_node(root, cn->key))) {
			_insert_config_node(&cft->root, cn);
			if (merge_type == CONFIG_MERGE_TYPE_TAGS) {
				/* Remove any "tags" nodes */
				for (cn2 = cn->child; cn2; cn2 = cn2->sib) {
					if (!strcmp(cn2->key, "tags")) {
						cn->child = cn2->sib;
						continue;
					}
					if (cn2->sib && !strcmp(cn2->sib->key, "tags")) {
						cn2->sib = cn2->sib->sib;
						continue;
					}
				}
			}
			continue;
		}
		_merge_section(oldn, cn, merge_type);
	}

	/*
	 * Persistent filter loading is based on timestamp,
	 * so we need to know the newest timestamp to make right decision
	 * whether the .cache isn't older then any of configs
	 */
	cs = dm_config_get_custom(cft);
	csn = dm_config_get_custom(newdata);

	if (cs && csn && (cs->timestamp < csn->timestamp))
		cs->timestamp = csn->timestamp;

	return 1;
}
Beispiel #3
0
static void test_clone(void)
{
	struct dm_config_tree *tree = dm_config_from_string(conf);
	struct dm_config_node *n = dm_config_clone_node(tree, tree->root, 1);
	const struct dm_config_value *value;

	/* Check that the nodes are actually distinct. */
	CU_ASSERT(n != tree->root);
	CU_ASSERT(n->sib != tree->root->sib);
	CU_ASSERT(dm_config_find_node(n, "physical_volumes") != NULL);
	CU_ASSERT(dm_config_find_node(tree->root, "physical_volumes") != NULL);
	CU_ASSERT(dm_config_find_node(n, "physical_volumes") != dm_config_find_node(tree->root, "physical_volumes"));

	CU_ASSERT(dm_config_has_node(n, "id"));
	CU_ASSERT(dm_config_has_node(n, "physical_volumes"));
	CU_ASSERT(dm_config_has_node(n, "physical_volumes/pv0"));
	CU_ASSERT(dm_config_has_node(n, "physical_volumes/pv0/id"));

	CU_ASSERT(!strcmp(dm_config_find_str(n, "id", "foo"), "yada-yada"));
	CU_ASSERT(!strcmp(dm_config_find_str(n, "idt", "foo"), "foo"));

	CU_ASSERT(!strcmp(dm_config_find_str(n, "physical_volumes/pv0/bb", "foo"), "foo"));
	CU_ASSERT(!strcmp(dm_config_find_str(n, "physical_volumes/pv0/id", "foo"), "abcd-efgh"));

	CU_ASSERT(!dm_config_get_uint32(n, "id", NULL));
	CU_ASSERT(dm_config_get_uint32(n, "extent_size", NULL));

	/* FIXME: Currently everything parses as a list, even if it's not */
	// CU_ASSERT(!dm_config_get_list(tree->root, "id", NULL));
	// CU_ASSERT(!dm_config_get_list(tree->root, "extent_size", NULL));

	CU_ASSERT(dm_config_get_list(n, "flags", &value));
	CU_ASSERT(value->next == NULL); /* an empty list */
	CU_ASSERT(dm_config_get_list(n, "status", &value));
	CU_ASSERT(value->next != NULL); /* a non-empty list */

	dm_config_destroy(tree);
}
Beispiel #4
0
/* Destructively merge a new config tree into an existing one */
int merge_config_tree(struct cmd_context *cmd, struct dm_config_tree *cft,
		      struct dm_config_tree *newdata)
{
	struct dm_config_node *root = cft->root;
	struct dm_config_node *cn, *nextn, *oldn, *cn2;
	const struct dm_config_node *tn;

	for (cn = newdata->root; cn; cn = nextn) {
		nextn = cn->sib;
		/* Ignore tags section */
		if (!strcmp(cn->key, "tags"))
			continue;
		/* If there's a tags node, skip if host tags don't match */
		if ((tn = dm_config_find_node(cn->child, "tags"))) {
			if (!_match_host_tags(&cmd->tags, tn))
				continue;
		}
		if (!(oldn = dm_config_find_node(root, cn->key))) {
			_insert_config_node(&cft->root, cn);
			/* Remove any "tags" nodes */
			for (cn2 = cn->child; cn2; cn2 = cn2->sib) {
				if (!strcmp(cn2->key, "tags")) {
					cn->child = cn2->sib;
					continue;
				}
				if (cn2->sib && !strcmp(cn2->sib->key, "tags")) {
					cn2->sib = cn2->sib->sib;
					continue;
				}
			}
			continue;
		}
		_merge_section(oldn, cn);
	}

	return 1;
}
Beispiel #5
0
/*
 * Merge section cn2 into section cn1 (which has the same name)
 * overwriting any existing cn1 nodes with matching names.
 */
static void _merge_section(struct dm_config_node *cn1, struct dm_config_node *cn2,
			   config_merge_t merge_type)
{
	struct dm_config_node *cn, *nextn, *oldn;
	struct dm_config_value *cv;

	for (cn = cn2->child; cn; cn = nextn) {
		nextn = cn->sib;

		if (merge_type == CONFIG_MERGE_TYPE_TAGS) {
			/* Skip "tags" */
			if (!strcmp(cn->key, "tags"))
				continue;
		}

		/* Subsection? */
		if (!cn->v)
			/* Ignore - we don't have any of these yet */
			continue;
		/* Not already present? */
		if (!(oldn = dm_config_find_node(cn1->child, cn->key))) {
			_insert_config_node(&cn1->child, cn);
			continue;
		}
		if (merge_type == CONFIG_MERGE_TYPE_TAGS) {
			/* Merge certain value lists */
			if ((!strcmp(cn1->key, "activation") &&
			     !strcmp(cn->key, "volume_list")) ||
			    (!strcmp(cn1->key, "devices") &&
			     (!strcmp(cn->key, "filter") || !strcmp(cn->key, "types")))) {
				cv = cn->v;
				while (cv->next)
					cv = cv->next;
				cv->next = oldn->v;
			}
		}

		/* Replace values */
		oldn->v = cn->v;
	}
}
Beispiel #6
0
int config_write(struct dm_config_tree *cft, const char *file,
		 int argc, char **argv)
{
	const struct dm_config_node *cn;
	int r = 1;
	FILE *fp = NULL;

	if (!file) {
		fp = stdout;
		file = "stdout";
	} else if (!(fp = fopen(file, "w"))) {
		log_sys_error("open", file);
		return 0;
	}

	log_verbose("Dumping configuration to %s", file);
	if (!argc) {
		if (!dm_config_write_node(cft->root, _putline_fn, fp)) {
			log_error("Failure while writing to %s", file);
			r = 0;
		}
	} else while (argc--) {
		if ((cn = dm_config_find_node(cft->root, *argv))) {
			if (!dm_config_write_node(cn, _putline_fn, fp)) {
				log_error("Failure while writing to %s", file);
				r = 0;
			}
		} else {
			log_error("Configuration node %s not found", *argv);
			r = 0;
		}
		argv++;
	}

	if (fp && dm_fclose(fp)) {
		stack;
		r = 0;
	}

	return r;
}
Beispiel #7
0
int main(int argc, char **argv)
{
	daemon_reply reply;
	char *cmd;
	char *uuid;
	char *name;
	int val;
	int ver;

	if (argc < 2) {
		printf("lvmetactl dump\n");
		printf("lvmetactl pv_list\n");
		printf("lvmetactl vg_list\n");
		printf("lvmetactl vg_lookup_name <name>\n");
		printf("lvmetactl vg_lookup_uuid <uuid>\n");
		printf("lvmetactl pv_lookup_uuid <uuid>\n");
		printf("lvmetactl set_global_invalid 0|1\n");
		printf("lvmetactl get_global_invalid\n");
		printf("lvmetactl set_vg_version <uuid> <name> <version>\n");
		printf("lvmetactl vg_lock_type <uuid>\n");
		return -1;
	}

	cmd = argv[1];

	h = lvmetad_open(NULL);

	if (!strcmp(cmd, "dump")) {
		reply = daemon_send_simple(h, "dump",
					   "token = %s", "skip",
					   NULL);
		printf("%s\n", reply.buffer.mem);

	} else if (!strcmp(cmd, "pv_list")) {
		reply = daemon_send_simple(h, "pv_list",
					   "token = %s", "skip",
					   NULL);
		printf("%s\n", reply.buffer.mem);

	} else if (!strcmp(cmd, "vg_list")) {
		reply = daemon_send_simple(h, "vg_list",
					   "token = %s", "skip",
					   NULL);
		printf("%s\n", reply.buffer.mem);

	} else if (!strcmp(cmd, "set_global_invalid")) {
		if (argc < 3) {
			printf("set_global_invalid 0|1\n");
			return -1;
		}
		val = atoi(argv[2]);

		reply = daemon_send_simple(h, "set_global_info",
					   "global_invalid = %d", val,
					   "token = %s", "skip",
					   NULL);
		print_reply(reply);

	} else if (!strcmp(cmd, "get_global_invalid")) {
		reply = daemon_send_simple(h, "get_global_info",
					   "token = %s", "skip",
					   NULL);
		printf("%s\n", reply.buffer.mem);

	} else if (!strcmp(cmd, "set_vg_version")) {
		if (argc < 5) {
			printf("set_vg_version <uuid> <name> <ver>\n");
			return -1;
		}
		uuid = argv[2];
		name = argv[3];
		ver = atoi(argv[4]);

		if ((strlen(uuid) == 1) && (uuid[0] == '-'))
			uuid = NULL;
		if ((strlen(name) == 1) && (name[0] == '-'))
			name = NULL;

		if (uuid && name) {
			reply = daemon_send_simple(h, "set_vg_info",
						   "uuid = %s", uuid,
						   "name = %s", name,
						   "version = %d", ver,
						    "token = %s", "skip",
						    NULL);
		} else if (uuid) {
			reply = daemon_send_simple(h, "set_vg_info",
						   "uuid = %s", uuid,
						   "version = %d", ver,
						    "token = %s", "skip",
						    NULL);
		} else if (name) {
			reply = daemon_send_simple(h, "set_vg_info",
						   "name = %s", name,
						   "version = %d", ver,
						    "token = %s", "skip",
						    NULL);
		} else {
			printf("name or uuid required\n");
			return -1;
		}

		print_reply(reply);

	} else if (!strcmp(cmd, "vg_lookup_name")) {
		if (argc < 3) {
			printf("vg_lookup_name <name>\n");
			return -1;
		}
		name = argv[2];

		reply = daemon_send_simple(h, "vg_lookup",
					   "name = %s", name,
					   "token = %s", "skip",
					   NULL);
		printf("%s\n", reply.buffer.mem);

	} else if (!strcmp(cmd, "vg_lookup_uuid")) {
		if (argc < 3) {
			printf("vg_lookup_uuid <uuid>\n");
			return -1;
		}
		uuid = argv[2];

		reply = daemon_send_simple(h, "vg_lookup",
					   "uuid = %s", uuid,
					   "token = %s", "skip",
					   NULL);
		printf("%s\n", reply.buffer.mem);

	} else if (!strcmp(cmd, "vg_lock_type")) {
		struct dm_config_node *metadata;
		const char *lock_type;

		if (argc < 3) {
			printf("vg_lock_type <uuid>\n");
			return -1;
		}
		uuid = argv[2];

		reply = daemon_send_simple(h, "vg_lookup",
					   "uuid = %s", uuid,
					   "token = %s", "skip",
					   NULL);
		/* printf("%s\n", reply.buffer.mem); */

		metadata = dm_config_find_node(reply.cft->root, "metadata");
		if (!metadata) {
			printf("no metadata\n");
			goto out;
		}

		lock_type = dm_config_find_str(metadata, "metadata/lock_type", NULL);
		if (!lock_type) {
			printf("no lock_type\n");
			goto out;
		}
		printf("lock_type %s\n", lock_type);

	} else if (!strcmp(cmd, "pv_lookup_uuid")) {
		if (argc < 3) {
			printf("pv_lookup_uuid <uuid>\n");
			return -1;
		}
		uuid = argv[2];

		reply = daemon_send_simple(h, "pv_lookup",
					   "uuid = %s", uuid,
					   "token = %s", "skip",
					   NULL);
		printf("%s\n", reply.buffer.mem);

	} else {
		printf("unknown command\n");
		goto out_close;
	}
out:
	daemon_reply_destroy(reply);
out_close:
	daemon_close(h);
	return 0;
}