diff --git a/octavia/db/migration/alembic_migrations/versions/11e4bb2bb8ef_fix_ipv6_vip.py b/octavia/db/migration/alembic_migrations/versions/11e4bb2bb8ef_fix_ipv6_vip.py new file mode 100644 index 0000000000..2a87d0a821 --- /dev/null +++ b/octavia/db/migration/alembic_migrations/versions/11e4bb2bb8ef_fix_ipv6_vip.py @@ -0,0 +1,30 @@ +# Copyright 2017 Rackspace, US Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +"""Fix_IPv6_VIP + +Revision ID: 11e4bb2bb8ef +Revises: 211982b05afc +Create Date: 2019-01-28 08:35:35.333616 + +""" +from alembic import op +import sqlalchemy as sa + +# revision identifiers, used by Alembic. +revision = '11e4bb2bb8ef' +down_revision = '211982b05afc' + + +def upgrade(): + op.alter_column(u'vip', u'ip_address', type_=sa.String(64)) diff --git a/octavia/tests/functional/api/v2/test_load_balancer.py b/octavia/tests/functional/api/v2/test_load_balancer.py index ba7ff0fe68..27ce031a20 100644 --- a/octavia/tests/functional/api/v2/test_load_balancer.py +++ b/octavia/tests/functional/api/v2/test_load_balancer.py @@ -316,6 +316,40 @@ class TestLoadBalancer(base.BaseAPITest): self.assertEqual(network.id, api_lb.get('vip_network_id')) self.assertEqual(ip_address, api_lb.get('vip_address')) + # Note: This test is using the unique local address range to + # validate that we handle a fully expaned IP address properly. + # This is not possible with the documentation/testnet range. + def test_create_with_vip_network_and_address_full_ipv6(self): + ip_address = 'fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff' + network_id = uuidutils.generate_uuid() + subnet1 = network_models.Subnet(id=uuidutils.generate_uuid(), + network_id=network_id, + cidr='fc00::/7', + ip_version=6) + subnet2 = network_models.Subnet(id=uuidutils.generate_uuid(), + network_id=network_id, + cidr='198.51.100.0/24', + ip_version=4) + network = network_models.Network(id=network_id, + subnets=[subnet1.id, subnet2.id]) + lb_json = {'vip_network_id': network.id, + 'vip_address': ip_address, + 'project_id': self.project_id} + body = self._build_body(lb_json) + with mock.patch( + "octavia.network.drivers.noop_driver.driver.NoopManager" + ".get_network") as mock_get_network, mock.patch( + "octavia.network.drivers.noop_driver.driver.NoopManager" + ".get_subnet") as mock_get_subnet: + mock_get_network.return_value = network + mock_get_subnet.side_effect = [subnet1, subnet2] + response = self.post(self.LBS_PATH, body) + api_lb = response.json.get(self.root_tag) + self._assert_request_matches_response(lb_json, api_lb) + self.assertEqual(subnet1.id, api_lb.get('vip_subnet_id')) + self.assertEqual(network.id, api_lb.get('vip_network_id')) + self.assertEqual(ip_address, api_lb.get('vip_address')) + def test_create_with_vip_port_1_fixed_ip(self): ip_address = '198.51.100.1' subnet = network_models.Subnet(id=uuidutils.generate_uuid()) diff --git a/octavia/tests/functional/db/test_repositories.py b/octavia/tests/functional/db/test_repositories.py index 9b3df9baf4..2a5ed91221 100644 --- a/octavia/tests/functional/db/test_repositories.py +++ b/octavia/tests/functional/db/test_repositories.py @@ -2958,6 +2958,23 @@ class VipRepositoryTest(BaseRepositoryTest): self.assertIsNotNone(new_lb) self.assertIsNone(new_lb.vip) + def test_create_ipv6(self): + vip = self.vip_repo.create(self.session, load_balancer_id=self.lb.id, + ip_address="2001:DB8::10") + self.assertEqual(self.lb.id, vip.load_balancer_id) + self.assertEqual("2001:DB8::10", vip.ip_address) + + # Note: This test is using the unique local address range to + # validate that we handle a fully expaned IP address properly. + # This is not possible with the documentation/testnet range. + def test_create_ipv6_full(self): + vip = self.vip_repo.create( + self.session, load_balancer_id=self.lb.id, + ip_address="fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff") + self.assertEqual(self.lb.id, vip.load_balancer_id) + self.assertEqual("fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", + vip.ip_address) + class SNIRepositoryTest(BaseRepositoryTest): diff --git a/releasenotes/notes/fix-IPv6-vip-079a3285f78686ee.yaml b/releasenotes/notes/fix-IPv6-vip-079a3285f78686ee.yaml new file mode 100644 index 0000000000..55605d25e4 --- /dev/null +++ b/releasenotes/notes/fix-IPv6-vip-079a3285f78686ee.yaml @@ -0,0 +1,10 @@ +--- +upgrade: + - | + To fix IPv6 VIP addresses, you must run the "octavia-db-manage upgrade + head" migration script. +fixes: + - | + Fully expanded IPv6 VIP addresses would fail to store with "Data too long + for column 'ip_address' at row 1". This patch includes a database migration + to fix this column.