| # |
| # |
| |
| # Copyright (C) 2015 Google Inc. |
| # All rights reserved. |
| # |
| # Redistribution and use in source and binary forms, with or without |
| # modification, are permitted provided that the following conditions are |
| # met: |
| # |
| # 1. Redistributions of source code must retain the above copyright notice, |
| # this list of conditions and the following disclaimer. |
| # |
| # 2. Redistributions in binary form must reproduce the above copyright |
| # notice, this list of conditions and the following disclaimer in the |
| # documentation and/or other materials provided with the distribution. |
| # |
| # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS |
| # IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
| # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR |
| # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
| # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
| # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| |
| |
| """Verification helpers for the configuration object.""" |
| |
| from ganeti import constants |
| from ganeti import errors |
| from ganeti import objects |
| from ganeti import utils |
| |
| |
| def ValidateConfig(data): |
| """Verifies that a configuration dict looks valid. |
| |
| This only verifies the version of the configuration. |
| |
| @raise errors.ConfigurationError: if the version differs from what |
| we expect |
| |
| """ |
| if data['version'] != constants.CONFIG_VERSION: |
| raise errors.ConfigVersionMismatch(constants.CONFIG_VERSION, |
| data['version']) |
| |
| |
| def VerifyType(owner, attr, value, template, callback): |
| """Checks if an attribute has correct form. |
| |
| @type owner: str |
| @param owner: name of the object containing the attribute |
| @type attr: str |
| @param attr: name of the attribute |
| @type value: dict |
| @param value: actual value of the attribute |
| @type template: dict |
| @param template: expected types of the keys |
| @type callback: callable |
| @param callback: will be called if there is an error |
| |
| """ |
| try: |
| utils.ForceDictType(value, template) |
| except errors.GenericError, err: |
| return callback("%s has invalid %s: %s" % (owner, attr, err)) |
| |
| |
| def VerifyNic(owner, params, callback): |
| """Checks if a NIC has correct form. |
| |
| @type owner: str |
| @param owner: name of the object containing the attribute |
| @type params: dict |
| @param params: actual value of the NIC parameters |
| @type callback: callable |
| @param callback: will be called if there is an error |
| |
| """ |
| try: |
| objects.NIC.CheckParameterSyntax(params) |
| except errors.ConfigurationError, err: |
| callback("%s has invalid nicparams: %s" % (owner, err)) |
| |
| |
| def VerifyIpolicy(owner, ipolicy, iscluster, callback): |
| """Checks if an ipolicy has correct form. |
| |
| @type owner: str |
| @param owner: name of the object containing the attribute |
| @type ipolicy: dict |
| @param ipolicy: actual value of the ipolicy parameters |
| @type iscluster: bool |
| @param iscluster: True iff the owner is the cluster |
| @type callback: callable |
| @param callback: will be called if there is an error |
| |
| """ |
| try: |
| objects.InstancePolicy.CheckParameterSyntax(ipolicy, iscluster) |
| except errors.ConfigurationError, err: |
| callback("%s has invalid instance policy: %s" % (owner, err)) |
| for key, value in ipolicy.items(): |
| if key == constants.ISPECS_MINMAX: |
| for k in range(len(value)): |
| VerifyIspecs(owner, "ipolicy/%s[%s]" % (key, k), value[k], callback) |
| elif key == constants.ISPECS_STD: |
| VerifyType(owner, "ipolicy/" + key, value, |
| constants.ISPECS_PARAMETER_TYPES, callback) |
| else: |
| # FIXME: assuming list type |
| if key in constants.IPOLICY_PARAMETERS: |
| exp_type = float |
| # if the value is int, it can be converted into float |
| convertible_types = [int] |
| else: |
| exp_type = list |
| convertible_types = [] |
| # Try to convert from allowed types, if necessary. |
| if any(isinstance(value, ct) for ct in convertible_types): |
| try: |
| value = exp_type(value) |
| ipolicy[key] = value |
| except ValueError: |
| pass |
| if not isinstance(value, exp_type): |
| callback("%s has invalid instance policy: for %s," |
| " expecting %s, got %s" % |
| (owner, key, exp_type.__name__, type(value))) |
| |
| |
| def VerifyIspecs(owner, parentkey, params, callback): |
| """Checks if an ispec has correct form. |
| |
| @type owner: str |
| @param owner: name of the object containing the attribute |
| @type parentkey: str |
| @param parentkey: the root name of the key |
| @type params: dict |
| @param params: actual value of the ispec parameters |
| @type callback: callable |
| @param callback: will be called if there is an error |
| |
| """ |
| for (key, value) in params.items(): |
| fullkey = "/".join([parentkey, key]) |
| VerifyType(owner, fullkey, value, constants.ISPECS_PARAMETER_TYPES, |
| callback) |