diff --git a/os_faults/__init__.py b/os_faults/__init__.py index c091968..598e6a0 100644 --- a/os_faults/__init__.py +++ b/os_faults/__init__.py @@ -13,6 +13,7 @@ import os import appdirs +import jsonschema import pbr.version import yaml @@ -36,6 +37,32 @@ CONFIG_FILES = [ for s in ['.json', '.yaml', '.yml'] ] +CONFIG_SCHEMA = { + 'type': 'object', + '$schema': 'http://json-schema.org/draft-04/schema#', + 'properties': { + 'cloud_management': { + 'type': 'object', + 'properties': { + 'driver': {'type': 'string'}, + 'args': {'type': 'object'}, + }, + 'required': ['driver', 'args'], + 'additionalProperties': False, + }, + 'power_management': { + 'type': 'object', + 'properties': { + 'driver': {'type': 'string'}, + 'args': {'type': 'object'}, + }, + 'required': ['driver', 'args'], + 'additionalProperties': False, + } + }, + 'required': ['cloud_management'], +} + def _read_config(config_filename): os_faults_config = config_filename or os.environ.get('OS_FAULTS_CONFIG') @@ -53,7 +80,8 @@ def _read_config(config_filename): def _init_driver(params): driver_cls = registry.get_driver(params['driver']) - return driver_cls(params.get('args', {})) + jsonschema.validate(params['args'], driver_cls.CONFIG_SCHEMA) + return driver_cls(params['args']) def connect(cloud_config=None, config_filename=None): @@ -66,13 +94,12 @@ def connect(cloud_config=None, config_filename=None): if cloud_config is None: cloud_config = _read_config(config_filename) - if 'cloud_management' not in cloud_config: - raise error.OSFError('Cloud management driver name is not specified') + jsonschema.validate(cloud_config, CONFIG_SCHEMA) cloud_management_conf = cloud_config['cloud_management'] cloud_management = _init_driver(cloud_management_conf) - power_management_conf = cloud_config.get('power_management', {}) + power_management_conf = cloud_config.get('power_management') if power_management_conf: power_management = _init_driver(power_management_conf) cloud_management.set_power_management(power_management) diff --git a/os_faults/drivers/devstack.py b/os_faults/drivers/devstack.py index 30a606f..0c265db 100644 --- a/os_faults/drivers/devstack.py +++ b/os_faults/drivers/devstack.py @@ -100,6 +100,18 @@ class DevStackManagement(cloud_management.CloudManagement): DESCRIPTION = 'Single node DevStack management driver' SUPPORTED_SERVICES = list(SERVICE_NAME_TO_CLASS.keys()) SUPPORTED_NETWORKS = ['all-in-one'] + CONFIG_SCHEMA = { + 'type': 'object', + '$schema': 'http://json-schema.org/draft-04/schema#', + 'properties': { + 'address': {'type': 'string'}, + 'username': {'type': 'string'}, + 'private_key': {'type': 'string'}, + + }, + 'required': ['address', 'username'], + 'additionalProperties': False, + } def __init__(self, cloud_management_params): super(DevStackManagement, self).__init__() diff --git a/os_faults/drivers/fuel.py b/os_faults/drivers/fuel.py index f1e252e..447ee78 100644 --- a/os_faults/drivers/fuel.py +++ b/os_faults/drivers/fuel.py @@ -446,6 +446,18 @@ class FuelManagement(cloud_management.CloudManagement): DESCRIPTION = 'Fuel 9.x cloud management driver' SUPPORTED_SERVICES = list(SERVICE_NAME_TO_CLASS.keys()) SUPPORTED_NETWORKS = ['management', 'private', 'public', 'storage'] + CONFIG_SCHEMA = { + 'type': 'object', + '$schema': 'http://json-schema.org/draft-04/schema#', + 'properties': { + 'address': {'type': 'string'}, + 'username': {'type': 'string'}, + 'private_key_file': {'type': 'string'}, + + }, + 'required': ['address', 'username'], + 'additionalProperties': False, + } def __init__(self, cloud_management_params): super(FuelManagement, self).__init__() diff --git a/os_faults/drivers/ipmi.py b/os_faults/drivers/ipmi.py index c710dcd..e7facd1 100644 --- a/os_faults/drivers/ipmi.py +++ b/os_faults/drivers/ipmi.py @@ -24,6 +24,28 @@ from os_faults import utils class IPMIDriver(power_management.PowerManagement): NAME = 'ipmi' DESCRIPTION = 'IPMI power management driver' + CONFIG_SCHEMA = { + 'type': 'object', + '$schema': 'http://json-schema.org/draft-04/schema#', + 'properties': { + 'mac_to_bmc': { + 'type': 'object', + 'patternProperties': { + '^([0-9A-Fa-f]{2}:){5}[0-9A-Fa-f]{2}$': { + 'type': 'object', + 'properties': { + 'address': {'type': 'string'}, + 'username': {'type': 'string'}, + 'password': {'type': 'string'}, + }, + 'required': ['address', 'username', 'password'] + } + } + } + }, + 'required': ['mac_to_bmc'], + 'additionalProperties': False, + } def __init__(self, params): self.mac_to_bmc = params['mac_to_bmc'] diff --git a/os_faults/drivers/libvirt_driver.py b/os_faults/drivers/libvirt_driver.py index 1ce67fd..e9cd698 100644 --- a/os_faults/drivers/libvirt_driver.py +++ b/os_faults/drivers/libvirt_driver.py @@ -23,6 +23,16 @@ from os_faults import utils class LibvirtDriver(power_management.PowerManagement): NAME = 'libvirt' DESCRIPTION = 'Libvirt power management driver' + CONFIG_SCHEMA = { + 'type': 'object', + '$schema': 'http://json-schema.org/draft-04/schema#', + 'properties': { + 'connection_uri': {'type': 'string'}, + + }, + 'required': ['connection_uri'], + 'additionalProperties': False, + } def __init__(self, params): self.connection_uri = params['connection_uri'] diff --git a/os_faults/tests/unit/test_os_faults.py b/os_faults/tests/unit/test_os_faults.py index 1adbf2f..1f190d5 100644 --- a/os_faults/tests/unit/test_os_faults.py +++ b/os_faults/tests/unit/test_os_faults.py @@ -11,9 +11,10 @@ # under the License. import os -import yaml +import jsonschema import mock +import yaml import os_faults from os_faults.api import error @@ -93,6 +94,7 @@ class OSFaultsTestCase(test.TestCase): cloud_config = { 'cloud_management': { 'driver': 'non-existing', + 'args': {}, } } self.assertRaises( @@ -100,7 +102,8 @@ class OSFaultsTestCase(test.TestCase): def test_connect_driver_not_specified(self): cloud_config = {'foo': 'bar'} - self.assertRaises(error.OSFError, os_faults.connect, cloud_config) + self.assertRaises( + jsonschema.ValidationError, os_faults.connect, cloud_config) @mock.patch('os.path.exists', return_value=True) def test_connect_with_config_file(self, mock_os_path_exists): diff --git a/requirements.txt b/requirements.txt index 7a72d2d..37a9d1f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,6 +6,7 @@ pbr>=1.6 ansible>=2.0 appdirs>=1.3.0 # MIT License +jsonschema>=2.0.0,!=2.5.0,<3.0.0 # MIT iso8601>=0.1.9 oslo.i18n>=1.5.0 # Apache-2.0 oslo.log>=1.12.0 # Apache-2.0