Add Magnum config for default network driver per COE

Problem description:
Magnum should provide support for configuration of default network drivers per
COE. An example use case could be a cloud operator who would like to have
control of what default container network driver should be used on a per-COE
basis. The cloud operator in this case should be able to set the default
network driver per COE in /etc/magnum/magnum.conf.

Proposed fix:
Add 3 configuration list options to the config in /etc/magnum/magnum.conf:
- kubernetes_default_network_driver
  (default='flannel')
- swarm_default_network_driver
  (default='docker')
- mesos_default_network_driver
  (default='docker')
When a baymodel is created and the --network-driver attribute is not supplied,
then the configured default network driver for the selected COE will first be
checked against the list of allowed network drivers for that COE, and if
allowed, the configured default network driver will be used for the new
baymodel.

Change-Id: I1e1d68c3348f609975b914926994bd79c1ef6d28
Closes-Bug: #1504664
This commit is contained in:
Dane LeBlanc 2015-11-05 12:39:07 -05:00 committed by Daneyon Hansen
parent 58cbafdc87
commit 471aa924fc
7 changed files with 112 additions and 61 deletions

View File

@ -375,16 +375,25 @@
# network drivers include flannel. (list value)
#kubernetes_allowed_network_drivers = all
# Allowed network drivers for docker swarm baymodels. Use 'all'
# keyword to allow all drivers supported for swarm baymodels.
# Supported network drivers include docker. (list value)
# Default network driver for kubernetes baymodels.
#kubernetes_default_network_driver = flannel
# Allowed network drivers for docker swarm baymodels. Use 'all' keyword
# to allow all drivers supported for swarm baymodels. Supported
# network drivers include docker. (list value)
#swarm_allowed_network_drivers = all
# Allowed network drivers for mesos baymodels. Use 'all' keyword to
# allow all drivers supported for mesos baymodels. Supported network
# drivers include docker. (list value)
# Default network driver for docker swarm baymodels.
#swarm_default_network_driver = docker
# Allowed network drivers for mesos baymodels. Use 'all' keyword
# to allow all drivers supported for mesos baymodels. Supported
# network drivers include docker. (list value)
#mesos_allowed_network_drivers = all
# Default network driver for mesos baymodels.
#mesos_default_network_driver = docker
[certificates]

View File

@ -14,7 +14,6 @@
import glanceclient.exc
import novaclient.exceptions as nova_exc
from oslo_config import cfg
from oslo_utils import timeutils
import pecan
from pecan import rest
@ -34,29 +33,6 @@ from magnum.common import policy
from magnum import objects
baymodel_opts = [
cfg.ListOpt('kubernetes_allowed_network_drivers',
default=['all'],
help="Allowed network drivers for kubernetes baymodels. "
"Use 'all' keyword to allow all drivers supported "
"for kubernetes baymodels. Supported network drivers "
"include flannel."),
cfg.ListOpt('swarm_allowed_network_drivers',
default=['all'],
help="Allowed network drivers for docker swarm baymodels. "
"Use 'all' keyword to allow all drivers supported "
"for swarm baymodels. Supported network drivers "
"include docker."),
cfg.ListOpt('mesos_allowed_network_drivers',
default=['all'],
help="Allowed network drivers for mesos baymodels. "
"Use 'all' keyword to allow all drivers supported "
"for mesos baymodels. Supported network drivers "
"include docker.")
]
cfg.CONF.register_opts(baymodel_opts, group='baymodel')
class BayModelPatchType(types.JsonPatchType):
pass

View File

@ -21,6 +21,38 @@ from magnum.common import exception
from magnum import objects
baymodel_opts = [
cfg.ListOpt('kubernetes_allowed_network_drivers',
default=['all'],
help="Allowed network drivers for kubernetes baymodels. "
"Use 'all' keyword to allow all drivers supported "
"for kubernetes baymodels. Supported network drivers "
"include flannel."),
cfg.StrOpt('kubernetes_default_network_driver',
default='flannel',
help="Default network driver for kubernetes baymodels."),
cfg.ListOpt('swarm_allowed_network_drivers',
default=['all'],
help="Allowed network drivers for docker swarm baymodels. "
"Use 'all' keyword to allow all drivers supported "
"for swarm baymodels. Supported network drivers "
"include docker."),
cfg.StrOpt('swarm_default_network_driver',
default='docker',
help="Default network driver for docker swarm baymodels."),
cfg.ListOpt('mesos_allowed_network_drivers',
default=['all'],
help="Allowed network drivers for mesos baymodels. "
"Use 'all' keyword to allow all drivers supported "
"for mesos baymodels. Supported network drivers "
"include docker."),
cfg.StrOpt('mesos_default_network_driver',
default='docker',
help="Default network driver for mesos baymodels."),
]
cfg.CONF.register_opts(baymodel_opts, group='baymodel')
def enforce_bay_types(*bay_types):
@decorator.decorator
def wrapper(func, *args, **kwargs):
@ -62,24 +94,29 @@ def enforce_network_driver_types_update():
def _enforce_network_driver_types(baymodel):
driver = baymodel.network_driver
if driver:
validator = Validator.get_coe_validator(baymodel.coe)
validator.validate_network_driver(driver)
validator = Validator.get_coe_validator(baymodel.coe)
if not baymodel.network_driver:
baymodel.network_driver = validator.default_driver
validator.validate_network_driver(baymodel.network_driver)
class Validator(object):
@staticmethod
def get_coe_validator(coe):
if coe == 'kubernetes':
return K8sValidator()
if coe == 'swarm':
return SwarmValidator()
if coe == 'mesos':
return MesosValidator()
raise exception.InvalidParameterValue(
'Requested COE type %s is not supported.' % coe)
validators = {}
@classmethod
def get_coe_validator(cls, coe):
if not cls.validators:
cls.validators = {
'kubernetes': K8sValidator(),
'swarm': SwarmValidator(),
'mesos': MesosValidator(),
}
if coe in cls.validators:
return cls.validators[coe]
else:
raise exception.InvalidParameterValue(
'Requested COE type %s is not supported.' % coe)
@classmethod
def validate_network_driver(cls, driver):
@ -100,32 +137,32 @@ class Validator(object):
@classmethod
def _validate_network_driver_allowed(cls, driver):
"""Confirm that driver is allowed via configuration for this COE."""
allowed_drivers = cfg.CONF.baymodel[cls.allowed_driver_config]
if ('all' not in allowed_drivers and
driver not in allowed_drivers):
if ('all' not in cls.allowed_drivers and
driver not in cls.allowed_drivers):
raise exception.InvalidParameterValue(
'Network driver type %(driver)s is not allowed, '
'expecting a %(allowed_drivers)s network driver. '
'Check %(config)s configuration.' % {
'expecting a %(allowed_drivers)s network driver. ' % {
'driver': driver,
'allowed_drivers': '/'.join(
allowed_drivers + ['unspecified']),
'config': cls.allowed_driver_config})
cls.allowed_drivers + ['unspecified'])})
class K8sValidator(Validator):
supported_drivers = ['flannel']
allowed_driver_config = 'kubernetes_allowed_network_drivers'
allowed_drivers = cfg.CONF.baymodel.kubernetes_allowed_network_drivers
default_driver = cfg.CONF.baymodel.kubernetes_default_network_driver
class SwarmValidator(Validator):
supported_drivers = ['docker']
allowed_driver_config = 'swarm_allowed_network_drivers'
allowed_drivers = cfg.CONF.baymodel.swarm_allowed_network_drivers
default_driver = cfg.CONF.baymodel.swarm_default_network_driver
class MesosValidator(Validator):
supported_drivers = ['docker']
allowed_driver_config = 'mesos_allowed_network_drivers'
allowed_drivers = cfg.CONF.baymodel.mesos_allowed_network_drivers
default_driver = cfg.CONF.baymodel.mesos_default_network_driver

View File

@ -17,7 +17,7 @@ import itertools
import magnum.api.app
import magnum.api.auth
import magnum.api.controllers.v1.baymodel
import magnum.api.validation
import magnum.common.cert_manager
from magnum.common.cert_manager import local_cert_manager
import magnum.common.clients
@ -57,5 +57,5 @@ def list_opts():
itertools.chain(magnum.common.cert_manager.cert_manager_opts,
local_cert_manager.local_cert_manager_opts,
)),
('baymodel', magnum.api.controllers.v1.baymodel.baymodel_opts),
('baymodel', magnum.api.validation.baymodel_opts),
]

View File

@ -49,8 +49,8 @@ def generate_random_coe():
def generate_random_coe_dep_network_driver(coe):
allowed_driver_types = {
'kubernetes': ['flannel', None],
'swarm': [None],
'mesos': [None],
'swarm': ['docker', None],
'mesos': ['docker', None],
}
driver_types = allowed_driver_types[coe]
return driver_types[random.randrange(0, len(driver_types))]

View File

@ -563,7 +563,11 @@ class TestPost(api_base.FunctionalTest):
if expect_errors:
self.assertEqual(400, response.status_int)
else:
self.assertEqual(bdict['network_driver'],
expected_driver = bdict.get('network_driver')
if not expected_driver:
expected_driver = (
cfg.CONF.baymodel.swarm_default_network_driver)
self.assertEqual(expected_driver,
response.json['network_driver'])
self.assertEqual(bdict['image_id'],
response.json['image_id'])

View File

@ -122,15 +122,18 @@ class TestValidation(base.BaseTestCase):
baymodel.network_driver = network_driver_type
baymodel.coe = coe
# Reload the validator module so that baymodel configs are
# re-evaluated.
reload(v)
validator = v.K8sValidator
validator.supported_drivers = ['flannel', 'type1', 'type2']
validator.allowed_driver_config = 'kubernetes_allowed_network_drivers'
if assert_raised:
self.assertRaises(exception.InvalidParameterValue,
test, self, baymodel)
else:
test(self, baymodel)
return baymodel
def test_enforce_network_driver_types_one_allowed_create(self):
self._test_enforce_network_driver_types_create(
@ -165,6 +168,26 @@ class TestValidation(base.BaseTestCase):
coe='invalid_coe_type',
assert_raised=True)
def test_enforce_network_driver_types_default_create(self):
baymodel = self._test_enforce_network_driver_types_create(
network_driver_type=None,
network_driver_config_dict={})
self.assertEqual('flannel', baymodel.network_driver)
def test_enforce_network_driver_types_default_config_create(self):
baymodel = self._test_enforce_network_driver_types_create(
network_driver_type=None,
network_driver_config_dict={
'kubernetes_default_network_driver': 'type1'})
self.assertEqual('type1', baymodel.network_driver)
def test_enforce_network_driver_types_default_invalid_create(self):
self._test_enforce_network_driver_types_create(
network_driver_type=None,
network_driver_config_dict={
'kubernetes_default_network_driver': 'invalid_driver'},
assert_raised=True)
@mock.patch('pecan.request')
@mock.patch('magnum.objects.BayModel.get_by_uuid')
def _test_enforce_network_driver_types_update(
@ -188,9 +211,11 @@ class TestValidation(base.BaseTestCase):
baymodel.coe = 'kubernetes'
mock_baymodel_get_by_uuid.return_value = baymodel
# Reload the validator module so that baymodel configs are
# re-evaluated.
reload(v)
validator = v.K8sValidator
validator.supported_drivers = ['flannel', 'type1', 'type2']
validator.allowed_driver_config = 'kubernetes_allowed_network_drivers'
if assert_raised:
self.assertRaises(exception.InvalidParameterValue,