Merge "Add support for Octavia resources in Heat"
This commit is contained in:
commit
ec08641e90
@ -367,6 +367,10 @@ class RegionsListFailed(MagnumException):
|
||||
message = _("Failed to list regions.")
|
||||
|
||||
|
||||
class ServicesListFailed(MagnumException):
|
||||
message = _("Failed to list services.")
|
||||
|
||||
|
||||
class TrusteeOrTrustToClusterFailed(MagnumException):
|
||||
message = _("Failed to create trustee or trust for Cluster: "
|
||||
"%(cluster_uuid)s")
|
||||
|
@ -291,3 +291,32 @@ class KeystoneClientV3(object):
|
||||
'region_name_list': '/'.join(
|
||||
region_list + ['unspecified'])})
|
||||
return region_name
|
||||
|
||||
|
||||
def is_octavia_enabled():
|
||||
"""Check if Octavia service is deployed in the cloud.
|
||||
|
||||
Octavia is already an official LBaaS solution for Openstack
|
||||
(https://governance.openstack.org/tc/reference/projects/octavia.html) and
|
||||
will deprecate the neutron-lbaas extension starting from Queens release.
|
||||
|
||||
We use Octavia instead of Neutron LBaaS API for load balancing
|
||||
functionality for k8s cluster if Octavia service is deployed and enabled
|
||||
in the cloud.
|
||||
"""
|
||||
# Put the import here to avoid circular importing.
|
||||
from magnum.common import context
|
||||
admin_context = context.make_admin_context()
|
||||
keystone = KeystoneClientV3(admin_context)
|
||||
|
||||
try:
|
||||
octavia_svc = keystone.client.services.list(type='load-balancer')
|
||||
except Exception:
|
||||
LOG.exception('Failed to list services')
|
||||
raise exception.ServicesListFailed()
|
||||
|
||||
# Always assume there is only one load balancing service configured.
|
||||
if octavia_svc and octavia_svc[0].enabled:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
@ -0,0 +1,14 @@
|
||||
# Environment file to enable LBaaS in a cluster by mapping
|
||||
# LBaaS-related resource types to the real Octavia resource types.
|
||||
resource_registry:
|
||||
"Magnum::ApiGatewaySwitcher": ../fragments/api_gateway_switcher_pool.yaml
|
||||
|
||||
# Cluster template
|
||||
"Magnum::Optional::Neutron::LBaaS::LoadBalancer": "OS::Octavia::LoadBalancer"
|
||||
"Magnum::Optional::Neutron::LBaaS::Listener": "OS::Octavia::Listener"
|
||||
"Magnum::Optional::Neutron::LBaaS::Pool": "OS::Octavia::Pool"
|
||||
"Magnum::Optional::Neutron::LBaaS::HealthMonitor": "OS::Octavia::HealthMonitor"
|
||||
"Magnum::Optional::Neutron::LBaaS::FloatingIP": "OS::Neutron::FloatingIP"
|
||||
|
||||
# Master node template
|
||||
"Magnum::Optional::Neutron::LBaaS::PoolMember": "OS::Octavia::PoolMember"
|
@ -20,6 +20,7 @@ import six
|
||||
|
||||
from magnum.common import clients
|
||||
from magnum.common import exception
|
||||
from magnum.common import keystone
|
||||
from magnum.common import utils
|
||||
import magnum.conf
|
||||
|
||||
@ -328,7 +329,10 @@ class BaseTemplateDefinition(TemplateDefinition):
|
||||
|
||||
def add_lb_env_file(env_files, cluster_template):
|
||||
if cluster_template.master_lb_enabled:
|
||||
env_files.append(COMMON_ENV_PATH + 'with_master_lb.yaml')
|
||||
if keystone.is_octavia_enabled():
|
||||
env_files.append(COMMON_ENV_PATH + 'with_master_lb_octavia.yaml')
|
||||
else:
|
||||
env_files.append(COMMON_ENV_PATH + 'with_master_lb.yaml')
|
||||
else:
|
||||
env_files.append(COMMON_ENV_PATH + 'no_master_lb.yaml')
|
||||
|
||||
|
@ -207,8 +207,10 @@ class TestClusterConductorWithMesos(base.TestCase):
|
||||
|
||||
@patch('magnum.objects.ClusterTemplate.get_by_uuid')
|
||||
@patch('magnum.drivers.common.driver.Driver.get_driver')
|
||||
def test_extract_template_definition_with_lb(
|
||||
@patch('magnum.common.keystone.KeystoneClientV3')
|
||||
def test_extract_template_definition_with_lb_neutron(
|
||||
self,
|
||||
mock_kc,
|
||||
mock_driver,
|
||||
mock_objects_cluster_template_get_by_uuid):
|
||||
self.cluster_template_dict['master_lb_enabled'] = True
|
||||
@ -219,6 +221,8 @@ class TestClusterConductorWithMesos(base.TestCase):
|
||||
cluster = objects.Cluster(self.context, **self.cluster_dict)
|
||||
mock_driver.return_value = mesos_dr.Driver()
|
||||
|
||||
mock_kc.return_value.client.services.list.return_value = []
|
||||
|
||||
(template_path,
|
||||
definition,
|
||||
env_files) = mock_driver()._extract_template_definition(self.context,
|
||||
@ -266,8 +270,78 @@ class TestClusterConductorWithMesos(base.TestCase):
|
||||
|
||||
@patch('magnum.objects.ClusterTemplate.get_by_uuid')
|
||||
@patch('magnum.drivers.common.driver.Driver.get_driver')
|
||||
@patch('magnum.common.keystone.KeystoneClientV3')
|
||||
def test_extract_template_definition_with_lb_octavia(
|
||||
self,
|
||||
mock_kc,
|
||||
mock_driver,
|
||||
mock_objects_cluster_template_get_by_uuid):
|
||||
self.cluster_template_dict['master_lb_enabled'] = True
|
||||
cluster_template = objects.ClusterTemplate(
|
||||
self.context, **self.cluster_template_dict)
|
||||
mock_objects_cluster_template_get_by_uuid.return_value = \
|
||||
cluster_template
|
||||
cluster = objects.Cluster(self.context, **self.cluster_dict)
|
||||
mock_driver.return_value = mesos_dr.Driver()
|
||||
|
||||
class Service(object):
|
||||
def __init__(self):
|
||||
self.enabled = True
|
||||
|
||||
mock_kc.return_value.client.services.list.return_value = [Service()]
|
||||
|
||||
(template_path,
|
||||
definition,
|
||||
env_files) = mock_driver()._extract_template_definition(self.context,
|
||||
cluster)
|
||||
|
||||
expected = {
|
||||
'ssh_key_name': 'keypair_id',
|
||||
'external_network': 'external_network_id',
|
||||
'fixed_network': 'fixed_network',
|
||||
'fixed_subnet': 'fixed_subnet',
|
||||
'dns_nameserver': 'dns_nameserver',
|
||||
'server_image': 'image_id',
|
||||
'master_flavor': 'master_flavor_id',
|
||||
'slave_flavor': 'flavor_id',
|
||||
'number_of_slaves': 1,
|
||||
'number_of_masters': 1,
|
||||
'http_proxy': 'http_proxy',
|
||||
'https_proxy': 'https_proxy',
|
||||
'no_proxy': 'no_proxy',
|
||||
'cluster_name': 'cluster1',
|
||||
'trustee_domain_id': self.mock_keystone.trustee_domain_id,
|
||||
'trustee_username': 'fake_trustee',
|
||||
'trustee_password': 'fake_trustee_password',
|
||||
'trustee_user_id': '7b489f04-b458-4541-8179-6a48a553e656',
|
||||
'trust_id': '',
|
||||
'volume_driver': 'volume_driver',
|
||||
'auth_url': 'http://192.168.10.10:5000/v3',
|
||||
'region_name': self.mock_osc.cinder_region_name.return_value,
|
||||
'username': 'mesos_user',
|
||||
'tenant_name': 'admin',
|
||||
'domain_name': 'domainname',
|
||||
'rexray_preempt': 'False',
|
||||
'mesos_slave_executor_env_variables': '{}',
|
||||
'mesos_slave_isolation': 'docker/runtime,filesystem/linux',
|
||||
'mesos_slave_work_dir': '/tmp/mesos/slave',
|
||||
'mesos_slave_image_providers': 'docker',
|
||||
'verify_ca': True,
|
||||
'openstack_ca': '',
|
||||
}
|
||||
self.assertEqual(expected, definition)
|
||||
self.assertEqual(
|
||||
['../../common/templates/environments/no_private_network.yaml',
|
||||
'../../common/templates/environments/with_master_lb_octavia.yaml'
|
||||
],
|
||||
env_files)
|
||||
|
||||
@patch('magnum.objects.ClusterTemplate.get_by_uuid')
|
||||
@patch('magnum.drivers.common.driver.Driver.get_driver')
|
||||
@patch('magnum.common.keystone.KeystoneClientV3')
|
||||
def test_extract_template_definition_multi_master(
|
||||
self,
|
||||
mock_kc,
|
||||
mock_driver,
|
||||
mock_objects_cluster_template_get_by_uuid):
|
||||
self.cluster_template_dict['master_lb_enabled'] = True
|
||||
@ -279,6 +353,8 @@ class TestClusterConductorWithMesos(base.TestCase):
|
||||
cluster = objects.Cluster(self.context, **self.cluster_dict)
|
||||
mock_driver.return_value = mesos_dr.Driver()
|
||||
|
||||
mock_kc.return_value.client.services.list.return_value = []
|
||||
|
||||
(template_path,
|
||||
definition,
|
||||
env_files) = mock_driver()._extract_template_definition(self.context,
|
||||
|
@ -330,8 +330,10 @@ class TestClusterConductorWithSwarm(base.TestCase):
|
||||
@patch('requests.get')
|
||||
@patch('magnum.objects.ClusterTemplate.get_by_uuid')
|
||||
@patch('magnum.drivers.common.driver.Driver.get_driver')
|
||||
def test_extract_template_definition_with_lb(
|
||||
@patch('magnum.common.keystone.KeystoneClientV3')
|
||||
def test_extract_template_definition_with_lb_neutron(
|
||||
self,
|
||||
mock_kc,
|
||||
mock_driver,
|
||||
mock_objects_cluster_template_get_by_uuid,
|
||||
mock_get):
|
||||
@ -348,6 +350,8 @@ class TestClusterConductorWithSwarm(base.TestCase):
|
||||
mock_driver.return_value = swarm_dr.Driver()
|
||||
cluster = objects.Cluster(self.context, **self.cluster_dict)
|
||||
|
||||
mock_kc.return_value.client.services.list.return_value = []
|
||||
|
||||
(template_path,
|
||||
definition,
|
||||
env_files) = mock_driver()._extract_template_definition(self.context,
|
||||
@ -403,8 +407,92 @@ class TestClusterConductorWithSwarm(base.TestCase):
|
||||
@patch('requests.get')
|
||||
@patch('magnum.objects.ClusterTemplate.get_by_uuid')
|
||||
@patch('magnum.drivers.common.driver.Driver.get_driver')
|
||||
@patch('magnum.common.keystone.KeystoneClientV3')
|
||||
def test_extract_template_definition_with_lb_octavia(
|
||||
self,
|
||||
mock_kc,
|
||||
mock_driver,
|
||||
mock_objects_cluster_template_get_by_uuid,
|
||||
mock_get):
|
||||
self.cluster_template_dict['master_lb_enabled'] = True
|
||||
cluster_template = objects.ClusterTemplate(
|
||||
self.context, **self.cluster_template_dict)
|
||||
mock_objects_cluster_template_get_by_uuid.return_value = \
|
||||
cluster_template
|
||||
expected_result = str('{"action":"get","node":{"key":"test","value":'
|
||||
'"1","modifiedIndex":10,"createdIndex":10}}')
|
||||
mock_resp = mock.MagicMock()
|
||||
mock_resp.text = expected_result
|
||||
mock_get.return_value = mock_resp
|
||||
mock_driver.return_value = swarm_dr.Driver()
|
||||
cluster = objects.Cluster(self.context, **self.cluster_dict)
|
||||
|
||||
class Service(object):
|
||||
def __init__(self):
|
||||
self.enabled = True
|
||||
|
||||
mock_kc.return_value.client.services.list.return_value = [Service()]
|
||||
|
||||
(template_path,
|
||||
definition,
|
||||
env_files) = mock_driver()._extract_template_definition(self.context,
|
||||
cluster)
|
||||
|
||||
expected = {
|
||||
'ssh_key_name': 'keypair_id',
|
||||
'external_network': 'external_network_id',
|
||||
'fixed_network': 'fixed_network',
|
||||
'fixed_subnet': 'fixed_subnet',
|
||||
'dns_nameserver': 'dns_nameserver',
|
||||
'server_image': 'image_id',
|
||||
'master_flavor': 'master_flavor_id',
|
||||
'node_flavor': 'flavor_id',
|
||||
'number_of_masters': 1,
|
||||
'number_of_nodes': 1,
|
||||
'docker_volume_size': 20,
|
||||
'docker_storage_driver': 'devicemapper',
|
||||
'discovery_url': 'https://discovery.test.io/123456789',
|
||||
'http_proxy': 'http_proxy',
|
||||
'https_proxy': 'https_proxy',
|
||||
'no_proxy': 'no_proxy',
|
||||
'cluster_uuid': '5d12f6fd-a196-4bf0-ae4c-1f639a523a52',
|
||||
'magnum_url': self.mock_osc.magnum_url.return_value,
|
||||
'tls_disabled': False,
|
||||
'registry_enabled': False,
|
||||
'network_driver': 'network_driver',
|
||||
'flannel_network_cidr': '10.101.0.0/16',
|
||||
'flannel_network_subnetlen': '26',
|
||||
'flannel_backend': 'vxlan',
|
||||
'trustee_domain_id': self.mock_keystone.trustee_domain_id,
|
||||
'trustee_username': 'fake_trustee',
|
||||
'trustee_password': 'fake_trustee_password',
|
||||
'trustee_user_id': '7b489f04-b458-4541-8179-6a48a553e656',
|
||||
'trust_id': 'bd11efc5-d4e2-4dac-bbce-25e348ddf7de',
|
||||
'auth_url': 'http://192.168.10.10:5000/v3',
|
||||
'swarm_version': 'fake-version',
|
||||
'swarm_strategy': u'spread',
|
||||
'volume_driver': 'rexray',
|
||||
'rexray_preempt': 'False',
|
||||
'docker_volume_type': 'lvmdriver-1',
|
||||
'verify_ca': True,
|
||||
'openstack_ca': '',
|
||||
'nodes_affinity_policy': 'soft-anti-affinity'
|
||||
}
|
||||
self.assertEqual(expected, definition)
|
||||
self.assertEqual(
|
||||
['../../common/templates/environments/no_private_network.yaml',
|
||||
'../../common/templates/environments/with_volume.yaml',
|
||||
'../../common/templates/environments/with_master_lb_octavia.yaml'
|
||||
],
|
||||
env_files)
|
||||
|
||||
@patch('requests.get')
|
||||
@patch('magnum.objects.ClusterTemplate.get_by_uuid')
|
||||
@patch('magnum.drivers.common.driver.Driver.get_driver')
|
||||
@patch('magnum.common.keystone.KeystoneClientV3')
|
||||
def test_extract_template_definition_multi_master(
|
||||
self,
|
||||
mock_kc,
|
||||
mock_driver,
|
||||
mock_objects_cluster_template_get_by_uuid,
|
||||
mock_get):
|
||||
@ -422,6 +510,8 @@ class TestClusterConductorWithSwarm(base.TestCase):
|
||||
mock_driver.return_value = swarm_dr.Driver()
|
||||
cluster = objects.Cluster(self.context, **self.cluster_dict)
|
||||
|
||||
mock_kc.return_value.client.services.list.return_value = []
|
||||
|
||||
(template_path,
|
||||
definition,
|
||||
env_files) = mock_driver()._extract_template_definition(self.context,
|
||||
|
Loading…
x
Reference in New Issue
Block a user