int read_scalar_params(config_item_t block, const char *block_name, const cfg_param_t * params, char *msgout) { int i; int rc = 0; /* read all expected parameters */ for (i = 0; params[i].name != NULL; i++) { switch (params[i].type) { case PT_STRING: rc = GetStringParam(block, block_name, params[i].name, params[i].flags, (char*)params[i].ptr, params[i].ptrsize, NULL, NULL, msgout); if cfg_is_err(rc, params[i].flags) return rc; break; case PT_CMD: rc = GetCommandParam(block, block_name, params[i].name, params[i].flags, (char***)params[i].ptr, NULL, NULL, msgout); if cfg_is_err(rc, params[i].flags) return rc; break; case PT_BOOL: rc = GetBoolParam(block, block_name, params[i].name, params[i].flags, (bool*)params[i].ptr, NULL, NULL, msgout); if cfg_is_err(rc, params[i].flags) return rc; break; case PT_DURATION: rc = GetDurationParam(block, block_name, params[i].name, params[i].flags, (time_t*)params[i].ptr, NULL, NULL, msgout); if cfg_is_err(rc, params[i].flags) return rc; break; case PT_SIZE: rc = GetSizeParam(block, block_name, params[i].name, params[i].flags, (unsigned long long*)params[i].ptr, NULL, NULL, msgout); if cfg_is_err(rc, params[i].flags) return rc; break; case PT_INT: rc = GetIntParam(block, block_name, params[i].name, params[i].flags, (int*)params[i].ptr, NULL, NULL, msgout); if cfg_is_err(rc, params[i].flags) return rc; break; case PT_INT64: rc = GetInt64Param(block, block_name, params[i].name, params[i].flags, (uint64_t*)params[i].ptr, NULL, NULL, msgout); if cfg_is_err(rc, params[i].flags) return rc; break; case PT_FLOAT: rc = GetFloatParam(block, block_name, params[i].name, params[i].flags, (double*)params[i].ptr, NULL, NULL, msgout); if cfg_is_err(rc, params[i].flags) return rc; break; case PT_TYPE: sprintf(msgout, "Unexpected type for %s parameter (type)", params[i].name); return EINVAL; } } return 0; }
static int parse_trigger_block( config_item_t config_blk, const char *block_name, trigger_item_t * p_trigger_item, char *msg_out ) { int rc; int rc_hp, rc_lp, rc_hv, rc_lv, rc_hc, rc_lc; unsigned int high_count = 0; unsigned int low_count = 0; double h_pct, l_pct; unsigned long long h_vol, l_vol; uint64_t h_cnt, l_cnt; int tmpval; int i; char tmpstr[1024]; char **arg_tab; unsigned int arg_count; static const char *trigger_expect[] = { "trigger_on", "check_interval", "high_threshold_pct", "low_threshold_pct", "high_threshold_vol", "low_threshold_vol", "high_threshold_cnt", "low_threshold_cnt", "alert_high", "alert_low", /* for backward compatibility */ "high_watermark_pct", "low_watermark_pct", "high_watermark_vol", "low_watermark_vol", "high_watermark_cnt", "low_watermark_cnt", "notify", "notify_hw", "alert_lw", NULL }; /* retrieve parameters */ rc = GetStringParam( config_blk, block_name, "trigger_on", PARAM_MANDATORY | STR_PARAM_NO_WILDCARDS, tmpstr, 1024, &arg_tab, &arg_count, msg_out ); if ( rc ) /* even ENOENT retruns an error because trigger_on is mandatory */ return rc; /* initialize list of optional args */ p_trigger_item->list = NULL; p_trigger_item->list_size = 0; /* analyze trigger_on parameter */ if ( !strcasecmp( tmpstr, "periodic" ) ) { p_trigger_item->type = TRIGGER_ALWAYS; /* default: alert enabled if LW cannot be reached */ p_trigger_item->alert_lw = FALSE; /* no arg expected */ if ( arg_count > 0 ) { sprintf( msg_out, "No extra argument expected for trigger type '%s': %u argument(s) found.", tmpstr, arg_count ); return EINVAL; } } else if ( !strcasecmp( tmpstr, "global_usage" ) ) { p_trigger_item->type = TRIGGER_GLOBAL_USAGE; /* default: alert enabled if LW cannot be reached */ p_trigger_item->alert_lw = TRUE; /* no arg expected */ if ( arg_count > 0 ) { sprintf( msg_out, "No extra argument expected for trigger type '%s': %u argument(s) found.", tmpstr, arg_count ); return EINVAL; } } else if ( !strcasecmp( tmpstr, "OST_usage" ) ) { p_trigger_item->type = TRIGGER_OST_USAGE; /* default: alert enabled if LW cannot be reached */ p_trigger_item->alert_lw = TRUE; /* no arg expected */ if ( arg_count > 0 ) { sprintf( msg_out, "No extra argument expected for trigger type '%s': %u argument(s) found.", tmpstr, arg_count ); return EINVAL; } } else if ( !strcasecmp( tmpstr, "user_usage" ) ) { p_trigger_item->type = TRIGGER_USER_USAGE; /* default: alert enabled if LW cannot be reached */ p_trigger_item->alert_lw = TRUE; /* optional arguments: user list */ if ( arg_count > 0 ) { p_trigger_item->list = ( char ** ) calloc( arg_count, sizeof( char * ) ); p_trigger_item->list_size = arg_count; for ( i = 0; i < arg_count; i++ ) { p_trigger_item->list[i] = ( char * ) malloc( strlen( arg_tab[i] ) + 1 ); strcpy( p_trigger_item->list[i], arg_tab[i] ); } } } else if ( !strcasecmp( tmpstr, "group_usage" ) ) { p_trigger_item->type = TRIGGER_GROUP_USAGE; /* default: alert enabled if LW cannot be reached */ p_trigger_item->alert_lw = TRUE; /* optional argument: group list */ if ( arg_count > 0 ) { p_trigger_item->list = ( char ** ) calloc( arg_count, sizeof( char * ) ); p_trigger_item->list_size = arg_count; for ( i = 0; i < arg_count; i++ ) { p_trigger_item->list[i] = ( char * ) malloc( strlen( arg_tab[i] ) + 1 ); strcpy( p_trigger_item->list[i], arg_tab[i] ); } } } else if ( !strcasecmp( tmpstr, "pool_usage" ) ) { p_trigger_item->type = TRIGGER_POOL_USAGE; /* default: alert enabled if LW cannot be reached */ p_trigger_item->alert_lw = TRUE; /* optional arguments: user list */ if ( arg_count > 0 ) { p_trigger_item->list = ( char ** ) calloc( arg_count, sizeof( char * ) ); p_trigger_item->list_size = arg_count; for ( i = 0; i < arg_count; i++ ) { p_trigger_item->list[i] = ( char * ) malloc( strlen( arg_tab[i] ) + 1 ); strcpy( p_trigger_item->list[i], arg_tab[i] ); } } } else if ( !strcasecmp( tmpstr, "external_command" ) ) { p_trigger_item->type = TRIGGER_CUSTOM_CMD; /* default: alert enabled if LW cannot be reached */ p_trigger_item->alert_lw = TRUE; /* single mandatory argument: command */ if ( arg_count != 1 ) { sprintf( msg_out, "A single mandatory argument is expected for trigger type '%s': %u argument(s) found.", tmpstr, arg_count ); return EINVAL; } p_trigger_item->list = ( char ** ) malloc( sizeof( char * ) ); p_trigger_item->list[0] = ( char * ) malloc( strlen( arg_tab[0] ) + 1 ); strcpy( p_trigger_item->list[0], arg_tab[0] ); p_trigger_item->list_size = 1; } else { sprintf( msg_out, "Unexpected value for 'trigger_on' parameter: %s.", tmpstr ); return EINVAL; } /* retrieve all threshold params and check their compatibility */ high_count = low_count = 0; rc_hp = GetFloatParam( config_blk, block_name, "high_threshold_pct", FLOAT_PARAM_POSITIVE | ALLOW_PCT_SIGN, &h_pct, NULL, NULL, msg_out ); /* for backward compatibility */ if ( rc_hp == ENOENT ) rc_hp = GetFloatParam( config_blk, block_name, "high_watermark_pct", FLOAT_PARAM_POSITIVE | ALLOW_PCT_SIGN, &h_pct, NULL, NULL, msg_out ); if ( ( rc_hp != 0 ) && ( rc_hp != ENOENT ) ) return rc_hp; else if ( rc_hp != ENOENT ) high_count++; rc_hv = GetSizeParam( config_blk, block_name, "high_threshold_vol", INT_PARAM_POSITIVE, &h_vol, NULL, NULL, msg_out ); /* for backward compatibility */ if ( rc_hv == ENOENT ) rc_hv = GetSizeParam( config_blk, block_name, "high_watermark_vol", INT_PARAM_POSITIVE, &h_vol, NULL, NULL, msg_out ); if ( ( rc_hv != 0 ) && ( rc_hv != ENOENT ) ) return rc_hv; else if ( rc_hv != ENOENT ) high_count++; rc_hc = GetInt64Param( config_blk, block_name, "high_threshold_cnt", INT_PARAM_POSITIVE, &h_cnt, NULL, NULL, msg_out ); /* for backward compatibility */ if ( rc_hc == ENOENT ) rc_hc = GetInt64Param( config_blk, block_name, "high_watermark_cnt", INT_PARAM_POSITIVE, &h_cnt, NULL, NULL, msg_out ); if ( ( rc_hc != 0 ) && ( rc_hc != ENOENT ) ) return rc_hc; else if ( rc_hc != ENOENT ) high_count++; rc_lp = GetFloatParam( config_blk, block_name, "low_threshold_pct", FLOAT_PARAM_POSITIVE | ALLOW_PCT_SIGN, &l_pct, NULL, NULL, msg_out ); /* for backward compatibility */ if ( rc_lp == ENOENT ) rc_lp = GetFloatParam( config_blk, block_name, "low_watermark_pct", FLOAT_PARAM_POSITIVE | ALLOW_PCT_SIGN, &l_pct, NULL, NULL, msg_out ); if ( ( rc_lp != 0 ) && ( rc_lp != ENOENT ) ) return rc_lp; else if ( rc_lp != ENOENT ) low_count++; rc_lv = GetSizeParam( config_blk, block_name, "low_threshold_vol", INT_PARAM_POSITIVE, &l_vol, NULL, NULL, msg_out ); /* for backward compatibility */ if ( rc_lv == ENOENT ) rc_lv = GetSizeParam( config_blk, block_name, "low_watermark_vol", INT_PARAM_POSITIVE, &l_vol, NULL, NULL, msg_out ); if ( ( rc_lv != 0 ) && ( rc_lv != ENOENT ) ) return rc_lv; else if ( rc_lv != ENOENT ) low_count++; rc_lc = GetInt64Param( config_blk, block_name, "low_threshold_cnt", INT_PARAM_POSITIVE, &l_cnt, NULL, NULL, msg_out ); /* for backward compatibility */ if ( rc_lc == ENOENT ) rc_lc = GetInt64Param( config_blk, block_name, "low_watermark_cnt", INT_PARAM_POSITIVE, &l_cnt, NULL, NULL, msg_out ); if ( ( rc_lc != 0 ) && ( rc_lc != ENOENT ) ) return rc_lc; else if ( rc_lc != ENOENT ) low_count++; if ( p_trigger_item->type == TRIGGER_ALWAYS ) { /* in case of 'periodic' trigger, no thresholds are expected */ if ( (high_count > 0) || (low_count > 0) ) { strcpy( msg_out, "No high/low threshold expected for trigger type 'periodic'" ); return EINVAL; } } else if ( p_trigger_item->type == TRIGGER_CUSTOM_CMD ) { /* in case of an external command, no thresholds are expected */ if ( (high_count > 0) || (low_count > 0) ) { strcpy( msg_out, "No high/low thresholds expected for trigger type 'external_command'" ); return EINVAL; } } else if ( high_count > 1 ) { strcpy( msg_out, "Multiple purge start conditions in trigger." ); return EINVAL; } else if ( low_count > 1 ) { strcpy( msg_out, "Multiple purge stop conditions in trigger." ); return EINVAL; } else if ( high_count == 0 ) { strcpy( msg_out, "No purge start condition found in trigger " "(mandatory). 'high_threshold_pct', 'high_threshold_vol'" "or 'high_threshold_cnt' expected" ); return ENOENT; } else if ( low_count == 0 ) { strcpy( msg_out, "No purge stop condition found in trigger " "(mandatory). 'low_threshold_pct', 'low_threshold_vol'" "or 'low_threshold_cnt' expected" ); return ENOENT; } else if ( rc_hc != rc_lc ) /* both 0 or both ENOENT */ { strcpy( msg_out, "Incompatible threshold types: 'high_threshold_cnt' " "must be used with 'low_threshold_cnt'" ); return ENOENT; } /* NOTE: count threshold for HSM systems only match online files (not released)*/ /* count threshold is only on global usage */ if ( (p_trigger_item->type != TRIGGER_GLOBAL_USAGE) && (p_trigger_item->type != TRIGGER_ALWAYS) && (p_trigger_item->type != TRIGGER_USER_USAGE) && (p_trigger_item->type != TRIGGER_GROUP_USAGE) && ( (rc_hc == 0) || (rc_lc == 0) ) ) { strcpy( msg_out, "Threshold on entry count is only supported " "for 'global_usage', 'user_usage', 'group_usage' and 'periodic' triggers" ); return EINVAL; } if ( rc_hp == 0 ) { p_trigger_item->hw_type = PCT_THRESHOLD; p_trigger_item->hw_percent = h_pct; } else if ( rc_hv == 0 ) { p_trigger_item->hw_type = VOL_THRESHOLD; p_trigger_item->hw_volume = h_vol; } else if ( rc_hc == 0 ) { p_trigger_item->hw_type = COUNT_THRESHOLD; p_trigger_item->hw_count = h_cnt; } if ( rc_lp == 0 ) { p_trigger_item->lw_type = PCT_THRESHOLD; p_trigger_item->lw_percent = l_pct; } else if ( rc_lv == 0 ) { p_trigger_item->lw_type = VOL_THRESHOLD; p_trigger_item->lw_volume = l_vol; } else if ( rc_lc == 0 ) { p_trigger_item->lw_type = COUNT_THRESHOLD; p_trigger_item->lw_count = l_cnt; } /* retrieve check interval parameter */ rc = GetDurationParam( config_blk, block_name, "check_interval", INT_PARAM_POSITIVE | INT_PARAM_NOT_NULL | PARAM_MANDATORY, &tmpval, NULL, NULL, msg_out ); if ( rc ) return rc; p_trigger_item->check_interval = tmpval; rc = GetBoolParam( config_blk, block_name, "alert_high", 0, &tmpval, NULL, NULL, msg_out ); /* for backward compatibility */ if ( rc == ENOENT ) rc = GetBoolParam( config_blk, block_name, "notify_hw", 0, &tmpval, NULL, NULL, msg_out ); if ( rc == ENOENT ) rc = GetBoolParam( config_blk, block_name, "notify", 0, &tmpval, NULL, NULL, msg_out ); if ( ( rc != 0 ) && ( rc != ENOENT ) ) return rc; else if ( rc == 0 ) p_trigger_item->alert_hw = tmpval; rc = GetBoolParam( config_blk, block_name, "alert_low", 0, &tmpval, NULL, NULL, msg_out ); /* for backward compatibility */ if ( rc == ENOENT ) rc = GetBoolParam( config_blk, block_name, "alert_lw", 0, &tmpval, NULL, NULL, msg_out ); if ( ( rc != 0 ) && ( rc != ENOENT ) ) return rc; else if ( rc == 0 ) p_trigger_item->alert_lw = tmpval; CheckUnknownParameters( config_blk, block_name, trigger_expect ); return 0; }
/** read thresholds params, check their consistency and fills the trigger item. * @param[in] prefix "high" or "low" * @param[in] p_trigger to check compatibility with trigger type and target. */ static int read_threshold_params(config_item_t config_blk, const char *block_name, const char *prefix, const trigger_item_t *p_trigger, trigger_value_type_t *type, threshold_u *val, char *msg_out) { unsigned int cnt = 0; uint64_t tmpval; int rc; char buff[128]; /* oversized for param name */ rc = GetFloatParam(config_blk, block_name, mk_threshold_param(prefix, "pct", buff), PFLG_POSITIVE | PFLG_ALLOW_PCT_SIGN, &val->percent, NULL, NULL, msg_out); if ((rc != 0) && (rc != ENOENT)) /* real error */ return rc; if (rc == 0) { *type = PCT_THRESHOLD; cnt++; } rc = GetSizeParam(config_blk, block_name, mk_threshold_param(prefix, "vol", buff), PFLG_POSITIVE, &val->volume, NULL, NULL, msg_out); if ((rc != 0) && (rc != ENOENT)) return rc; if (rc == 0) { *type = VOL_THRESHOLD; cnt++; } rc = GetInt64Param(config_blk, block_name, mk_threshold_param(prefix, "cnt", buff), PFLG_POSITIVE, &tmpval, NULL, NULL, msg_out); if ((rc != 0) && (rc != ENOENT)) return rc; if (rc == 0) { *type = COUNT_THRESHOLD; /* unsigned long long to uint64_t */ val->count = (unsigned long long)tmpval; cnt++; } /* check params consistency */ if (p_trigger->trigger_type == TRIG_ALWAYS) { if (cnt > 0) { /* in case of 'periodic' triggers, no thresholds are expected */ strcpy(msg_out, "No high/low threshold expected for 'periodic' trigger"); return EINVAL; } else /* no extra check needed */ return 0; } if (cnt > 1) { sprintf(msg_out, "Multiple %s_threshold parameters in trigger", prefix); return EINVAL; } if (cnt == 0) { sprintf(msg_out, "No %s_threshold found in trigger (mandatory): " " '%s_threshold_pct', '%s_threshold_vol'" "or '%s_threshold_cnt' expected", prefix, prefix, prefix, prefix); return ENOENT; } /* count threshold is only support for global FS usage */ if ((*type == COUNT_THRESHOLD) && (p_trigger->target_type != TGT_FS) && (p_trigger->target_type != TGT_USER) && (p_trigger->target_type != TGT_GROUP)) { strcpy(msg_out, "Threshold on entry count is only supported " "for 'global_usage', 'user_usage' and 'group_usage' triggers"); return EINVAL; } return 0; }