Merge pull request #1057 from jfckm/standby-load-config
Standby load config
This commit is contained in:
commit
1742841ee3
@ -967,9 +967,8 @@ int start_cache(uint16_t cache_id, unsigned int cache_init,
|
||||
{
|
||||
int fd = 0;
|
||||
struct kcas_start_cache cmd;
|
||||
struct cache_device **caches;
|
||||
struct cache_device *cache;
|
||||
int i, status, caches_count;
|
||||
int i, status;
|
||||
double min_free_ram_gb;
|
||||
|
||||
/* check if cache device given exists */
|
||||
@ -984,21 +983,6 @@ int start_cache(uint16_t cache_id, unsigned int cache_init,
|
||||
if (fd == -1)
|
||||
return FAILURE;
|
||||
|
||||
if (cache_id == 0) {
|
||||
cache_id = 1;
|
||||
caches = get_cache_devices(&caches_count, false);
|
||||
if (caches != NULL) {
|
||||
psort(caches, caches_count, sizeof(struct cache_device*), caches_compare);
|
||||
for (i = 0; i < caches_count; ++i) {
|
||||
if (caches[i]->id == cache_id) {
|
||||
cache_id += 1;
|
||||
}
|
||||
}
|
||||
|
||||
free_cache_devices_list(caches, caches_count);
|
||||
}
|
||||
}
|
||||
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
|
||||
cmd.cache_id = cache_id;
|
||||
@ -1014,9 +998,12 @@ int start_cache(uint16_t cache_id, unsigned int cache_init,
|
||||
cmd.line_size = line_size;
|
||||
cmd.force = (uint8_t)force;
|
||||
|
||||
if (run_ioctl_interruptible_retry(fd, KCAS_IOCTL_START_CACHE, &cmd,
|
||||
"Starting cache", cache_id, OCF_CORE_ID_INVALID) < 0) {
|
||||
status = run_ioctl_interruptible_retry(fd, KCAS_IOCTL_START_CACHE, &cmd,
|
||||
"Starting cache", cache_id, OCF_CORE_ID_INVALID);
|
||||
cache_id = cmd.cache_id;
|
||||
if (status < 0) {
|
||||
close(fd);
|
||||
|
||||
if (cmd.ext_err_code == OCF_ERR_NO_FREE_RAM) {
|
||||
min_free_ram_gb = cmd.min_free_ram;
|
||||
min_free_ram_gb /= GiB;
|
||||
@ -3014,7 +3001,7 @@ int standby_load(int cache_id, ocf_cache_line_size_t line_size,
|
||||
return start_cache(cache_id,
|
||||
CACHE_INIT_STANDBY_LOAD,
|
||||
cache_device,
|
||||
ocf_cache_mode_default,
|
||||
ocf_cache_mode_none,
|
||||
line_size,
|
||||
0);
|
||||
}
|
||||
|
@ -406,11 +406,17 @@ int handle_start()
|
||||
{
|
||||
int status;
|
||||
|
||||
if (command_args_values.state == CACHE_INIT_LOAD && command_args_values.force) {
|
||||
cas_printf(LOG_ERR, "Use of 'load' and 'force' simultaneously is forbidden.\n");
|
||||
if (command_args_values.state == CACHE_INIT_LOAD) {
|
||||
if (command_args_values.force ||
|
||||
command_args_values.line_size != ocf_cache_line_size_none ||
|
||||
command_args_values.cache_mode != ocf_cache_mode_none ||
|
||||
command_args_values.cache_id != OCF_CACHE_ID_INVALID) {
|
||||
cas_printf(LOG_ERR, "Use of 'load' with 'force', 'cache-id',"
|
||||
" 'cache-mode' or 'cache-line-size'"
|
||||
" simultaneously is forbidden.\n");
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
} else {
|
||||
if (command_args_values.line_size == ocf_cache_line_size_none) {
|
||||
command_args_values.line_size = ocf_cache_line_size_default;
|
||||
}
|
||||
@ -418,6 +424,7 @@ int handle_start()
|
||||
if (command_args_values.cache_mode == ocf_cache_mode_none) {
|
||||
command_args_values.cache_mode = ocf_cache_mode_default;
|
||||
}
|
||||
}
|
||||
|
||||
if (validate_cache_path(command_args_values.cache_device) == FAILURE)
|
||||
return FAILURE;
|
||||
@ -1473,7 +1480,7 @@ int io_class_is_missing() {
|
||||
/* Option is set, check if this option is allowed */
|
||||
mask = (1 << io_class_params.subcmd);
|
||||
if (0 == (mask & iter->priv)) {
|
||||
cas_printf(LOG_INFO, "Option '%s' is not allowed\n", option_name);
|
||||
cas_printf(LOG_ERR, "Option '%s' is not allowed\n", option_name);
|
||||
result = -1;
|
||||
}
|
||||
|
||||
@ -1481,7 +1488,7 @@ int io_class_is_missing() {
|
||||
/* Option is missing, check if it is required for this sub-command*/
|
||||
mask = (1 << io_class_params.subcmd) | (1 << io_class_opt_flag_required);
|
||||
if (mask == (iter->priv & mask)) {
|
||||
cas_printf(LOG_INFO, "Option '%s' is missing\n", option_name);
|
||||
cas_printf(LOG_ERR, "Option '%s' is missing\n", option_name);
|
||||
result = -1;
|
||||
}
|
||||
}
|
||||
@ -1741,12 +1748,12 @@ int script_command_is_valid() {
|
||||
|
||||
if (option_is_set) {
|
||||
if (!is_option_allowed(option_id)) {
|
||||
cas_printf(LOG_INFO, "Option '%s' is not allowed\n", option_name);
|
||||
cas_printf(LOG_ERR, "Option '%s' is not allowed\n", option_name);
|
||||
result = FAILURE;
|
||||
}
|
||||
} else {
|
||||
if (is_option_required(option_id)) {
|
||||
cas_printf(LOG_INFO, "Option '%s' is missing\n", option_name);
|
||||
cas_printf(LOG_ERR, "Option '%s' is missing\n", option_name);
|
||||
result = FAILURE;
|
||||
}
|
||||
}
|
||||
@ -1926,7 +1933,6 @@ static cli_option standby_params_options[] = {
|
||||
.args_count = 1,
|
||||
.arg = "ID",
|
||||
.priv = (1 << standby_opt_subcmd_init)
|
||||
| (1 << standby_opt_subcmd_load)
|
||||
| (1 << standby_opt_subcmd_detach)
|
||||
| (1 << standby_opt_subcmd_activate)
|
||||
| (1 << standby_opt_flag_required),
|
||||
@ -1941,7 +1947,6 @@ static cli_option standby_params_options[] = {
|
||||
.args_count = 1,
|
||||
.arg = "NUMBER",
|
||||
.priv = (1 << standby_opt_subcmd_init)
|
||||
| (1 << standby_opt_subcmd_load)
|
||||
| (1 << standby_opt_flag_required),
|
||||
.flags = CLI_OPTION_DEFAULT_INT,
|
||||
.default_value = ocf_cache_line_size_default / KiB,
|
||||
@ -2053,7 +2058,7 @@ int standby_is_missing() {
|
||||
/* Option is set, check if this option is allowed */
|
||||
mask = (1 << standby_params.subcmd);
|
||||
if (0 == (mask & iter->priv)) {
|
||||
cas_printf(LOG_INFO, "Option '%s' is not allowed\n", option_name);
|
||||
cas_printf(LOG_ERR, "Option '%s' is not allowed\n", option_name);
|
||||
result = -1;
|
||||
}
|
||||
|
||||
@ -2061,7 +2066,7 @@ int standby_is_missing() {
|
||||
/* Option is missing, check if it is required for this sub-command*/
|
||||
mask = (1 << standby_params.subcmd) | (1 << standby_opt_flag_required);
|
||||
if (mask == (iter->priv & mask)) {
|
||||
cas_printf(LOG_INFO, "Option '%s' is missing\n", option_name);
|
||||
cas_printf(LOG_ERR, "Option '%s' is missing\n", option_name);
|
||||
result = -1;
|
||||
}
|
||||
}
|
||||
@ -2078,6 +2083,16 @@ int standby_handle() {
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
if (standby_params.subcmd == standby_opt_subcmd_load &&
|
||||
(standby_params.force ||
|
||||
standby_params.line_size != ocf_cache_line_size_none ||
|
||||
standby_params.cache_id != OCF_CACHE_ID_INVALID)) {
|
||||
cas_printf(LOG_ERR, "Use of 'load' with 'force', 'cache-id'"
|
||||
" or 'cache-line-size' simultaneously is"
|
||||
" forbidden.\n");
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
/* Check if all required options are set */
|
||||
if (standby_is_missing()) {
|
||||
return FAILURE;
|
||||
|
@ -1839,7 +1839,6 @@ int cache_mngt_prepare_cache_device_cfg(struct ocf_mngt_cache_device_config *cfg
|
||||
&cfg->volume_type);
|
||||
}
|
||||
|
||||
|
||||
int cache_mngt_prepare_cache_cfg(struct ocf_mngt_cache_config *cfg,
|
||||
struct ocf_mngt_cache_attach_config *attach_cfg,
|
||||
struct kcas_start_cache *cmd)
|
||||
@ -1851,7 +1850,25 @@ int cache_mngt_prepare_cache_cfg(struct ocf_mngt_cache_config *cfg,
|
||||
if (!cmd)
|
||||
return -OCF_ERR_INVAL;
|
||||
|
||||
if (cmd->cache_id == OCF_CACHE_ID_INVALID) {
|
||||
if (cmd->init_cache == CACHE_INIT_LOAD ||
|
||||
cmd->init_cache == CACHE_INIT_STANDBY_LOAD) {
|
||||
if (cmd->cache_id != OCF_CACHE_ID_INVALID) {
|
||||
printk(KERN_WARNING "Specifying cache id while loading "
|
||||
"cache is forbidden\n");
|
||||
return -OCF_ERR_INVAL;
|
||||
}
|
||||
|
||||
if (cmd->line_size != ocf_cache_line_size_none) {
|
||||
printk(KERN_WARNING "Specifying cache line size while "
|
||||
"loading cache is forbidden\n");
|
||||
return -OCF_ERR_INVAL;
|
||||
}
|
||||
if (cmd->caching_mode != ocf_cache_mode_none) {
|
||||
printk(KERN_WARNING "Specifying cache mode while "
|
||||
"loading cache is forbidden\n");
|
||||
return -OCF_ERR_INVAL;
|
||||
}
|
||||
} else if (cmd->cache_id == OCF_CACHE_ID_INVALID) {
|
||||
cache_id = find_free_cache_id(cas_ctx);
|
||||
if (cache_id == OCF_CACHE_ID_INVALID)
|
||||
return -OCF_ERR_INVAL;
|
||||
@ -2043,39 +2060,47 @@ static int _cache_mngt_cache_priv_init(ocf_cache_t cache)
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct cache_mngt_check_metadata_context {
|
||||
struct cache_mngt_probe_metadata_context {
|
||||
struct completion cmpl;
|
||||
char *cache_name;
|
||||
int *result;
|
||||
|
||||
char *cache_name_meta;
|
||||
ocf_cache_mode_t *cache_mode_meta;
|
||||
ocf_cache_line_size_t *cache_line_size_meta;
|
||||
};
|
||||
|
||||
static void cache_mngt_check_metadata_end(void *priv, int error,
|
||||
static void cache_mngt_probe_metadata_end(void *priv, int error,
|
||||
struct ocf_metadata_probe_status *status)
|
||||
{
|
||||
struct cache_mngt_check_metadata_context *context = priv;
|
||||
struct cache_mngt_probe_metadata_context *context = priv;
|
||||
|
||||
*context->result = error;
|
||||
|
||||
if (error == -OCF_ERR_NO_METADATA) {
|
||||
printk(KERN_ERR "No cache metadata found!\n");
|
||||
goto err;
|
||||
} else if (error == -OCF_ERR_METADATA_VER) {
|
||||
printk(KERN_ERR "Cache metadata version mismatch\n");
|
||||
goto err;
|
||||
} else if (error) {
|
||||
printk(KERN_ERR "Failed to load cache metadata!\n");
|
||||
} else if (strncmp(status->cache_name, context->cache_name,
|
||||
OCF_CACHE_NAME_SIZE)) {
|
||||
*context->result = -OCF_ERR_CACHE_NAME_MISMATCH;
|
||||
printk(KERN_ERR "Loaded cache name is invalid: %s!\n",
|
||||
status->cache_name);
|
||||
goto err;
|
||||
}
|
||||
|
||||
strlcpy(context->cache_name_meta, status->cache_name,
|
||||
OCF_CACHE_NAME_SIZE);
|
||||
*(context->cache_mode_meta) = status->cache_mode;
|
||||
*(context->cache_line_size_meta) = status->cache_line_size;
|
||||
err:
|
||||
complete(&context->cmpl);
|
||||
}
|
||||
|
||||
static int _cache_mngt_check_metadata(struct ocf_mngt_cache_config *cfg,
|
||||
char *cache_path_name)
|
||||
static int _cache_mngt_probe_metadata(char *cache_path_name,
|
||||
char *cache_name_meta, ocf_cache_mode_t *cache_mode_meta,
|
||||
ocf_cache_line_size_t *cache_line_size_meta)
|
||||
{
|
||||
struct cache_mngt_check_metadata_context context;
|
||||
struct cache_mngt_probe_metadata_context context;
|
||||
struct block_device *bdev;
|
||||
ocf_volume_t volume;
|
||||
char holder[] = "CAS CHECK METADATA\n";
|
||||
@ -2094,10 +2119,12 @@ static int _cache_mngt_check_metadata(struct ocf_mngt_cache_config *cfg,
|
||||
goto out_bdev;
|
||||
|
||||
init_completion(&context.cmpl);
|
||||
context.cache_name = cfg->name;
|
||||
context.result = &result;
|
||||
context.cache_name_meta = cache_name_meta;
|
||||
context.cache_mode_meta = cache_mode_meta;
|
||||
context.cache_line_size_meta = cache_line_size_meta;
|
||||
|
||||
ocf_metadata_probe(cas_ctx, volume, cache_mngt_check_metadata_end,
|
||||
ocf_metadata_probe(cas_ctx, volume, cache_mngt_probe_metadata_end,
|
||||
&context);
|
||||
wait_for_completion(&context.cmpl);
|
||||
|
||||
@ -2351,9 +2378,12 @@ int cache_mngt_init_instance(struct ocf_mngt_cache_config *cfg,
|
||||
struct kcas_start_cache *cmd)
|
||||
{
|
||||
struct _cache_mngt_attach_context *context;
|
||||
ocf_cache_t cache;
|
||||
ocf_cache_t cache, tmp_cache = NULL;
|
||||
char cache_name_meta[OCF_CACHE_NAME_SIZE];
|
||||
struct cache_priv *cache_priv;
|
||||
int result = 0, rollback_result = 0;
|
||||
ocf_cache_mode_t cache_mode_meta;
|
||||
ocf_cache_line_size_t cache_line_size_meta;
|
||||
|
||||
if (!try_module_get(THIS_MODULE))
|
||||
return -KCAS_ERR_SYSTEM;
|
||||
@ -2367,11 +2397,40 @@ int cache_mngt_init_instance(struct ocf_mngt_cache_config *cfg,
|
||||
switch (cmd->init_cache) {
|
||||
case CACHE_INIT_LOAD:
|
||||
case CACHE_INIT_STANDBY_LOAD:
|
||||
result = _cache_mngt_check_metadata(cfg, cmd->cache_path_name);
|
||||
result = _cache_mngt_probe_metadata(cmd->cache_path_name,
|
||||
cache_name_meta, &cache_mode_meta,
|
||||
&cache_line_size_meta);
|
||||
if (result) {
|
||||
module_put(THIS_MODULE);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Need to return name from metadata now for caller to properly
|
||||
* communicate the error to user */
|
||||
if (cache_id_from_name(&cmd->cache_id, cache_name_meta)) {
|
||||
printk(KERN_ERR "Improper cache name format on %s.\n",
|
||||
cmd->cache_path_name);
|
||||
|
||||
module_put(THIS_MODULE);
|
||||
return -OCF_ERR_START_CACHE_FAIL;
|
||||
}
|
||||
|
||||
result = ocf_mngt_cache_get_by_name(cas_ctx, cache_name_meta,
|
||||
OCF_CACHE_NAME_SIZE, &tmp_cache);
|
||||
|
||||
if (result != -OCF_ERR_CACHE_NOT_EXIST) {
|
||||
printk(KERN_ERR "Can't load %s. Cache using that name "
|
||||
"already exists.\n", cache_name_meta);
|
||||
|
||||
ocf_mngt_cache_put(tmp_cache);
|
||||
module_put(THIS_MODULE);
|
||||
return -OCF_ERR_CACHE_EXIST;
|
||||
}
|
||||
|
||||
result = 0;
|
||||
strlcpy(cfg->name, cache_name_meta, OCF_CACHE_NAME_SIZE);
|
||||
cfg->cache_mode = cache_mode_meta;
|
||||
cfg->cache_line_size = cache_line_size_meta;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -81,7 +81,8 @@ stop_cache_mounted_core = [
|
||||
]
|
||||
|
||||
load_and_force = [
|
||||
r"Use of \'load\' and \'force\' simultaneously is forbidden\."
|
||||
(r"Use of \'load\' and \'force\', \'cache-id\', \'cache-mode\' or \'cache-line-size\'",
|
||||
r" simultaneously is forbidden.")
|
||||
]
|
||||
|
||||
try_add_core_sector_size_mismatch = [
|
||||
|
@ -30,8 +30,11 @@ restore_config() {
|
||||
start_cache() {
|
||||
check_options ${FUNCNAME[0]}
|
||||
|
||||
local COMMAND="$CAS --start-cache --cache-device $CACHE_DEVICE_OPTION --cache-id $CACHE_ID_OPTION"
|
||||
local COMMAND="$CAS --start-cache --cache-device $CACHE_DEVICE_OPTION"
|
||||
|
||||
if [ -n "$CACHE_ID_OPTION" ] ; then
|
||||
COMMAND="$COMMAND --cache-id $CACHE_ID_OPTION"
|
||||
fi
|
||||
if [ -n "$CACHE_FORCE_OPTION" ] ; then
|
||||
COMMAND="$COMMAND --force"
|
||||
fi
|
||||
|
@ -33,7 +33,7 @@ export ALL_OPTIONS="
|
||||
# Specify ONLY required options here. The name of the variable should start with
|
||||
# uppercase function's name + "_REQUIRED_OPTIONS".
|
||||
|
||||
export START_CACHE_REQUIRED_OPTIONS="CACHE_ID_OPTION CACHE_DEVICE_OPTION"
|
||||
export START_CACHE_REQUIRED_OPTIONS="CACHE_DEVICE_OPTION"
|
||||
export STOP_CACHE_REQUIRED_OPTIONS="CACHE_ID_OPTION"
|
||||
export ADD_CORE_REQUIRED_OPTIONS="CACHE_ID_OPTION CORE_DEVICE_OPTION"
|
||||
export TRY_ADD_CORE_REQUIRED_OPTIONS="CACHE_ID_OPTION CORE_ID_OPTION CORE_DEVICE_OPTION"
|
||||
@ -67,7 +67,6 @@ export TURN_ON_NVME_DEVICE_REQUIRED_OPTIONS="CACHE_DEVICE_OPTION"
|
||||
|
||||
export START_DUAL_LEVEL_CACHE_REQUIRED_OPTIONS="CACHE_ID_OPTION CACHE_DEVICE_OPTION"
|
||||
|
||||
export START_CACHE_REQUIRED_OPTIONS="CACHE_ID_OPTION CACHE_DEVICE_OPTION"
|
||||
|
||||
export IO_CLASS_LIST_REQUIRED_OPTIONS="CACHE_ID_OPTION"
|
||||
export IO_CLASS_LOAD_REQUIRED_OPTIONS="CACHE_ID_OPTION CSV_FILE"
|
||||
|
@ -57,7 +57,7 @@ DEVICE_ID_OPTION="${CORE_DEVICE}-part3" DEMANDED_STATE_OPTION="Detached" check_d
|
||||
|
||||
|
||||
# Try to load cache device, check if it is running and if all cores status is appropirate
|
||||
CACHE_ID_OPTION="1" CACHE_DEVICE_OPTION="${CACHE_DEVICE}-part1" CACHE_LOAD_METADATA_OPTION="y" start_cache
|
||||
CACHE_DEVICE_OPTION="${CACHE_DEVICE}-part1" CACHE_LOAD_METADATA_OPTION="y" start_cache
|
||||
DEVICE_ID_OPTION="${CACHE_DEVICE}-part1" DEMANDED_STATE_OPTION="Running" check_device_state
|
||||
DEVICE_ID_OPTION="${DEVICE_NAME}1-1" DEMANDED_STATE_OPTION="Active" check_device_state
|
||||
DEVICE_ID_OPTION="${DEVICE_NAME}1-2" DEMANDED_STATE_OPTION="Active" check_device_state
|
||||
|
@ -48,7 +48,7 @@ TARGET_DEVICE_OPTION="$CORE_DEVICE" PARTITION_SIZE_OPTION="4000M" PARTITION_IDS_
|
||||
sleep 1
|
||||
# Load cache, then add cores and check if chache is running
|
||||
# Try to load cache device, check its state and cores state
|
||||
CACHE_ID_OPTION="1" CACHE_DEVICE_OPTION="${CACHE_DEVICE}-part1" CACHE_LOAD_METADATA_OPTION="y" start_cache
|
||||
CACHE_DEVICE_OPTION="${CACHE_DEVICE}-part1" CACHE_LOAD_METADATA_OPTION="y" start_cache
|
||||
DEVICE_ID_OPTION="${CACHE_DEVICE}-part1" DEMANDED_STATE_OPTION="Incomplete" check_device_state
|
||||
DEVICE_ID_OPTION="${DEVICE_NAME}1-1" DEMANDED_STATE_OPTION="Active" check_device_state
|
||||
DEVICE_ID_OPTION="${DEVICE_NAME}1-2" DEMANDED_STATE_OPTION="Active" check_device_state
|
||||
@ -66,7 +66,7 @@ DEVICE_ID_OPTION="${CORE_DEVICE}-part1" DEMANDED_STATE_OPTION="Detached" check_d
|
||||
DEVICE_ID_OPTION="${CORE_DEVICE}-part2" DEMANDED_STATE_OPTION="Detached" check_device_state
|
||||
DEVICE_ID_OPTION="${CORE_DEVICE}-part3" DEMANDED_STATE_OPTION="Detached" check_device_state
|
||||
|
||||
CACHE_ID_OPTION="1" CACHE_DEVICE_OPTION="${CACHE_DEVICE}-part1" CACHE_LOAD_METADATA_OPTION="y" start_cache
|
||||
CACHE_DEVICE_OPTION="${CACHE_DEVICE}-part1" CACHE_LOAD_METADATA_OPTION="y" start_cache
|
||||
|
||||
DEVICE_ID_OPTION="${CACHE_DEVICE}-part1" DEMANDED_STATE_OPTION="Running" check_device_state
|
||||
DEVICE_ID_OPTION="${DEVICE_NAME}1-1" DEMANDED_STATE_OPTION="Active" check_device_state
|
||||
|
@ -114,7 +114,7 @@ do
|
||||
fi
|
||||
|
||||
# Start again with load option, this should fail, metadata is corrupted.
|
||||
NEGATIVE_TEST_OPTION="1" CACHE_ID_OPTION="1" CACHE_LOAD_METADATA_OPTION="1" CACHE_DEVICE_OPTION="${CACHE_DEVICE}-part1" start_cache
|
||||
NEGATIVE_TEST_OPTION="1" CACHE_LOAD_METADATA_OPTION="1" CACHE_DEVICE_OPTION="${CACHE_DEVICE}-part1" start_cache
|
||||
done
|
||||
|
||||
|
||||
|
@ -91,7 +91,7 @@ do
|
||||
fi
|
||||
|
||||
# Start again with load option, this should fail, metadata is corrupted.
|
||||
NEGATIVE_TEST_OPTION="1" CACHE_ID_OPTION="1" CACHE_LOAD_METADATA_OPTION="1" CACHE_DEVICE_OPTION="${CACHE_DEVICE}-part1" start_cache
|
||||
NEGATIVE_TEST_OPTION="1" CACHE_LOAD_METADATA_OPTION="1" CACHE_DEVICE_OPTION="${CACHE_DEVICE}-part1" start_cache
|
||||
done
|
||||
|
||||
test_log_stop
|
||||
|
@ -108,7 +108,7 @@ CACHE_ID_OPTION="1" PROMO_POL_NS_OPTION="promotion-nhit" THRESHOLD_OPTION="451"
|
||||
CACHE_ID_OPTION="1" PROMO_POL_NS_OPTION="promotion-nhit" THRESHOLD_OPTION="812" TRIGGER_OPTION="49" set_promotion_params
|
||||
CACHE_ID_OPTION="1" PROMO_POL_OPTION="nhit" set_promotion_policy
|
||||
CACHE_ID_OPTION="1" stop_cache
|
||||
CACHE_MODE_OPTION="wt" CACHE_ID_OPTION="1" CACHE_DEVICE_OPTION="${CACHE_DEVICE}-part1" CACHE_LOAD_METADATA_OPTION="1" start_cache
|
||||
CACHE_MODE_OPTION="wt" CACHE_DEVICE_OPTION="${CACHE_DEVICE}-part1" CACHE_LOAD_METADATA_OPTION="1" start_cache
|
||||
CACHE_ID_OPTION="1" PROMO_POL_OPTION="nhit" check_promotion_policy
|
||||
CACHE_ID_OPTION="1" PROMO_POL_NS_OPTION="promotion-nhit" THRESHOLD_OPTION="812" TRIGGER_OPTION="49" check_promotion_params
|
||||
|
||||
|
@ -72,7 +72,7 @@ done
|
||||
CACHE_DEVICE_OPTION="${SHORT_LINK}" turn_on_device
|
||||
|
||||
for ID in 1 2 3 ; do
|
||||
CACHE_ID_OPTION="$ID" CACHE_DEVICE_OPTION="${CACHE_DEVICE}-part${ID}" CACHE_LOAD_METADATA_OPTION="y" CACHE_MODE_OPTION="wb" start_cache
|
||||
CACHE_DEVICE_OPTION="${CACHE_DEVICE}-part${ID}" CACHE_LOAD_METADATA_OPTION="y" start_cache
|
||||
CACHE_ID_OPTION="$ID" stop_cache
|
||||
run_cmd "mount ${CORE_DEVICE}-part${ID} ${MOUNTPOINT}-${ID}-1"
|
||||
done
|
||||
|
@ -72,7 +72,7 @@ done
|
||||
CACHE_DEVICE_OPTION="${SHORT_LINK}" turn_on_device
|
||||
|
||||
for ID in 1 2 3 ; do
|
||||
CACHE_ID_OPTION="$ID" CACHE_DEVICE_OPTION="${CACHE_DEVICE}-part${ID}" CACHE_LOAD_METADATA_OPTION="y" CACHE_MODE_OPTION="wb" start_cache
|
||||
CACHE_DEVICE_OPTION="${CACHE_DEVICE}-part${ID}" CACHE_LOAD_METADATA_OPTION="y" start_cache
|
||||
CACHE_ID_OPTION="$ID" CORE_ID_OPTION="1" mount_cache
|
||||
done
|
||||
|
||||
|
@ -316,7 +316,7 @@ def test_cas_config_get_by_id_path_not_found(mock_listdir, mock_realpath):
|
||||
"2 /dev/dummy0n2 pt ioclass_file=mango.csv",
|
||||
"3 /dev/dummy0n3 WA cache_line_size=16",
|
||||
("4 /dev/dummyc wb cache_line_size=16,"
|
||||
"ioclass_file=mango.csv,cleaning_policy=nop"),
|
||||
"ioclass_file=mango.csv,cleaning_policy=nop,target_failover_state=standby"),
|
||||
],
|
||||
[],
|
||||
),
|
||||
|
@ -187,8 +187,10 @@ def test_cache_config_from_line_missing_ioclass_file(
|
||||
"ioclass_file=ioclass.csv,ioclass_file=ioclass.csv",
|
||||
"cleaning_policy=nop,cleaning_policy=acp",
|
||||
"cleaning_policy=",
|
||||
"clining_polisi=nop",
|
||||
"cleaning_policy=INVALID",
|
||||
"ioclass_file=ioclass.csv, cleaning_policy=nop",
|
||||
"ioclas_file=ioclass.csv",
|
||||
"cache_line_size=4,cache_line_size=8",
|
||||
"cache_line_size=",
|
||||
"cache_line_size=0",
|
||||
@ -198,14 +200,20 @@ def test_cache_config_from_line_missing_ioclass_file(
|
||||
"cache_line_size=-1",
|
||||
"cache_line_size=four",
|
||||
"cache_line_size=128",
|
||||
"cach_lin_siz=4",
|
||||
"promotion_policy=111111",
|
||||
"promotion_policy=",
|
||||
"promotion_policy=dinosaurs",
|
||||
"promotion_policy=Robert'); DROP TABLE Students;--",
|
||||
"promotion_policy=awlays",
|
||||
"promotion_policy=nnhit",
|
||||
"demolition_policy=nhit",
|
||||
"lazy_startup=yes",
|
||||
"lazy_startup=absolutely",
|
||||
"hasty_startup=true",
|
||||
"target_failover_state=no",
|
||||
"target_failover_state=maybe",
|
||||
"target_failrover_state=standby",
|
||||
],
|
||||
)
|
||||
@mock.patch("os.path.exists")
|
||||
@ -242,10 +250,12 @@ def test_cache_config_from_line_parameter_validation_01(
|
||||
"ioclass_file=ioclass.csv,cache_line_size=4,cleaning_policy=nop",
|
||||
"promotion_policy=nhit",
|
||||
"promotion_policy=always",
|
||||
"target_failover_state=standby",
|
||||
"target_failover_state=active",
|
||||
"lazy_startup=true",
|
||||
"lazy_startup=false",
|
||||
("ioclass_file=ioclass.csv,cache_line_size=4,cleaning_policy=nop,promotion_policy=always,"
|
||||
"lazy_startup=true"),
|
||||
"lazy_startup=true,target_failover_state=active"),
|
||||
],
|
||||
)
|
||||
@mock.patch("os.path.exists")
|
||||
@ -416,6 +426,7 @@ def test_cache_config_from_line_cache_id_validation_02(
|
||||
"cache_mode": "wo",
|
||||
"promotion_policy": "always",
|
||||
"cache_line_size": "16",
|
||||
"lazy_startup": "true"
|
||||
},
|
||||
{
|
||||
"cache_id": "1",
|
||||
@ -423,6 +434,7 @@ def test_cache_config_from_line_cache_id_validation_02(
|
||||
"cache_mode": "wo",
|
||||
"promotion_policy": "nhit",
|
||||
"cache_line_size": "16",
|
||||
"target_failover_state": "active",
|
||||
},
|
||||
],
|
||||
)
|
||||
|
@ -6,6 +6,7 @@
|
||||
import pytest
|
||||
from unittest.mock import patch, Mock
|
||||
import time
|
||||
import subprocess
|
||||
|
||||
import opencas
|
||||
|
||||
@ -74,7 +75,7 @@ def test_cas_settle_cores_didnt_start_02(mock_add, mock_exists, mock_run, mock_l
|
||||
"type": "cache",
|
||||
"id": "1",
|
||||
"disk": "/dev/dummy_cache",
|
||||
"status": "Active",
|
||||
"status": "Standby",
|
||||
"write policy": "wt",
|
||||
"device": "-",
|
||||
}
|
||||
@ -303,7 +304,11 @@ def test_cas_settle_caches_didnt_start_01(
|
||||
mock_config.return_value = Mock(
|
||||
spec_set=opencas.cas_config(),
|
||||
cores=[],
|
||||
caches={42: opencas.cas_config.cache_config(42, "/dev/dummy", "wt")},
|
||||
caches={
|
||||
42: opencas.cas_config.cache_config(
|
||||
42, "/dev/dummy", "wt", target_failover_state="standby"
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
result = opencas.wait_for_startup(timeout=0, interval=0)
|
||||
@ -345,7 +350,7 @@ def test_cas_settle_caches_didnt_start_02(
|
||||
|
||||
result = opencas.wait_for_startup(timeout=0, interval=0)
|
||||
|
||||
assert len(result) == 1, "didn't return uninitialized core"
|
||||
assert len(result) == 1, "didn't return uninitialized cache"
|
||||
|
||||
|
||||
@patch("opencas.cas_config.from_file")
|
||||
@ -416,7 +421,7 @@ def test_cas_settle_caches_didnt_start_03(
|
||||
|
||||
result = opencas.wait_for_startup(timeout=0, interval=0)
|
||||
|
||||
assert len(result) == 2, "didn't return uninitialized cores"
|
||||
assert len(result) == 2, "didn't return uninitialized caches"
|
||||
|
||||
|
||||
@patch("opencas.cas_config.from_file")
|
||||
@ -802,10 +807,10 @@ def test_last_resort_add_02(mock_start, mock_add, mock_exists, mock_run, mock_li
|
||||
|
||||
result = opencas.wait_for_startup(timeout=0, interval=0)
|
||||
|
||||
mock_start.assert_any_call(config.caches[1], True)
|
||||
mock_start.assert_any_call(config.caches[2], True)
|
||||
mock_add.assert_any_call(config.cores[0], True)
|
||||
mock_add.assert_any_call(config.cores[1], True)
|
||||
mock_start.assert_any_call(config.caches[1], load=True)
|
||||
mock_start.assert_any_call(config.caches[2], load=True)
|
||||
mock_add.assert_any_call(config.cores[0], try_add=True)
|
||||
mock_add.assert_any_call(config.cores[1], try_add=True)
|
||||
mock_run.assert_called_with(["udevadm", "settle"])
|
||||
|
||||
|
||||
@ -883,10 +888,10 @@ def test_last_resort_add_04(mock_start, mock_add, mock_exists, mock_run, mock_li
|
||||
|
||||
result = opencas.wait_for_startup(timeout=2, interval=0.1)
|
||||
|
||||
mock_start.assert_any_call(config.caches[1], True)
|
||||
mock_start.assert_any_call(config.caches[2], True)
|
||||
mock_add.assert_any_call(config.cores[0], True)
|
||||
mock_add.assert_any_call(config.cores[1], True)
|
||||
mock_start.assert_any_call(config.caches[1], load=True)
|
||||
mock_start.assert_any_call(config.caches[2], load=True)
|
||||
mock_add.assert_any_call(config.cores[0], try_add=True)
|
||||
mock_add.assert_any_call(config.cores[1], try_add=True)
|
||||
mock_run.assert_called_with(["udevadm", "settle"])
|
||||
|
||||
|
||||
@ -896,7 +901,7 @@ def test_last_resort_add_04(mock_start, mock_add, mock_exists, mock_run, mock_li
|
||||
@patch("os.path.exists")
|
||||
@patch("opencas.add_core")
|
||||
@patch("opencas.start_cache")
|
||||
def test_last_resort_add_04(mock_start, mock_add, mock_exists, mock_run, mock_list, mock_config):
|
||||
def test_last_resort_add_05(mock_start, mock_add, mock_exists, mock_run, mock_list, mock_config):
|
||||
"""
|
||||
Check if adding cores/starting caches is attempted while waiting for startup for lazy_startup
|
||||
devices once before returning.
|
||||
@ -919,11 +924,11 @@ def test_last_resort_add_04(mock_start, mock_add, mock_exists, mock_run, mock_li
|
||||
|
||||
result = opencas.wait_for_startup(timeout=0.5, interval=0.1)
|
||||
|
||||
mock_start.assert_any_call(config.caches[1], True)
|
||||
mock_start.assert_any_call(config.caches[2], True)
|
||||
mock_start.assert_any_call(config.caches[1], load=True)
|
||||
mock_start.assert_any_call(config.caches[2], load=True)
|
||||
assert mock_start.call_count == 2, "start cache was called more than once per device"
|
||||
mock_add.assert_any_call(config.cores[0], True)
|
||||
mock_add.assert_any_call(config.cores[1], True)
|
||||
mock_add.assert_any_call(config.cores[0], try_add=True)
|
||||
mock_add.assert_any_call(config.cores[1], try_add=True)
|
||||
assert mock_add.call_count == 2, "add core was called more than once per device"
|
||||
mock_run.assert_called_with(["udevadm", "settle"])
|
||||
|
||||
@ -934,7 +939,7 @@ def test_last_resort_add_04(mock_start, mock_add, mock_exists, mock_run, mock_li
|
||||
@patch("os.path.exists")
|
||||
@patch("opencas.add_core")
|
||||
@patch("opencas.start_cache")
|
||||
def test_last_resort_add_05(mock_start, mock_add, mock_exists, mock_run, mock_list, mock_config):
|
||||
def test_last_resort_add_06(mock_start, mock_add, mock_exists, mock_run, mock_list, mock_config):
|
||||
"""
|
||||
Check if adding cores/starting caches is not attempted while waiting for startup for lazy
|
||||
startup devices if paths show up after half of the startup timeout expires.
|
||||
@ -960,3 +965,53 @@ def test_last_resort_add_05(mock_start, mock_add, mock_exists, mock_run, mock_li
|
||||
mock_start.assert_not_called()
|
||||
mock_add.assert_not_called()
|
||||
mock_run.assert_called_with(["udevadm", "settle"])
|
||||
|
||||
|
||||
def assert_option_value(call, option, value):
|
||||
try:
|
||||
index = call.index(option)
|
||||
except ValueError as e:
|
||||
raise AssertionError(f"{option} not found in call ({call})") from e
|
||||
|
||||
assert call[index + 1] == value
|
||||
|
||||
|
||||
@pytest.mark.parametrize("failover", ["standby", "active"])
|
||||
@pytest.mark.parametrize("force", [True, False])
|
||||
@pytest.mark.parametrize("load", [True, False])
|
||||
@patch("subprocess.run")
|
||||
def test_start_cache(mock_run, load, force, failover):
|
||||
cache_config = opencas.cas_config.cache_config(
|
||||
1,
|
||||
"/dev/lizards",
|
||||
"wt",
|
||||
lazy_startup="true",
|
||||
cache_line_size="64",
|
||||
target_failover_state=failover,
|
||||
)
|
||||
mock_run.return_value = Mock(
|
||||
returncode=0,
|
||||
stderr="",
|
||||
stdout="",
|
||||
)
|
||||
|
||||
opencas.start_cache(cache_config, load, force)
|
||||
|
||||
casadm_call = mock_run.call_args[0][0]
|
||||
assert "/sbin/casadm" in casadm_call
|
||||
assert_option_value(casadm_call, "--cache-device", "/dev/lizards")
|
||||
|
||||
if not load:
|
||||
assert_option_value(casadm_call, "--cache-id", "1")
|
||||
assert_option_value(casadm_call, "--cache-line-size", "64")
|
||||
if failover == "active":
|
||||
assert "--start-cache" in casadm_call
|
||||
assert_option_value(casadm_call, "--cache-mode", "wt")
|
||||
else:
|
||||
assert "--standby" in casadm_call
|
||||
assert "--init" in casadm_call
|
||||
else:
|
||||
assert "--load" in casadm_call
|
||||
assert "--cache-id" not in casadm_call
|
||||
assert "--cache-mode" not in casadm_call
|
||||
assert "--cache-line-size" not in casadm_call
|
||||
|
@ -44,7 +44,7 @@ def start():
|
||||
|
||||
for cache in config.caches.values():
|
||||
try:
|
||||
opencas.start_cache(cache, True)
|
||||
opencas.start_cache(cache, load=True)
|
||||
except opencas.casadm.CasadmError as e:
|
||||
eprint(
|
||||
"Unable to load cache {0} ({1}). Reason:\n{2}".format(
|
||||
@ -116,7 +116,7 @@ def init(force):
|
||||
|
||||
for cache in config.caches.values():
|
||||
try:
|
||||
opencas.start_cache(cache, False, force)
|
||||
opencas.start_cache(cache, load=False, force=force)
|
||||
except opencas.casadm.CasadmError as e:
|
||||
eprint(
|
||||
"Unable to start cache {0} ({1}). Reason:\n{2}".format(
|
||||
|
@ -24,7 +24,7 @@ Cache device <DEVICE>
|
||||
.br
|
||||
Cache mode {wt|wb|wa|pt|wo}
|
||||
.br
|
||||
Extra fields (optional) ioclass_file=<file>,cleaning_policy=<alru,nop>,promotion_policy=<always,nhit>
|
||||
Extra fields (optional) ioclass_file=<file>,cleaning_policy=<alru,nop>,promotion_policy=<always,nhit>,target_failover_state=<active,standby>
|
||||
.RE
|
||||
.TP
|
||||
\fB[cores]\fR Cores configuration. Following columns are required:
|
||||
|
@ -60,8 +60,9 @@ class casadm:
|
||||
return cls.run_cmd(cmd)
|
||||
|
||||
@classmethod
|
||||
def start_cache(cls, device, cache_id=None, cache_mode=None,
|
||||
cache_line_size=None, load=False, force=False):
|
||||
def start_cache(
|
||||
cls, device, cache_id=None, cache_mode=None, cache_line_size=None, load=False, force=False
|
||||
):
|
||||
cmd = [cls.casadm_path,
|
||||
'--start-cache',
|
||||
'--cache-device', device]
|
||||
@ -77,6 +78,22 @@ class casadm:
|
||||
cmd += ['--force']
|
||||
return cls.run_cmd(cmd)
|
||||
|
||||
@classmethod
|
||||
def start_standby_cache(
|
||||
cls, device, cache_id=None, cache_line_size=None, load=False, force=False
|
||||
):
|
||||
cmd = [cls.casadm_path,
|
||||
'--standby',
|
||||
'--init' if not load else '--load',
|
||||
'--cache-device', device]
|
||||
if cache_id:
|
||||
cmd += ['--cache-id', str(cache_id)]
|
||||
if cache_line_size:
|
||||
cmd += ['--cache-line-size', str(cache_line_size)]
|
||||
if force:
|
||||
cmd += ['--force']
|
||||
return cls.run_cmd(cmd)
|
||||
|
||||
@classmethod
|
||||
def add_core(cls, device, cache_id, core_id=None, try_add=False):
|
||||
cmd = [cls.casadm_path,
|
||||
@ -197,7 +214,7 @@ class cas_config(object):
|
||||
def __init__(self, cache_id, device, cache_mode, **params):
|
||||
self.cache_id = int(cache_id)
|
||||
self.device = device
|
||||
self.cache_mode = cache_mode
|
||||
self.cache_mode = cache_mode.lower()
|
||||
self.params = params
|
||||
self.cores = dict()
|
||||
|
||||
@ -215,7 +232,7 @@ class cas_config(object):
|
||||
|
||||
params = dict()
|
||||
if len(values) > 3:
|
||||
for param in values[3].split(','):
|
||||
for param in values[3].lower().split(','):
|
||||
param_name, param_value = param.split('=')
|
||||
if param_name in params:
|
||||
raise ValueError('Invalid cache configuration (repeated parameter')
|
||||
@ -250,6 +267,8 @@ class cas_config(object):
|
||||
self.check_cache_line_size_valid(param_value)
|
||||
elif param_name == "lazy_startup":
|
||||
self.check_lazy_startup_valid(param_value)
|
||||
elif param_name == "target_failover_state":
|
||||
self.check_failover_state_valid(param_value)
|
||||
else:
|
||||
raise ValueError(f'{param_name} is invalid parameter name')
|
||||
|
||||
@ -273,19 +292,23 @@ class cas_config(object):
|
||||
)
|
||||
|
||||
def check_cache_mode_valid(self, cache_mode):
|
||||
if cache_mode.lower() not in ['wt', 'pt', 'wa', 'wb', 'wo']:
|
||||
if cache_mode not in ['wt', 'pt', 'wa', 'wb', 'wo']:
|
||||
raise ValueError(f'Invalid cache mode {cache_mode}')
|
||||
|
||||
def check_cleaning_policy_valid(self, cleaning_policy):
|
||||
if cleaning_policy.lower() not in ['acp', 'alru', 'nop']:
|
||||
if cleaning_policy not in ['acp', 'alru', 'nop']:
|
||||
raise ValueError(f'{cleaning_policy} is invalid cleaning policy name')
|
||||
|
||||
def check_lazy_startup_valid(self, lazy_startup):
|
||||
if lazy_startup.lower() not in ["true", "false"]:
|
||||
if lazy_startup not in ["true", "false"]:
|
||||
raise ValueError('{0} is invalid lazy_startup value'.format(lazy_startup))
|
||||
|
||||
def check_failover_state_valid(self, failover_state):
|
||||
if failover_state not in ["active", "standby"]:
|
||||
raise ValueError(f"{failover_state} is invalid target_failover_state value")
|
||||
|
||||
def check_promotion_policy_valid(self, promotion_policy):
|
||||
if promotion_policy.lower() not in ['always', 'nhit']:
|
||||
if promotion_policy not in ['always', 'nhit']:
|
||||
raise ValueError(f'{promotion_policy} is invalid promotion policy name')
|
||||
|
||||
def check_cache_line_size_valid(self, cache_line_size):
|
||||
@ -319,7 +342,7 @@ class cas_config(object):
|
||||
return ret
|
||||
|
||||
def is_lazy(self):
|
||||
return self.params.get("lazy_startup", "false").lower() == "true"
|
||||
return self.params.get("lazy_startup", "false") == "true"
|
||||
|
||||
class core_config(object):
|
||||
def __init__(self, cache_id, core_id, path, **params):
|
||||
@ -369,7 +392,7 @@ class cas_config(object):
|
||||
|
||||
def validate_parameter(self, param_name, param_value):
|
||||
if param_name == "lazy_startup":
|
||||
if param_value.lower() not in ["true", "false"]:
|
||||
if param_value not in ["true", "false"]:
|
||||
raise ValueError(
|
||||
f"{param_value} is invalid value for '{param_name}' core param"
|
||||
)
|
||||
@ -401,7 +424,7 @@ class cas_config(object):
|
||||
return ret
|
||||
|
||||
def is_lazy(self):
|
||||
return self.params.get("lazy_startup", "false").lower() == "true"
|
||||
return self.params.get("lazy_startup", "false") == "true"
|
||||
|
||||
def __init__(self, caches=None, cores=None, version_tag=None):
|
||||
self.caches = caches if caches else dict()
|
||||
@ -545,13 +568,24 @@ class cas_config(object):
|
||||
|
||||
|
||||
def start_cache(cache, load, force=False):
|
||||
target_state = cache.params.get("target_failover_state")
|
||||
if target_state is not None and target_state == "standby":
|
||||
casadm.start_standby_cache(
|
||||
device=cache.device,
|
||||
cache_id=cache.cache_id if not load else None,
|
||||
cache_line_size=cache.params.get("cache_line_size") if not load else None,
|
||||
load=load,
|
||||
force=force
|
||||
)
|
||||
else:
|
||||
casadm.start_cache(
|
||||
device=cache.device,
|
||||
cache_id=cache.cache_id,
|
||||
cache_mode=cache.cache_mode,
|
||||
cache_line_size=cache.params.get('cache_line_size'),
|
||||
cache_id=cache.cache_id if not load else None,
|
||||
cache_mode=cache.cache_mode if not load else None,
|
||||
cache_line_size=cache.params.get('cache_line_size') if not load else None,
|
||||
load=load,
|
||||
force=force)
|
||||
force=force
|
||||
)
|
||||
|
||||
|
||||
def configure_cache(cache):
|
||||
@ -820,9 +854,9 @@ def wait_for_startup(timeout=300, interval=5):
|
||||
def start_device(dev):
|
||||
if os.path.exists(dev.device):
|
||||
if type(dev) is cas_config.core_config:
|
||||
add_core(dev, True)
|
||||
add_core(dev, try_add=True)
|
||||
elif type(dev) is cas_config.cache_config:
|
||||
start_cache(dev, True)
|
||||
start_cache(dev, load=True)
|
||||
|
||||
stop_time = time.time() + int(timeout)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user