[lvm-devel] dev-peter-config-profiles - config: add support for loading profiles
Peter Rajnoha
prajnoha at fedoraproject.org
Wed Jun 26 14:55:46 UTC 2013
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=070ffe7822089eefac9c4ed867ada0ee45634536
Commit: 070ffe7822089eefac9c4ed867ada0ee45634536
Parent: f15a403a256f033d18bd53f8d155cb2686e02a1c
Author: Peter Rajnoha <prajnoha at redhat.com>
AuthorDate: Tue Jun 25 12:27:04 2013 +0200
Committer: Peter Rajnoha <prajnoha at redhat.com>
CommitterDate: Wed Jun 26 16:53:49 2013 +0200
config: add support for loading profiles
This patch adds --profile arg to lvm cmds and adds config/profile_dir
configuration setting to select the directory where profile are stored
By default it's /etc/lvm/profile.
The profiles are loaded using the new "load_profile" fn and all
profiles are stored in a cmd context withing the new
"struct profile_params":
struct profile_params {
const char *dir;
struct profile *global_profile;
struct dm_list profiles;
};
...where "dir" is the directory with profiles, "global_profile" is
the profile that is set globally via the --profile arg (IOW, not
set per VG/LV basis based on metadata record) and the "profiles"
is the list with loaded profiles.
---
doc/example.conf.in | 3 +
lib/commands/toolcontext.c | 89 +++++++++++++++++++++++++++++++++++++++++-
lib/commands/toolcontext.h | 3 +
lib/config/config.h | 14 +++++++
lib/config/config_settings.h | 1 +
tools/args.h | 1 +
tools/lvmcmdline.c | 13 ++++++-
7 files changed, 122 insertions(+), 2 deletions(-)
diff --git a/doc/example.conf.in b/doc/example.conf.in
index 1620721..9ae754f 100644
--- a/doc/example.conf.in
+++ b/doc/example.conf.in
@@ -23,6 +23,9 @@ config {
# If enabled, any configuration mismatch aborts the LVM2 process.
abort_on_errors = 0
+
+ # Directory where LVM looks for configuration profiles.
+ profile_dir = "@DEFAULT_SYS_DIR@/profiles"
}
# This section allows you to configure which block devices should
diff --git a/lib/commands/toolcontext.c b/lib/commands/toolcontext.c
index 4299d8c..b4658f5 100644
--- a/lib/commands/toolcontext.c
+++ b/lib/commands/toolcontext.c
@@ -597,6 +597,51 @@ static int _load_config_file(struct cmd_context *cmd, const char *tag)
return 1;
}
+struct profile *load_profile(struct cmd_context *cmd, const char *profile_name)
+{
+ static char profile_path[PATH_MAX];
+ struct profile *profile;
+
+ /* Do some sanity checks first. */
+ if (!profile_name || !*profile_name) {
+ log_error("Undefined profile name.");
+ return NULL;
+ }
+
+ if (strchr(profile_name, '/')) {
+ log_error("%s: bad profile name, it contains '/'.", profile_name);
+ return NULL;
+ }
+
+ /* Check if the profile is already loaded... */
+ dm_list_iterate_items(profile, &cmd->profile_params->profiles) {
+ if (!strcmp(profile->name, profile_name))
+ return profile;
+ }
+
+ /* ...if it's not loaded yet, load it and add it to the profile list. */
+ if (dm_snprintf(profile_path, sizeof(profile_path), "%s/%s.profile",
+ cmd->profile_params->dir, profile_name) < 0) {
+ log_error("LVM_SYSTEM_DIR or profile name too long");
+ return NULL;
+ }
+
+ if (!(profile = dm_pool_zalloc(cmd->libmem, sizeof(*profile)))) {
+ log_error("profile allocation failed");
+ return NULL;
+ }
+
+ profile->name = dm_pool_strdup(cmd->libmem, profile_name);
+ if (!(profile->cft = _open_and_read_config_file(profile_path, CONFIG_PROFILE))) {
+ dm_pool_free(cmd->libmem, profile);
+ return_NULL;
+ }
+
+ dm_list_add(&cmd->profile_params->profiles, &profile->list);
+
+ return profile;
+}
+
/* Find and read first config file */
static int _init_lvm_conf(struct cmd_context *cmd)
{
@@ -629,6 +674,34 @@ static int _init_tag_configs(struct cmd_context *cmd)
return 1;
}
+static int _init_profiles(struct cmd_context *cmd)
+{
+ static char default_dir[PATH_MAX];
+ const char *dir;
+ struct profile_params *pp;
+
+ if (!(pp = dm_pool_zalloc(cmd->libmem, sizeof(*pp)))) {
+ log_error("profile_params alloc failed");
+ return 0;
+ }
+
+ if (!(dir = find_config_tree_str(cmd, config_profile_dir_CFG))) {
+ if (dm_snprintf(default_dir, sizeof(default_dir), "%s/%s",
+ cmd->system_dir, DEFAULT_PROFILE_SUBDIR) == -1) {
+ log_error("Couldn't create default profile path '%s/%s'.",
+ cmd->system_dir, DEFAULT_PROFILE_SUBDIR);
+ return 0;
+ }
+ dir = default_dir;
+ }
+
+ pp->dir = dm_pool_strdup(cmd->libmem, dir);
+ dm_list_init(&pp->profiles);
+
+ cmd->profile_params = pp;
+ return 1;
+}
+
static struct dm_config_tree *_merge_config_files(struct cmd_context *cmd, struct dm_config_tree *cft)
{
struct config_tree_list *cfl;
@@ -675,12 +748,14 @@ static void _destroy_config(struct cmd_context *cmd)
{
struct config_tree_list *cfl;
struct dm_config_tree *cft;
+ struct profile *profile;
/*
* Configuration cascade:
- * CONFIG_STRING -> CONFIG_FILE/CONFIG_MERGED_FILES
+ * CONFIG_STRING -> CONFIG_PROFILE -> CONFIG_FILE/CONFIG_MERGED_FILES
*
* CONFIG_STRING - the configuration string passed in command line via '--config'
+ * CONFIG_PROFILE - the profile used or selected via '--profile'
* CONFIG_MERGED_FILES - merged master lvm.conf and tag configurations
* CONFIG_FILE - master lvm.conf only
*/
@@ -695,6 +770,14 @@ static void _destroy_config(struct cmd_context *cmd)
config_destroy(cfl->cft);
dm_list_init(&cmd->config_files);
+ /* CONFIG_PROFILE */
+ if (cmd->profile_params) {
+ remove_config_tree_by_source(cmd, CONFIG_PROFILE);
+ dm_list_iterate_items(profile, &cmd->profile_params->profiles)
+ config_destroy(profile->cft);
+ dm_list_init(&cmd->profile_params->profiles);
+ }
+
/* CONFIG_STRING */
if ((cft = remove_config_tree_by_source(cmd, CONFIG_STRING)))
config_destroy(cft);
@@ -1463,6 +1546,9 @@ struct cmd_context *create_toolcontext(unsigned is_long_lived,
if (!_process_config(cmd))
goto_out;
+ if (!_init_profiles(cmd))
+ goto_out;
+
if (!(cmd->dev_types = create_dev_types(cmd->proc_dir,
find_config_tree_node(cmd, devices_types_CFG))))
goto_out;
@@ -1506,6 +1592,7 @@ out:
cmd = NULL;
}
+
return cmd;
}
diff --git a/lib/commands/toolcontext.h b/lib/commands/toolcontext.h
index f6a09a7..7551245 100644
--- a/lib/commands/toolcontext.h
+++ b/lib/commands/toolcontext.h
@@ -51,6 +51,7 @@ struct config_info {
};
struct dm_config_tree;
+struct profile_params;
struct archive_params;
struct backup_params;
struct arg_values;
@@ -104,6 +105,8 @@ struct cmd_context {
struct config_info current_settings;
struct dm_hash_table *cft_def_hash; /* cft definition hash used for validity check */
+ struct profile_params *profile_params;
+
struct archive_params *archive_params;
struct backup_params *backup_params;
const char *stripe_filler;
diff --git a/lib/config/config.h b/lib/config/config.h
index 2f5cee6..93811fb 100644
--- a/lib/config/config.h
+++ b/lib/config/config.h
@@ -34,6 +34,18 @@ typedef enum {
CONFIG_PROFILE
} config_source_t;
+struct profile {
+ struct dm_list list;
+ const char *name;
+ struct dm_config_tree *cft;
+};
+
+struct profile_params {
+ const char *dir;
+ struct profile *global_profile;
+ struct dm_list profiles;
+};
+
#define CFG_PATH_MAX_LEN 64
/*
@@ -114,6 +126,8 @@ enum {
#undef cfg_array
};
+struct profile *load_profile(struct cmd_context *cmd, const char *profile_name);
+
int config_def_get_path(char *buf, size_t buf_size, int id);
int config_def_check(struct cmd_context *cmd, int force, int skip, int suppress_messages);
diff --git a/lib/config/config_settings.h b/lib/config/config_settings.h
index 6229f2e..65d869b 100644
--- a/lib/config/config_settings.h
+++ b/lib/config/config_settings.h
@@ -68,6 +68,7 @@ cfg_section(tags_CFG_SECTION, "tags", root_CFG_SECTION, 0, vsn(1, 0, 18), NULL)
cfg(config_checks_CFG, "checks", config_CFG_SECTION, 0, CFG_TYPE_BOOL, 1, vsn(2, 2, 99), "Configuration tree check on each LVM command execution.")
cfg(config_abort_on_errors_CFG, "abort_on_errors", config_CFG_SECTION, 0, CFG_TYPE_BOOL, 0, vsn(2,2,99), "Abort LVM command execution if configuration is invalid.")
+cfg(config_profile_dir_CFG, "profile_dir", config_CFG_SECTION, 0, CFG_TYPE_STRING, 0, vsn(2, 2, 99), "Directory with configuration profiles.")
cfg(devices_dir_CFG, "dir", devices_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_DEV_DIR, vsn(1, 0, 0), NULL)
cfg_array(devices_scan_CFG, "scan", devices_CFG_SECTION, 0, CFG_TYPE_STRING, "#S/dev", vsn(1, 0, 0), NULL)
diff --git a/tools/args.h b/tools/args.h
index 2fed97e..cadd211 100644
--- a/tools/args.h
+++ b/tools/args.h
@@ -91,6 +91,7 @@ arg(writemostly_ARG, '\0', "writemostly", string_arg, ARG_GROUPABLE)
arg(writebehind_ARG, '\0', "writebehind", int_arg, 0)
arg(minrecoveryrate_ARG, '\0', "minrecoveryrate", size_kb_arg, 0)
arg(maxrecoveryrate_ARG, '\0', "maxrecoveryrate", size_kb_arg, 0)
+arg(profile_ARG, '\0', "profile", string_arg, 0)
/* Allow some variations */
arg(resizable_ARG, '\0', "resizable", yes_no_arg, 0)
diff --git a/tools/lvmcmdline.c b/tools/lvmcmdline.c
index 51bbcd2..9bf3d93 100644
--- a/tools/lvmcmdline.c
+++ b/tools/lvmcmdline.c
@@ -620,7 +620,8 @@ void lvm_register_commands(void)
debug_ARG, help_ARG, help2_ARG, \
version_ARG, verbose_ARG, \
yes_ARG, \
- quiet_ARG, config_ARG, -1);
+ quiet_ARG, config_ARG, \
+ profile_ARG, -1);
#include "commands.h"
#undef xx
}
@@ -1051,6 +1052,7 @@ int lvm_run_command(struct cmd_context *cmd, int argc, char **argv)
int locking_type;
int monitoring;
struct dm_config_tree *old_cft;
+ struct profile *profile;
init_error_message_produced(0);
@@ -1091,6 +1093,15 @@ int lvm_run_command(struct cmd_context *cmd, int argc, char **argv)
}
}
+ if (arg_count(cmd, profile_ARG)) {
+ if (!(profile = load_profile(cmd, arg_str_value(cmd, profile_ARG, NULL)))) {
+ log_error("Failed to load configuration profile.");
+ return ECMD_FAILED;
+ }
+ log_debug("Setting global configuration profile \"%s\".", profile->name);
+ cmd->profile_params->global_profile = profile;
+ }
+
if ((ret = _get_settings(cmd)))
goto_out;
_apply_settings(cmd);
More information about the lvm-devel
mailing list