From da135bfd3039ec4af0e848326bc5cfada1dc8ee4 Mon Sep 17 00:00:00 2001 From: "Sean M. Collins" Date: Fri, 24 Apr 2015 09:22:55 -0400 Subject: [PATCH] Neutron VxLAN support The patch changes GRE in UI and Nailgun to more generic TUN segmentation type, letting fuel-library decide what tunnels to use (VxLAN will be used by default in 7.0) Implements: blueprint neutron-vxlan-support Change-Id: Ifa63b7f149dfa021aa5898674bc16c1955cdb787 Co-Authored-By: Oleg Bondarev --- .../nailgun/api/v1/validators/node_group.py | 7 ++-- nailgun/nailgun/consts.py | 3 +- .../alembic_migrations/versions/fuel_7_0.py | 26 +++++++++++++++ nailgun/nailgun/fixtures/openstack.yaml | 18 ++++++++--- nailgun/nailgun/objects/node.py | 3 +- .../orchestrator/neutron_serializers.py | 25 +++++++++------ .../test/integration/test_network_manager.py | 12 +++++++ .../integration/test_network_validation.py | 32 +++++++++++++++++++ .../integration/test_node_nic_assignment.py | 6 ++++ .../test_orchestrator_serializer.py | 12 +++++++ .../test_orchestrator_serializer_70.py | 16 +++++++--- .../test/unit/test_migration_fuel_7_0.py | 30 +++++++++++++++++ nailgun/nailgun/test/unit/test_node_groups.py | 16 ++++++++++ nailgun/static/models.js | 4 +-- nailgun/static/translations/core.json | 6 ++-- .../views/cluster_page_tabs/network_tab.jsx | 2 +- 16 files changed, 190 insertions(+), 28 deletions(-) diff --git a/nailgun/nailgun/api/v1/validators/node_group.py b/nailgun/nailgun/api/v1/validators/node_group.py index 4b6fbd6c30..e3704dc28b 100644 --- a/nailgun/nailgun/api/v1/validators/node_group.py +++ b/nailgun/nailgun/api/v1/validators/node_group.py @@ -26,10 +26,11 @@ class NodeGroupValidator(BasicValidator): data = cls.validate_json(data) cluster = objects.Cluster.get_by_uid(data['cluster_id']) if (cluster.net_provider == consts.CLUSTER_NET_PROVIDERS.nova_network - or cluster.network_config.segmentation_type != - consts.NEUTRON_SEGMENT_TYPES.gre): + or cluster.network_config.segmentation_type == + consts.NEUTRON_SEGMENT_TYPES.vlan): raise errors.NotAllowed( - "Node groups can only be created when using Neutron GRE." + "Node groups can only be created when using Neutron tunneling " + "segmentation type." ) return data diff --git a/nailgun/nailgun/consts.py b/nailgun/nailgun/consts.py index 7ca64c9e71..0976ab6be8 100644 --- a/nailgun/nailgun/consts.py +++ b/nailgun/nailgun/consts.py @@ -84,7 +84,8 @@ NEUTRON_L23_PROVIDERS = Enum( NEUTRON_SEGMENT_TYPES = Enum( 'vlan', - 'gre' + 'gre', + 'tun' ) NODE_STATUSES = Enum( diff --git a/nailgun/nailgun/db/migration/alembic_migrations/versions/fuel_7_0.py b/nailgun/nailgun/db/migration/alembic_migrations/versions/fuel_7_0.py index 5c7fecca6a..2950c34b9d 100644 --- a/nailgun/nailgun/db/migration/alembic_migrations/versions/fuel_7_0.py +++ b/nailgun/nailgun/db/migration/alembic_migrations/versions/fuel_7_0.py @@ -98,6 +98,7 @@ def upgrade(): extensions_field_upgrade() set_deployable_false_for_old_releases() upgrade_node_labels() + extend_segmentation_type() def downgrade(): @@ -115,6 +116,7 @@ def downgrade(): extend_ip_addrs_model_downgrade() downgrade_task_names() vms_conf_downgrade() + extend_segmentation_type_downgrade() op.execute('UPDATE clusters SET name=LEFT(name, 50)') op.alter_column('clusters', 'name', type_=sa.VARCHAR(50)) @@ -334,6 +336,30 @@ def extend_plugin_model_downgrade(): op.drop_column('plugins', 'network_roles_metadata') +def extend_segmentation_type(): + + segmentation_type_old = ('vlan', 'gre') + segmentation_type_new = ('vlan', 'gre', 'tun') + + upgrade_enum('neutron_config', + 'segmentation_type', + 'segmentation_type', + segmentation_type_old, + segmentation_type_new) + + +def extend_segmentation_type_downgrade(): + + segmentation_type_old = ('vlan', 'gre') + segmentation_type_new = ('vlan', 'gre', 'tun') + + upgrade_enum('neutron_config', + 'segmentation_type', + 'segmentation_type', + segmentation_type_new, + segmentation_type_old) + + def upgrade_node_roles_metadata(): connection = op.get_bind() select_query = sa.sql.text("SELECT id, roles_metadata FROM releases") diff --git a/nailgun/nailgun/fixtures/openstack.yaml b/nailgun/nailgun/fixtures/openstack.yaml index cddfb8bed0..e301fbaf6a 100644 --- a/nailgun/nailgun/fixtures/openstack.yaml +++ b/nailgun/nailgun/fixtures/openstack.yaml @@ -400,6 +400,16 @@ render_addr_mask: "private" map_priority: 2 configurable: true + - name: "private" + seg_type: "tun" + cidr: "192.168.2.0/24" + vlan_start: 103 + use_gateway: false + notation: "cidr" + render_type: "cidr" + render_addr_mask: "private" + map_priority: 2 + configurable: true config: vlan_range: [1000, 1030] gre_id_range: [2, 65535] @@ -1214,14 +1224,14 @@ bind: - "cluster:net_provider": "neutron" - "cluster:net_segment_type": "vlan" - - data: "neutron-gre" - label: "dialog.create_cluster_wizard.network.neutr_gre" - description: "dialog.create_cluster_wizard.network.neutr_gre_description" + - data: "neutron-tun" + label: "dialog.create_cluster_wizard.network.neutr_tun" + description: "dialog.create_cluster_wizard.network.neutr_tun_description" restrictions: - "Compute.vcenter == true": "dialog.create_cluster_wizard.network.hypervisor_alert" bind: - "cluster:net_provider": "neutron" - - "cluster:net_segment_type": "gre" + - "cluster:net_segment_type": "tun" - data: "nova-network" label: "dialog.create_cluster_wizard.network.nova_network" description: "dialog.create_cluster_wizard.network.nova_network_description" diff --git a/nailgun/nailgun/objects/node.py b/nailgun/nailgun/objects/node.py index 8379f43e36..264247fc93 100644 --- a/nailgun/nailgun/objects/node.py +++ b/nailgun/nailgun/objects/node.py @@ -911,7 +911,8 @@ class NodeCollection(NailgunCollection): netmanager.assign_ips(instances, 'management') netmanager.assign_ips(instances, 'public') netmanager.assign_ips(instances, 'storage') - if nst == consts.NEUTRON_SEGMENT_TYPES.gre: + if nst in (consts.NEUTRON_SEGMENT_TYPES.gre, + consts.NEUTRON_SEGMENT_TYPES.tun): netmanager.assign_ips(instances, 'private') netmanager.assign_admin_ips(instances) diff --git a/nailgun/nailgun/orchestrator/neutron_serializers.py b/nailgun/nailgun/orchestrator/neutron_serializers.py index bd898d1001..2501bbb54d 100644 --- a/nailgun/nailgun/orchestrator/neutron_serializers.py +++ b/nailgun/nailgun/orchestrator/neutron_serializers.py @@ -340,8 +340,9 @@ class NeutronNetworkDeploymentSerializer(NetworkDeploymentSerializer): 'br-prv' ] }) - elif node.cluster.network_config.segmentation_type == \ - consts.NEUTRON_SEGMENT_TYPES.gre: + elif node.cluster.network_config.segmentation_type in \ + (consts.NEUTRON_SEGMENT_TYPES.gre, + consts.NEUTRON_SEGMENT_TYPES.tun): attrs['roles']['mesh'] = 'br-mgmt' return attrs @@ -447,8 +448,9 @@ class NeutronNetworkDeploymentSerializer(NetworkDeploymentSerializer): } } } - if cluster.network_config.segmentation_type == \ - consts.NEUTRON_SEGMENT_TYPES.gre: + if cluster.network_config.segmentation_type in \ + (consts.NEUTRON_SEGMENT_TYPES.gre, + consts.NEUTRON_SEGMENT_TYPES.tun): res["tunnel_id_ranges"] = utils.join_range( cluster.network_config.gre_id_range) elif cluster.network_config.segmentation_type == \ @@ -615,8 +617,9 @@ class NeutronNetworkDeploymentSerializer61( provider='ovs', mtu=65000)) - elif node.cluster.network_config.segmentation_type == \ - consts.NEUTRON_SEGMENT_TYPES.gre: + elif node.cluster.network_config.segmentation_type in \ + (consts.NEUTRON_SEGMENT_TYPES.gre, + consts.NEUTRON_SEGMENT_TYPES.tun): transformations.append( cls.add_bridge('br-mesh')) @@ -691,8 +694,9 @@ class NeutronNetworkDeploymentSerializer61( if is_public: netgroup_mapping.append(('public', 'br-ex')) - if node.cluster.network_config.segmentation_type == \ - consts.NEUTRON_SEGMENT_TYPES.gre: + if node.cluster.network_config.segmentation_type in \ + (consts.NEUTRON_SEGMENT_TYPES.gre, + consts.NEUTRON_SEGMENT_TYPES.tun): netgroup_mapping.append(('private', 'br-mesh')) attrs['endpoints']['br-mesh'] = {} attrs['roles']['neutron/mesh'] = 'br-mesh' @@ -891,8 +895,9 @@ class NeutronNetworkDeploymentSerializer70( mapping.update(old_mapping_6_1) attrs['roles'] = mapping - if node.cluster.network_config.segmentation_type == \ - consts.NEUTRON_SEGMENT_TYPES.gre: + if node.cluster.network_config.segmentation_type in \ + (consts.NEUTRON_SEGMENT_TYPES.gre, + consts.NEUTRON_SEGMENT_TYPES.tun): attrs['roles'].pop('neutron/private', None) if node.cluster.network_config.segmentation_type == \ diff --git a/nailgun/nailgun/test/integration/test_network_manager.py b/nailgun/nailgun/test/integration/test_network_manager.py index e66178fe3e..3255a7fa8f 100644 --- a/nailgun/nailgun/test/integration/test_network_manager.py +++ b/nailgun/nailgun/test/integration/test_network_manager.py @@ -479,6 +479,18 @@ class TestNeutronManager(BaseIntegrationTest): self.check_networks_assignment(self.env.nodes[0]) + def test_tun_get_default_nic_assignment(self): + self.env.create( + cluster_kwargs={ + 'net_provider': 'neutron', + 'net_segment_type': 'tun'}, + nodes_kwargs=[ + {'api': True, + 'pending_addition': True} + ]) + + self.check_networks_assignment(self.env.nodes[0]) + def test_vlan_get_default_nic_assignment(self): meta = self.env.default_metadata() self.env.set_interfaces_in_meta( diff --git a/nailgun/nailgun/test/integration/test_network_validation.py b/nailgun/nailgun/test/integration/test_network_validation.py index 63136af949..6471736b44 100644 --- a/nailgun/nailgun/test/integration/test_network_validation.py +++ b/nailgun/nailgun/test/integration/test_network_validation.py @@ -735,3 +735,35 @@ class TestNeutronHandlersVlan(TestNetworkChecking): "VLAN ID range defined for Neutron L2. " "Networks VLAN tags must not intersect " "with Neutron L2 VLAN ID range.") + + +class TestNeutronHandlersTun(TestNetworkChecking): + + def setUp(self): + super(TestNeutronHandlersTun, self).setUp() + meta = self.env.default_metadata() + self.env.set_interfaces_in_meta(meta, [ + {"name": "eth0", "mac": "00:00:00:00:00:66"}, + {"name": "eth1", "mac": "00:00:00:00:00:77"}]) + self.env.create( + cluster_kwargs={ + 'net_provider': 'neutron', + 'net_segment_type': 'tun' + }, + nodes_kwargs=[ + {'api': True, + 'pending_addition': True, + 'meta': meta} + ] + ) + self.cluster = self.env.clusters[0] + resp = self.env.neutron_networks_get(self.cluster.id) + self.nets = resp.json_body + + def test_network_checking(self): + self.update_neutron_networks_success(self.cluster.id, self.nets) + + ngs_created = self.db.query(NetworkGroup).filter( + NetworkGroup.name.in_([n['name'] for n in self.nets['networks']]) + ).all() + self.assertEqual(len(ngs_created), len(self.nets['networks'])) diff --git a/nailgun/nailgun/test/integration/test_node_nic_assignment.py b/nailgun/nailgun/test/integration/test_node_nic_assignment.py index ffc1cad35f..7b2a1124b3 100644 --- a/nailgun/nailgun/test/integration/test_node_nic_assignment.py +++ b/nailgun/nailgun/test/integration/test_node_nic_assignment.py @@ -546,6 +546,12 @@ class TestNodePublicNetworkToNICAssignment(BaseIntegrationTest): net_segment_type='gre') self.create_node_and_check_assignment() + def test_neutron_tun_public_network_assigned_to_second_nic_by_name(self): + self.env.create_cluster(api=True, + net_provider='neutron', + net_segment_type='tun') + self.create_node_and_check_assignment() + def test_neutron_vlan_public_network_assigned_to_second_nic_by_name(self): self.env.create_cluster(api=True, net_provider='neutron', diff --git a/nailgun/nailgun/test/integration/test_orchestrator_serializer.py b/nailgun/nailgun/test/integration/test_orchestrator_serializer.py index e0fa6b6efa..190c281f55 100644 --- a/nailgun/nailgun/test/integration/test_orchestrator_serializer.py +++ b/nailgun/nailgun/test/integration/test_orchestrator_serializer.py @@ -1840,6 +1840,18 @@ class TestNeutronOrchestratorSerializer(OrchestratorSerializerTestBase): self.assertEqual( 'private' in (fact['network_scheme']['roles']), False) + def test_tun_segmentation(self): + cluster = self.create_env('ha_compact', 'tun') + facts = self.serializer.serialize(cluster, cluster.nodes) + + for fact in facts: + self.assertEqual( + fact['quantum_settings']['L2']['segmentation_type'], 'tun') + self.assertNotIn( + 'br-prv', fact['network_scheme']['endpoints']) + self.assertNotIn( + 'private', fact['network_scheme']['roles']) + def test_gw_added_but_default_gw_is_ex_or_admin(self): self.new_env_release_version = '2014.2.-6.0' cluster = self.create_env('ha_compact', 'gre') diff --git a/nailgun/nailgun/test/integration/test_orchestrator_serializer_70.py b/nailgun/nailgun/test/integration/test_orchestrator_serializer_70.py index 7e46288e09..3b8b2325ca 100644 --- a/nailgun/nailgun/test/integration/test_orchestrator_serializer_70.py +++ b/nailgun/nailgun/test/integration/test_orchestrator_serializer_70.py @@ -104,8 +104,9 @@ class TestDeploymentAttributesSerialization70( consts.NEUTRON_SEGMENT_TYPES.vlan: expected_roles += [('neutron/private', 'br-prv')] - if node.cluster.network_config.segmentation_type == \ - consts.NEUTRON_SEGMENT_TYPES.gre: + if node.cluster.network_config.segmentation_type in \ + (consts.NEUTRON_SEGMENT_TYPES.gre, + consts.NEUTRON_SEGMENT_TYPES.tun): expected_roles += [('neutron/mesh', 'br-mesh')] self.assertEqual(roles, dict(expected_roles)) @@ -168,8 +169,9 @@ class TestDeploymentAttributesSerialization70( network_roles += zip( self.public, [ip_by_net['public']] * len(self.public)) - if node.cluster.network_config.segmentation_type == \ - consts.NEUTRON_SEGMENT_TYPES.gre: + if node.cluster.network_config.segmentation_type in \ + (consts.NEUTRON_SEGMENT_TYPES.gre, + consts.NEUTRON_SEGMENT_TYPES.tun): network_roles += zip( self.private, [ip_by_net['private']] * len(self.private)) @@ -186,6 +188,12 @@ class TestDeploymentAttributesSerializationSegmentationGre70( segmentation_type = consts.NEUTRON_SEGMENT_TYPES.gre +class TestDeploymentAttributesSerializationSegmentationTun70( + TestDeploymentAttributesSerialization70 +): + segmentation_type = consts.NEUTRON_SEGMENT_TYPES.tun + + class TestDeploymentSerializationForNovaNetwork70(BaseDeploymentSerializer): @mock.patch.object(models.Release, 'environment_version', new_callable=mock.PropertyMock(return_value='7.0')) diff --git a/nailgun/nailgun/test/unit/test_migration_fuel_7_0.py b/nailgun/nailgun/test/unit/test_migration_fuel_7_0.py index 0018e3ab7e..10f9f6dfd9 100644 --- a/nailgun/nailgun/test/unit/test_migration_fuel_7_0.py +++ b/nailgun/nailgun/test/unit/test_migration_fuel_7_0.py @@ -767,3 +767,33 @@ class TestNodeLabelsMigration(base.BaseAlembicMigrationTest): ).fetchone()[0] ) self.assertEqual(default_labels, {}) + + +class TestTunSegmentType(base.BaseAlembicMigrationTest): + + def test_tun_segment_type_added(self): + result = db.execute( + self.meta.tables['networking_configs'].insert(), + [{ + 'cluster_id': None, + 'dns_nameservers': ['8.8.8.8'], + 'floating_ranges': [], + 'configuration_template': None, + }]) + db.execute( + self.meta.tables['neutron_config'].insert(), + [{ + 'id': result.inserted_primary_key[0], + 'vlan_range': [], + 'gre_id_range': [], + 'base_mac': '00:00:00:00:00:00', + 'internal_cidr': '10.10.10.00/24', + 'internal_gateway': '10.10.10.01', + 'segmentation_type': 'tun', + 'net_l23_provider': 'ovs' + }]) + types = db.execute( + sa.select( + [self.meta.tables['neutron_config'].c.segmentation_type])).\ + fetchall() + self.assertIn(('tun',), types) diff --git a/nailgun/nailgun/test/unit/test_node_groups.py b/nailgun/nailgun/test/unit/test_node_groups.py index 8200a2ff26..c9dbe85946 100644 --- a/nailgun/nailgun/test/unit/test_node_groups.py +++ b/nailgun/nailgun/test/unit/test_node_groups.py @@ -116,3 +116,19 @@ class TestNodeGroups(BaseIntegrationTest): ) self.assertEquals(resp.status_code, 403) + + def test_nodegroup_tun_segmentation_type(self): + cluster = self.env.create_cluster( + api=False, + net_provider='neutron', + net_segment_type='tun' + ) + resp = self.app.post( + reverse('NodeGroupCollectionHandler'), + json.dumps({'cluster_id': cluster['id'], 'name': 'test_ng'}), + headers=self.default_headers, + expect_errors=True + ) + + self.assertEquals(resp.status_code, 201) + self.assertEquals(resp.json_body['cluster'], cluster['id']) diff --git a/nailgun/static/models.js b/nailgun/static/models.js index 9a47c108c4..c155b36183 100644 --- a/nailgun/static/models.js +++ b/nailgun/static/models.js @@ -843,8 +843,8 @@ define([ } else { var idRangeErrors = ['', '']; var segmentation = attrs.networking_parameters.get('segmentation_type'); - var idRangeAttr = segmentation == 'gre' ? 'gre_id_range' : 'vlan_range'; - var maxId = segmentation == 'gre' ? 65535 : 4094; + var idRangeAttr = segmentation == 'vlan' ? 'vlan_range' : 'gre_id_range'; + var maxId = segmentation == 'vlan' ? 4094 : 65535; var idRange = attrs.networking_parameters.get(idRangeAttr); var idStart = Number(idRange[0]), idEnd = Number(idRange[1]); if (!utils.isNaturalNumber(idStart) || idStart < 2 || idStart > maxId) { diff --git a/nailgun/static/translations/core.json b/nailgun/static/translations/core.json index d42787b7bc..cb3c1f0622 100644 --- a/nailgun/static/translations/core.json +++ b/nailgun/static/translations/core.json @@ -721,14 +721,16 @@ "description": "Choose the private (guest) network configuration. The choice you make here cannot be changed after you finish the wizard. More information see the ", "description_link": "Mirantis OpenStack Planning Guide for Network Topology", "release_alert": "Neutron is not supported in __NameAndRelease.release_name__", - "hypervisor_alert": "Neutron with VLAN or GRE segmentation is not available with __Compute.vcenter__ as a selected compute option.", + "hypervisor_alert": "Neutron is not available with __Compute.vcenter__ as a selected compute option.", "nove_network_vcenter_alert": "Legacy Networking (nova-network) requires __Compute.vcenter__ to be a selected compute option.", "nova_network": "(DEPRECATED) Legacy Networking (nova-network)", "nova_network_description": "This option is only available if you use VMware vCenter. Note that OpenStack is moving to deprecate nova-network in upcoming releases.", "neutr_gre": "Neutron with GRE segmentation", "neutr_gre_description": "The networking equipment must support GRE segmentation. This option supports up to 65535 networks.", "neutr_vlan": "Neutron with VLAN segmentation (default)", - "neutr_vlan_description": "The networking equipment must be configured for VLAN segmentation. This option supports up to 4095 networks." + "neutr_vlan_description": "The networking equipment must be configured for VLAN segmentation. This option supports up to 4095 networks.", + "neutr_tun": "Neutron with tunneling segmentation", + "neutr_tun_description": "By default VXLAN tunnels will be used (can be changed to GRE via Fuel CLI).The networking equipment must support VXLAN segmentation. This option supports millions of tenant data networks." }, "storage": { "title": "Storage Backends", diff --git a/nailgun/static/views/cluster_page_tabs/network_tab.jsx b/nailgun/static/views/cluster_page_tabs/network_tab.jsx index 8e0bcb47ee..be4ea01ecc 100644 --- a/nailgun/static/views/cluster_page_tabs/network_tab.jsx +++ b/nailgun/static/views/cluster_page_tabs/network_tab.jsx @@ -860,7 +860,7 @@ function($, _, i18n, Backbone, React, models, dispatcher, utils, componentMixins render: function() { var networkParameters = this.props.networkConfiguration.get('networking_parameters'), manager = networkParameters.get('net_manager'), - idRangePrefix = networkParameters.get('segmentation_type') == 'gre' ? 'gre_id' : 'vlan', + idRangePrefix = networkParameters.get('segmentation_type') == 'vlan' ? 'vlan' : 'gre_id', ns = 'cluster_page.network_tab.networking_parameters.'; return (