Merge "Add support for Octavia resources in Heat"

This commit is contained in:
Zuul 2018-02-21 11:35:38 +00:00 committed by Gerrit Code Review
commit ec08641e90
6 changed files with 220 additions and 3 deletions

View File

@ -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")

View File

@ -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

View File

@ -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"

View File

@ -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')

View File

@ -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,

View File

@ -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,