diff options
| author | Gaurav <gaurav@gluster.com> | 2011-03-23 00:50:17 +0000 | 
|---|---|---|
| committer | Vijay Bellur <vijay@dev.gluster.com> | 2011-03-23 04:55:29 -0700 | 
| commit | 9bd4f25b6b0ea8103324b685fcc21525a29849a8 (patch) | |
| tree | 7b0e0b875934521dea0c6fdd3412ac61972a527e /libglusterfs/src | |
| parent | 6f6c817314a2a867be996c2ad6d9a1337617ded4 (diff) | |
CLI : Validate options farmework.
Signed-off-by: Gaurav <gaurav@gluster.com>
Signed-off-by: Vijay Bellur <vijay@dev.gluster.com>
BUG: 2064 (NFS options are removed upon glusterd restart)
URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=2064
Diffstat (limited to 'libglusterfs/src')
| -rw-r--r-- | libglusterfs/src/xlator.c | 612 | ||||
| -rw-r--r-- | libglusterfs/src/xlator.h | 20 | 
2 files changed, 623 insertions, 9 deletions
diff --git a/libglusterfs/src/xlator.c b/libglusterfs/src/xlator.c index fd10eb097..b9952120d 100644 --- a/libglusterfs/src/xlator.c +++ b/libglusterfs/src/xlator.c @@ -105,6 +105,548 @@ fill_defaults (xlator_t *xl)  	return;  } +int  +_volume_option_value_validate_attacherr (xlator_t *xl, +                               data_pair_t *pair, +                               volume_option_t *opt, +                               char **op_errstr) +{ +        int       i = 0; +        int       ret = -1; +        uint64_t  input_size = 0; +        long long inputll = 0; +        char      errstr[256] = {0, }; + +        /* Key is valid, validate the option */ +        switch (opt->type) { +        case GF_OPTION_TYPE_PATH: +        { +                if (strstr (pair->value->data, "../")) { +                        gf_log (xl->name, GF_LOG_ERROR, +                                "invalid path given '%s'", +                                pair->value->data); +                        snprintf (errstr, 256, +                                  "invalid path given '%s'", +                                  pair->value->data); + +                        *op_errstr = gf_strdup (errstr); +                        ret = -1; +                        goto out; +                } + +                /* Make sure the given path is valid */ +                if (pair->value->data[0] != '/') { +                        gf_log (xl->name, GF_LOG_WARNING, +                                "option %s %s: '%s' is not an " +                                "absolute path name", +                                pair->key, pair->value->data, +                                pair->value->data); +                        snprintf (errstr, 256, +                                  "option %s %s: '%s' is not an " +                                  "absolute path name", +                                  pair->key, pair->value->data, +                                  pair->value->data); + +                        *op_errstr = gf_strdup (errstr); +                        goto out; +                } +                ret = 0; +        } +        break; +        case GF_OPTION_TYPE_INT: +        { +                /* Check the range */ +                if (gf_string2longlong (pair->value->data, +                                        &inputll) != 0) { +                        gf_log (xl->name, GF_LOG_ERROR, +                                "invalid number format \"%s\" in " +                                "\"option %s\"", +                                pair->value->data, pair->key); +                        snprintf (errstr, 256, +                                  "invalid number format \"%s\" in " +                                "\"option %s\"", +                                pair->value->data, pair->key); + +                        *op_errstr = gf_strdup (errstr); +                        goto out; +                } + +                if ((opt->min == 0) && (opt->max == 0)) { +                        gf_log (xl->name, GF_LOG_DEBUG, +                                "no range check required for " +                                "'option %s %s'", +                                pair->key, pair->value->data); +                        ret = 0; +                        break; +                } +                if ((inputll < opt->min) || +                    (inputll > opt->max)) { +                        gf_log (xl->name, GF_LOG_WARNING, +                                "'%lld' in 'option %s %s' is out of " +                                "range [%"PRId64" - %"PRId64"]", +                                inputll, pair->key, +                                pair->value->data, +                                opt->min, opt->max); +                        snprintf (errstr, 256, +                                  "'%lld' in 'option %s %s' is out of " +                                "range [%"PRId64" - %"PRId64"]", +                                inputll, pair->key, +                                pair->value->data, +                                opt->min, opt->max); + +                        *op_errstr = gf_strdup (errstr); +                        goto out; +                } +                ret = 0; +        } +        break; +        case GF_OPTION_TYPE_SIZET: +        { +                /* Check the range */ +                if (gf_string2bytesize (pair->value->data, +                                        &input_size) != 0) { +                        gf_log (xl->name, GF_LOG_ERROR, +                                "invalid size format \"%s\" in " +                                "\"option %s\"", +                                pair->value->data, pair->key); +                        snprintf (errstr, 256, +                                  "invalid size format \"%s\" in " +                                  "\"option %s\"", +                                  pair->value->data, pair->key); + +                        *op_errstr = gf_strdup (errstr); +                        goto out; +                } + +                if ((opt->min == 0) && (opt->max == 0)) { +                        gf_log (xl->name, GF_LOG_DEBUG, +                                "no range check required for " +                                "'option %s %s'", +                                pair->key, pair->value->data); +                        ret = 0; +                        break; +                } +                if ((input_size < opt->min) || +                    (input_size > opt->max)) { +                        gf_log (xl->name, GF_LOG_ERROR, +                                "'%"PRId64"' in 'option %s %s' is " +                                "out of range [%"PRId64" - %"PRId64"]", +                                input_size, pair->key, +                                pair->value->data, +                                opt->min, opt->max); +                        snprintf (errstr, 256, +                                  "'%"PRId64"' in 'option %s %s' is " +                                "out of range [%"PRId64" - %"PRId64"]", +                                input_size, pair->key, +                                pair->value->data, +                                opt->min, opt->max); + +                        *op_errstr = gf_strdup (errstr); +                        goto out; +                } +                ret = 0; +        } +        break; +        case GF_OPTION_TYPE_BOOL: +        { +                /* Check if the value is one of +                   '0|1|on|off|no|yes|true|false|enable|disable' */ +                gf_boolean_t bool_value; +                if (gf_string2boolean (pair->value->data, +                                       &bool_value) != 0) { +                        gf_log (xl->name, GF_LOG_ERROR, +                                "option %s %s: '%s' is not a valid " +                                "boolean value", +                                pair->key, pair->value->data, +                                pair->value->data); +                        snprintf (errstr, 256, +                                   "option %s %s: '%s' is not a valid " +                                   "boolean value", +                                   pair->key, pair->value->data, +                                   pair->value->data); + +                        *op_errstr = gf_strdup (errstr); +                        goto out; +                } +                ret = 0; +        } +        break; +        case GF_OPTION_TYPE_XLATOR: +        { +                /* Check if the value is one of the xlators */ +                xlator_t *xlopt = xl; +                while (xlopt->prev) +                        xlopt = xlopt->prev; + +                while (xlopt) { +                        if (strcmp (pair->value->data, +                                    xlopt->name) == 0) { +                                ret = 0; +                                break; +                        } +                        xlopt = xlopt->next; +                } +                if (!xlopt) { +                        gf_log (xl->name, GF_LOG_ERROR, +                                "option %s %s: '%s' is not a " +                                "valid volume name", +                                pair->key, pair->value->data, +                                pair->value->data); +                        snprintf (errstr, 256, +                                  "option %s %s: '%s' is not a " +                                  "valid volume name", +                                  pair->key, pair->value->data, +                                  pair->value->data); + +                        *op_errstr = gf_strdup (errstr); +                        goto out; +                } +                ret = 0; +        } +        break; +        case GF_OPTION_TYPE_STR: +        { +                /* Check if the '*str' is valid */ +                if (GF_OPTION_LIST_EMPTY(opt)) { +                        ret = 0; +                        goto out; +                } + +                for (i = 0; (i < ZR_OPTION_MAX_ARRAY_SIZE) && +                             opt->value[i]; i++) { +                        if (fnmatch (opt->value[i], pair->value->data, +                                     FNM_EXTMATCH) == 0) { +                                ret = 0; +                                break; +                        } +                } + +                if ((i == ZR_OPTION_MAX_ARRAY_SIZE) +                    || ((i < ZR_OPTION_MAX_ARRAY_SIZE) +                        && (!opt->value[i]))) { +                        /* enter here only if +                         * 1. reached end of opt->value array and haven't +                         *    validated input +                         *                      OR +                         * 2. valid input list is less than +                         *    ZR_OPTION_MAX_ARRAY_SIZE and input has not +                         *    matched all possible input values. +                         */ +                        char given_array[4096] = {0,}; +                        for (i = 0; (i < ZR_OPTION_MAX_ARRAY_SIZE) && +                                     opt->value[i]; i++) { +                                strcat (given_array, opt->value[i]); +                                strcat (given_array, ", "); +                        } + +                        gf_log (xl->name, GF_LOG_ERROR, +                                "option %s %s: '%s' is not valid " +                                "(possible options are %s)", +                                pair->key, pair->value->data, +                                pair->value->data, given_array); +                        snprintf (errstr, 256, +                                  "option %s %s: '%s' is not valid " +                                  "(possible options are %s)", +                                  pair->key, pair->value->data, +                                  pair->value->data, given_array); + +                        *op_errstr = gf_strdup (errstr); +                        goto out; +                } +        } +        break; +        case GF_OPTION_TYPE_PERCENT: +        { +                uint32_t percent = 0; + + +                /* Check if the value is valid percentage */ +                if (gf_string2percent (pair->value->data, +                                       &percent) != 0) { +                        gf_log (xl->name, GF_LOG_ERROR, +                                "invalid percent format \"%s\" " +                                "in \"option %s\"", +                                pair->value->data, pair->key); +                        snprintf (errstr, 256, +                                  "invalid percent format \"%s\" " +                                  "in \"option %s\"", +                                  pair->value->data, pair->key); + +                        *op_errstr = gf_strdup (errstr); +                        goto out; +                } + +                if ((percent < 0) || (percent > 100)) { +                        gf_log (xl->name, GF_LOG_ERROR, +                                "'%d' in 'option %s %s' is out of " +                                "range [0 - 100]", +                                percent, pair->key, +                                pair->value->data); +                        snprintf (errstr, 256, +                                   "'%d' in 'option %s %s' is out of " +                                "range [0 - 100]", +                                percent, pair->key, +                                pair->value->data); + +                        *op_errstr = gf_strdup (errstr); +                        goto out; +                } +                ret = 0; +        } +        break; +        case GF_OPTION_TYPE_PERCENT_OR_SIZET: +        { +                uint32_t percent = 0; +                uint64_t input_size = 0; + +                /* Check if the value is valid percentage */ +                if (gf_string2percent (pair->value->data, +                                       &percent) == 0) { +                        if (percent > 100) { +                                gf_log (xl->name, GF_LOG_DEBUG, +                                        "value given was greater than 100, " +                                        "assuming this is actually a size"); +                                if (gf_string2bytesize (pair->value->data, +                                                        &input_size) == 0) { +                                        /* Check the range */ +                                        if ((opt->min == 0) && +                                            (opt->max == 0)) { +                                                gf_log (xl->name, GF_LOG_DEBUG, +                                                        "no range check " +                                                        "required for " +                                                        "'option %s %s'", +                                                        pair->key, +                                                        pair->value->data); +                                                // It is a size +                                                ret = 0; +                                                goto out; +                                        } +                                        if ((input_size < opt->min) || +                                            (input_size > opt->max)) { +                                                gf_log (xl->name, GF_LOG_ERROR, +                                                        "'%"PRId64"' in " +                                                        "'option %s %s' is out" +                                                        " of range [%"PRId64"" +                                                        "- %"PRId64"]", +                                                        input_size, pair->key, +                                                        pair->value->data, +                                                        opt->min, opt->max); +                                                 snprintf (errstr, 256, +                                                          "'%"PRId64"' in " +                                                          "'option %s %s' is " +                                                          " out of range [" +                                                          "%"PRId64"- %"PRId64"]", +                                                          input_size, pair->key, +                                                          pair->value->data, +                                                          opt->min, opt->max); + +                                                *op_errstr = gf_strdup (errstr); +                                                goto out; +                                        } +                                        // It is a size +                                        ret = 0; +                                        goto out; +                                } else { +                                        // It's not a percent or size +                                        gf_log (xl->name, GF_LOG_ERROR, +                                        "invalid number format \"%s\" " +                                        "in \"option %s\"", +                                        pair->value->data, pair->key); + +                                        snprintf (errstr, 256, +                                        "invalid number format \"%s\" " +                                        "in \"option %s\"", +                                        pair->value->data, pair->key); + + +                                        *op_errstr = gf_strdup (errstr); +                                        goto out; +                                } + +                        } +                        // It is a percent +                        ret = 0; +                        goto out; +                } else { +                        if (gf_string2bytesize (pair->value->data, +                                                &input_size) == 0) { +                                /* Check the range */ +                                if ((opt->min == 0) && (opt->max == 0)) { +                                        gf_log (xl->name, GF_LOG_DEBUG, +                                                "no range check required for " +                                                "'option %s %s'", +                                                pair->key, pair->value->data); +                                        // It is a size +                                        ret = 0; +                                        goto out; +                                } +                                if ((input_size < opt->min) || +                                    (input_size > opt->max)) { +                                        gf_log (xl->name, GF_LOG_ERROR, +                                                "'%"PRId64"' in 'option %s %s'" +                                                " is out of range [%"PRId64" -" +                                                " %"PRId64"]", +                                                input_size, pair->key, +                                                pair->value->data, +                                                opt->min, opt->max); +                                        snprintf (errstr, 256, +                                                  "'%"PRId64"' in 'option %s %s'" +                                                  " is out of range [%"PRId64" -" +                                                  " %"PRId64"]", +                                                  input_size, pair->key, +                                                  pair->value->data, +                                                  opt->min, opt->max); + +                                        *op_errstr = gf_strdup (errstr); +                                        goto out; +                                } +                        } else { +                                // It's not a percent or size +                                gf_log (xl->name, GF_LOG_ERROR, +                                        "invalid number format \"%s\" " +                                        "in \"option %s\"", +                                        pair->value->data, pair->key); +                                snprintf (errstr, 256, +                                          "invalid number format \"%s\" " +                                          "in \"option %s\"", +                                          pair->value->data, pair->key); + +                                *op_errstr = gf_strdup (errstr); +                                goto out; +                        } +                        //It is a size +                        ret = 0; +                        goto out; +                } + +        } +        break; +        case GF_OPTION_TYPE_TIME: +        { +                uint32_t input_time = 0; + +                /* Check if the value is valid percentage */ +                if (gf_string2time (pair->value->data, +                                    &input_time) != 0) { +                        gf_log (xl->name, +                                GF_LOG_ERROR, +                                "invalid time format \"%s\" in " +                                "\"option %s\"", +                                pair->value->data, pair->key); + +                        snprintf (errstr, 256, +                                  "invalid time format \"%s\" in " +                                  "\"option %s\"", +                                  pair->value->data, pair->key); + +                        *op_errstr = gf_strdup (errstr); +                        goto out; +                } + +                if ((opt->min == 0) && (opt->max == 0)) { +                        gf_log (xl->name, GF_LOG_DEBUG, +                                "no range check required for " +                                "'option %s %s'", +                                pair->key, pair->value->data); +                        ret = 0; +                        goto out; +                } +                if ((input_time < opt->min) || +                    (input_time > opt->max)) { +                        gf_log (xl->name, GF_LOG_ERROR, +                                "'%"PRIu32"' in 'option %s %s' is " +                                "out of range [%"PRId64" - %"PRId64"]", +                                input_time, pair->key, +                                pair->value->data, +                                opt->min, opt->max); + +                        snprintf (errstr, 256, +                                  "'%"PRIu32"' in 'option %s %s' is " +                                  "out of range [%"PRId64" - %"PRId64"]", +                                  input_time, pair->key, +                                  pair->value->data, +                                  opt->min, opt->max); + +                        *op_errstr = gf_strdup (errstr); +                        goto out; +                } +                ret = 0; +        } +        break; +        case GF_OPTION_TYPE_DOUBLE: +        { +                double input_time = 0.0; + +                /* Check if the value is valid double */ +                if (gf_string2double (pair->value->data, +                                      &input_time) != 0) { +                        gf_log (xl->name, +                                GF_LOG_ERROR, +                                "invalid double \"%s\" in \"option %s\"", +                                pair->value->data, pair->key); + +                        snprintf (errstr, 256, +                                  "invalid double \"%s\" in \"option %s\"", +                                  pair->value->data, pair->key); + +                        *op_errstr = gf_strdup (errstr); +                        goto out; +                } + +                if (input_time < 0.0) { +                        gf_log (xl->name, +                                GF_LOG_ERROR, +                                "invalid time format \"%s\" in \"option %s\"", +                                pair->value->data, pair->key); + +                        snprintf (errstr, 256, +                                  "invalid double \"%s\" in \"option %s\"", +                                  pair->value->data, pair->key); + +                        *op_errstr = gf_strdup (errstr); +                        goto out; +                } + +                if ((opt->min == 0) && (opt->max == 0)) { +                        gf_log (xl->name, GF_LOG_DEBUG, +                                "no range check required for 'option %s %s'", +                                pair->key, pair->value->data); +                        ret = 0; +                        goto out; +                } +                ret = 0; +        } +        break; +        case GF_OPTION_TYPE_INTERNET_ADDRESS: +        { +                if (valid_internet_address (pair->value->data)) { +                        ret = 0; +                } else { +                        gf_log (xl->name, GF_LOG_ERROR, "internet address '%s'" +                                " does not conform to standards.", +                                pair->value->data); + +                        snprintf (errstr, 256, +                                  "internet address '%s'" +                                  " does not conform to standards.", +                                  pair->value->data); + +                        *op_errstr = gf_strdup (errstr); +                        goto out; +                } +        } +        break; +        case GF_OPTION_TYPE_ANY: +                /* NO CHECK */ +                ret = 0; +                break; +        } + +out: +        return ret; +} + +  int  _volume_option_value_validate (xlator_t *xl,  			       data_pair_t *pair, @@ -498,6 +1040,71 @@ out:  }  int +validate_xlator_volume_options_attacherr (xlator_t *xl, +                                          volume_option_t *opt, +                                          char **op_errstr) +{ +        int i = 0; +        int ret = -1; +        int index = 0; +        volume_option_t *trav  = NULL; +        data_pair_t     *pairs = NULL; + +        if (!opt) { +                ret = 0; +                goto out; +        } + +        /* First search for not supported options, if any report error */ +        pairs = xl->options->members_list; +        while (pairs) { +                ret = -1; +                for (index = 0; +                     opt[index].key && opt[index].key[0] ; index++) { +                        trav = &(opt[index]); +                        for (i = 0 ; +                             (i < ZR_VOLUME_MAX_NUM_KEY) && +                                     trav->key[i]; i++) { +                                /* Check if the key is valid */ +                                if (fnmatch (trav->key[i], +                                             pairs->key, FNM_NOESCAPE) == 0) { +                                        ret = 0; +                                        break; +                                } +                        } +                        if (!ret) { +                                if (i) { +                                        gf_log (xl->name, GF_LOG_WARNING, +                                                "option '%s' is deprecated, " +                                                "preferred is '%s', continuing" +                                                " with correction", +                                                trav->key[i], trav->key[0]); +                                        /* TODO: some bytes lost */ +                                        pairs->key = gf_strdup (trav->key[0]); +                                } +                                break; +                        } +                } +                if (!ret) { +                        ret = _volume_option_value_validate_attacherr (xl, +                                                                       pairs, +                                                                       trav, +                                                                       op_errstr); +                        if (-1 == ret) { +                                goto out; +                        } +                } + +                pairs = pairs->next; +        } + +        ret = 0; + out: +        return ret; +} + + +int  validate_xlator_volume_options (xlator_t *xl, volume_option_t *opt)  {  	int i = 0; @@ -888,9 +1495,8 @@ xlator_validate_rec (xlator_t *xlator, char **op_errstr)                  gf_log ("", GF_LOG_DEBUG, "Did not load the symbols");          if (xlator->validate_options) { -                if (xlator->validate_options (xlator, xlator->options, -                    op_errstr)) { -                        gf_log ("", GF_LOG_INFO, "%s", *op_errstr); +                if (xlator->validate_options (xlator, op_errstr)) { +                        gf_log ("", GF_LOG_DEBUG, "%s", *op_errstr);                          return -1;                  }                  gf_log (xlator->name, GF_LOG_DEBUG, "Validated option"); diff --git a/libglusterfs/src/xlator.h b/libglusterfs/src/xlator.h index 604c8c08f..e587ae578 100644 --- a/libglusterfs/src/xlator.h +++ b/libglusterfs/src/xlator.h @@ -771,8 +771,8 @@ typedef struct volume_options {          char                *key[ZR_VOLUME_MAX_NUM_KEY];          /* different key, same meaning */          volume_option_type_t type; -        int64_t              min;  /* -1 means no range */ -        int64_t              max;  /* -1 means no range */ +        int64_t              min;  /* 0 means no range */ +        int64_t              max;  /* 0 means no range */          char                *value[ZR_OPTION_MAX_ARRAY_SIZE];          /* If specified, will check for one of             the value from this array */ @@ -806,10 +806,9 @@ struct _xlator {          void              (*fini) (xlator_t *this);          int32_t           (*init) (xlator_t *this);          int32_t           (*reconfigure) (xlator_t *this, dict_t *options); -        int32_t           (*mem_acct_init) (xlator_t *this); -        int32_t           (*validate_options) (xlator_t *this, dict_t *options, -                                               char **op_errstr); -        event_notify_fn_t notify; +	int32_t           (*mem_acct_init) (xlator_t *this); +        int32_t           (*validate_options) (xlator_t *this, char **op_errstr); +	event_notify_fn_t notify;          gf_loglevel_t    loglevel;   /* Log level for translator */ @@ -865,5 +864,14 @@ int is_gf_log_command (xlator_t *trans, const char *name, char *value);  int xlator_validate_rec (xlator_t *xlator, char **op_errstr);  int graph_reconf_validateopt (glusterfs_graph_t *graph, char **op_errstr);  int glusterd_check_log_level (const char *value); +int validate_xlator_volume_options_attacherr (xlator_t *xl, +                                          volume_option_t *opt, +                                         char **op_errstr); +int _volume_option_value_validate_attacherr (xlator_t *xl,  +                               data_pair_t *pair,  +                               volume_option_t *opt,  +                               char **op_errstr); + +  #endif /* _XLATOR_H */  | 
