diff --git a/magnum/drivers/mesos_ubuntu_v1/template_def.py b/magnum/drivers/mesos_ubuntu_v1/template_def.py index 42c6c90865..fb5ca349a1 100644 --- a/magnum/drivers/mesos_ubuntu_v1/template_def.py +++ b/magnum/drivers/mesos_ubuntu_v1/template_def.py @@ -81,6 +81,12 @@ class UbuntuMesosTemplateDefinition(template_def.BaseTemplateDefinition): extra_params=extra_params, **kwargs) + def get_env_files(self, baymodel): + if baymodel.master_lb_enabled: + return ['environments/with_master_lb.yaml'] + else: + return ['environments/no_master_lb.yaml'] + @property def template_path(self): return os.path.join(os.path.dirname(os.path.realpath(__file__)), diff --git a/magnum/drivers/mesos_ubuntu_v1/templates/environments/no_master_lb.yaml b/magnum/drivers/mesos_ubuntu_v1/templates/environments/no_master_lb.yaml new file mode 100644 index 0000000000..3030cccbfd --- /dev/null +++ b/magnum/drivers/mesos_ubuntu_v1/templates/environments/no_master_lb.yaml @@ -0,0 +1,12 @@ +# Environment file to disable LBaaS in a Mesos cluster by mapping +# LBaaS-related resource types to OS::Heat::None +resource_registry: + "Magnum::ApiGatewaySwitcher": ../fragments/api_gateway_switcher_master.yaml + + # mesoscluster.yaml + "Magnum::Optional::Neutron::Pool": "OS::Heat::None" + "Magnum::Optional::Neutron::Pool::FloatingIP": "OS::Heat::None" + "Magnum::Optional::Neutron::Pool::HealthMonitor": "OS::Heat::None" + + # mesosmaster.yaml + "Magnum::Optional::Neutron::PoolMember": "OS::Heat::None" diff --git a/magnum/drivers/mesos_ubuntu_v1/templates/environments/with_master_lb.yaml b/magnum/drivers/mesos_ubuntu_v1/templates/environments/with_master_lb.yaml new file mode 100644 index 0000000000..5aae6bb803 --- /dev/null +++ b/magnum/drivers/mesos_ubuntu_v1/templates/environments/with_master_lb.yaml @@ -0,0 +1,12 @@ +# Environment file to enable LBaaS in a Mesos cluster by mapping +# LBaaS-related resource types to the real LBaaS resource types. +resource_registry: + "Magnum::ApiGatewaySwitcher": ../fragments/api_gateway_switcher_pool.yaml + + # mesoscluster.yaml + "Magnum::Optional::Neutron::Pool": "OS::Neutron::Pool" + "Magnum::Optional::Neutron::Pool::FloatingIP": "OS::Neutron::FloatingIP" + "Magnum::Optional::Neutron::Pool::HealthMonitor": "OS::Neutron::HealthMonitor" + + # mesosmaster.yaml + "Magnum::Optional::Neutron::PoolMember": "OS::Neutron::PoolMember" diff --git a/magnum/drivers/mesos_ubuntu_v1/templates/fragments/api_gateway_switcher_master.yaml b/magnum/drivers/mesos_ubuntu_v1/templates/fragments/api_gateway_switcher_master.yaml new file mode 100644 index 0000000000..d10437827a --- /dev/null +++ b/magnum/drivers/mesos_ubuntu_v1/templates/fragments/api_gateway_switcher_master.yaml @@ -0,0 +1,32 @@ +heat_template_version: 2013-05-23 + +description: > + This is a template resource that accepts public and private IPs from both + a Neutron LBaaS Pool and a master node. It connects the master inputs + to its outputs, essentially acting as one state of a multiplexer. + +parameters: + + pool_public_ip: + type: string + default: "" + + pool_private_ip: + type: string + default: "" + + master_public_ip: + type: string + default: "" + + master_private_ip: + type: string + default: "" + +outputs: + + public_ip: + value: {get_param: master_public_ip} + + private_ip: + value: {get_param: master_private_ip} diff --git a/magnum/drivers/mesos_ubuntu_v1/templates/fragments/api_gateway_switcher_pool.yaml b/magnum/drivers/mesos_ubuntu_v1/templates/fragments/api_gateway_switcher_pool.yaml new file mode 100644 index 0000000000..7a1384a4cf --- /dev/null +++ b/magnum/drivers/mesos_ubuntu_v1/templates/fragments/api_gateway_switcher_pool.yaml @@ -0,0 +1,32 @@ +heat_template_version: 2013-05-23 + +description: > + This is a template resource that accepts public and private IPs from both + a Neutron LBaaS Pool and a master node. It connects the pool inputs + to its outputs, essentially acting as one state of a multiplexer. + +parameters: + + pool_public_ip: + type: string + default: "" + + pool_private_ip: + type: string + default: "" + + master_public_ip: + type: string + default: "" + + master_private_ip: + type: string + default: "" + +outputs: + + public_ip: + value: {get_param: pool_public_ip} + + private_ip: + value: {get_param: pool_private_ip} diff --git a/magnum/drivers/mesos_ubuntu_v1/templates/mesoscluster.yaml b/magnum/drivers/mesos_ubuntu_v1/templates/mesoscluster.yaml index 62f69034fe..7d00b2b9b3 100644 --- a/magnum/drivers/mesos_ubuntu_v1/templates/mesoscluster.yaml +++ b/magnum/drivers/mesos_ubuntu_v1/templates/mesoscluster.yaml @@ -345,7 +345,7 @@ resources: # api_monitor: - type: OS::Neutron::HealthMonitor + type: Magnum::Optional::Neutron::Pool::HealthMonitor properties: type: TCP delay: 5 @@ -353,7 +353,7 @@ resources: timeout: 5 api_pool: - type: OS::Neutron::Pool + type: Magnum::Optional::Neutron::Pool properties: protocol: HTTP monitors: [{get_resource: api_monitor}] @@ -364,13 +364,25 @@ resources: description: API pool for Mesos bay api_pool_floating: - type: OS::Neutron::FloatingIP + type: Magnum::Optional::Neutron::Pool::FloatingIP depends_on: - extrouter_inside properties: floating_network: {get_param: external_network} port_id: {get_attr: [api_pool, vip, port_id]} + ###################################################################### + # + # resources that expose the IPs of either the mesos master or a given + # LBaaS pool depending on whether LBaaS is enabled for the bay. + # + + api_address_switch: + type: Magnum::ApiGatewaySwitcher + properties: + pool_public_ip: {get_attr: [api_pool_floating, floating_ip_address]} + master_public_ip: {get_attr: [mesos_masters, resource.0.mesos_master_external_ip]} + ###################################################################### # # Mesos masters. This is a resource group that will create @@ -441,7 +453,7 @@ resources: outputs: api_address: - value: {get_attr: [api_pool_floating, floating_ip_address]} + value: {get_attr: [api_address_switch, public_ip]} description: > This is the API endpoint of the Mesos master. Use this to access the Mesos API from outside the cluster. diff --git a/magnum/drivers/mesos_ubuntu_v1/templates/mesosmaster.yaml b/magnum/drivers/mesos_ubuntu_v1/templates/mesosmaster.yaml index e345692444..c2372002bb 100644 --- a/magnum/drivers/mesos_ubuntu_v1/templates/mesosmaster.yaml +++ b/magnum/drivers/mesos_ubuntu_v1/templates/mesosmaster.yaml @@ -78,7 +78,7 @@ resources: port_id: {get_resource: mesos_master_eth0} api_pool_member: - type: OS::Neutron::PoolMember + type: Magnum::Optional::Neutron::PoolMember properties: pool_id: {get_param: api_pool_id} address: {get_attr: [mesos_master_eth0, fixed_ips, 0, ip_address]} diff --git a/magnum/tests/unit/conductor/handlers/test_mesos_bay_conductor.py b/magnum/tests/unit/conductor/handlers/test_mesos_bay_conductor.py index 80dc17e2bc..24734992d6 100644 --- a/magnum/tests/unit/conductor/handlers/test_mesos_bay_conductor.py +++ b/magnum/tests/unit/conductor/handlers/test_mesos_bay_conductor.py @@ -45,7 +45,8 @@ class TestBayConductorWithMesos(base.TestCase): 'mesos_slave_image_providers': 'docker', 'mesos_slave_executor_env_variables': '{}', 'mesos_slave_work_dir': '/tmp/mesos/slave' - } + }, + 'master_lb_enabled': False, } self.bay_dict = { 'id': 1, @@ -120,7 +121,7 @@ class TestBayConductorWithMesos(base.TestCase): 'mesos_slave_image_providers': 'docker' } self.assertEqual(expected, definition) - self.assertEqual([], env_files) + self.assertEqual(['environments/no_master_lb.yaml'], env_files) @patch('magnum.objects.BayModel.get_by_uuid') def test_extract_template_definition_only_required( @@ -164,7 +165,102 @@ class TestBayConductorWithMesos(base.TestCase): 'mesos_slave_image_providers': 'docker' } self.assertEqual(expected, definition) - self.assertEqual([], env_files) + self.assertEqual(['environments/no_master_lb.yaml'], env_files) + + @patch('magnum.objects.BayModel.get_by_uuid') + def test_extract_template_definition_with_lb( + self, + mock_objects_baymodel_get_by_uuid): + self.baymodel_dict['master_lb_enabled'] = True + baymodel = objects.BayModel(self.context, **self.baymodel_dict) + mock_objects_baymodel_get_by_uuid.return_value = baymodel + bay = objects.Bay(self.context, **self.bay_dict) + + (template_path, + definition, + env_files) = bay_conductor._extract_template_definition(self.context, + bay) + + expected = { + 'ssh_key_name': 'keypair_id', + 'external_network': 'external_network_id', + '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': 'bay1', + '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', + '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' + } + self.assertEqual(expected, definition) + self.assertEqual(['environments/with_master_lb.yaml'], env_files) + + @patch('magnum.objects.BayModel.get_by_uuid') + def test_extract_template_definition_multi_master( + self, + mock_objects_baymodel_get_by_uuid): + self.baymodel_dict['master_lb_enabled'] = True + self.bay_dict['master_count'] = 2 + baymodel = objects.BayModel(self.context, **self.baymodel_dict) + mock_objects_baymodel_get_by_uuid.return_value = baymodel + bay = objects.Bay(self.context, **self.bay_dict) + + (template_path, + definition, + env_files) = bay_conductor._extract_template_definition(self.context, + bay) + + expected = { + 'ssh_key_name': 'keypair_id', + 'external_network': 'external_network_id', + 'dns_nameserver': 'dns_nameserver', + 'server_image': 'image_id', + 'master_flavor': 'master_flavor_id', + 'slave_flavor': 'flavor_id', + 'number_of_slaves': 1, + 'number_of_masters': 2, + 'http_proxy': 'http_proxy', + 'https_proxy': 'https_proxy', + 'no_proxy': 'no_proxy', + 'cluster_name': 'bay1', + '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', + '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' + } + self.assertEqual(expected, definition) + self.assertEqual(['environments/with_master_lb.yaml'], env_files) @patch('magnum.conductor.utils.retrieve_baymodel') @patch('oslo_config.cfg')