Disable allowed_address_pair ip 0.0.0.0/0 ::/0 for ipset
Previously, the ipset_manager would pass in 0.0.0.0/0 or ::/0 if these addresses were inputted as allowed address pairs. This causes ipset to raise an error as it does not work with zero prefix sizes. To solve this problem we use two ipset rules to represent this. This was correctly fixed in a backport to kilo though we did not have the cycles to backport this exact fix to juno as in juno additional work needs to be done because the iptable and ipset code are interleaved together. This patch fixes this issue by disabling one from creating an address pair of zero lenght. This patch also provides a small tool which one should run: tools/fix_zero_length_ip_prefix.py which changes all zero length address_pair rules into two address pair rules of: Ipv4: 0.0.0.0/1 and 128.0.0.1/1 IPv6: ::/1' and '8000::/1 to avoid the problem. After this patch is merged into juno it will be easier for us to apply a better change to allow /0 addresses again in juno. Change-Id: I8c6a08e0cf3b5b5386fe03af9f2174c666b8ac75 Closes-bug: 1461054 Co-Authored-by: Darragh O'Reilly <darragh.oreilly@hp.com>
This commit is contained in:
parent
ea63062898
commit
d9c78880d2
|
@ -12,6 +12,7 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import netaddr
|
||||
import webob.exc
|
||||
|
||||
from neutron.api.v2 import attributes as attr
|
||||
|
@ -46,6 +47,10 @@ class AllowedAddressPairExhausted(nexception.BadRequest):
|
|||
"exceeds the maximum %(quota)s.")
|
||||
|
||||
|
||||
class AllowedAddressPairsZeroPrefixNotAllowed(nexception.InvalidInput):
|
||||
message = _("AllowedAddressPair CIDR cannot have prefix length zero")
|
||||
|
||||
|
||||
def _validate_allowed_address_pairs(address_pairs, valid_values=None):
|
||||
unique_check = {}
|
||||
if len(address_pairs) > cfg.CONF.max_allowed_address_pair:
|
||||
|
@ -77,7 +82,9 @@ def _validate_allowed_address_pairs(address_pairs, valid_values=None):
|
|||
set(['mac_address', 'ip_address'])))
|
||||
raise webob.exc.HTTPBadRequest(msg)
|
||||
|
||||
if '/' in ip_address:
|
||||
if (netaddr.IPNetwork(ip_address).prefixlen == 0):
|
||||
raise AllowedAddressPairsZeroPrefixNotAllowed()
|
||||
elif '/' in ip_address:
|
||||
msg = attr._validate_subnet(ip_address)
|
||||
else:
|
||||
msg = attr._validate_ip_address(ip_address)
|
||||
|
|
|
@ -140,6 +140,11 @@ class TestAllowedAddressPairs(AllowedAddressPairDBTestCase):
|
|||
self.deserialize(self.fmt, res)
|
||||
self.assertEqual(res.status_int, 409)
|
||||
|
||||
def test_create_port_zero_prefix_ip(self):
|
||||
address_pairs = [{'mac_address': 'invalid_mac',
|
||||
'ip_address': '0.0.0.0/0'}]
|
||||
self._create_port_with_address_pairs(address_pairs, 400)
|
||||
|
||||
def test_create_port_bad_mac(self):
|
||||
address_pairs = [{'mac_address': 'invalid_mac',
|
||||
'ip_address': '10.0.0.1'}]
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
"""
|
||||
This script is needed to convert addresses that are zero prefix to be two
|
||||
address of one prefix to avoid a bug that exists in juno where the ipset
|
||||
manager isn't able to handle zero prefix lenght addresses.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
import netaddr
|
||||
from neutronclient.v2_0 import client
|
||||
|
||||
|
||||
def main():
|
||||
try:
|
||||
username = os.environ['OS_USERNAME']
|
||||
tenant_name = os.environ['OS_TENANT_NAME']
|
||||
password = os.environ['OS_PASSWORD']
|
||||
auth_url = os.environ['OS_AUTH_URL']
|
||||
except KeyError:
|
||||
print("You need to source your openstack creds file first!")
|
||||
sys.exit(1)
|
||||
|
||||
neutron = client.Client(username=username,
|
||||
tenant_name=tenant_name,
|
||||
password=password,
|
||||
auth_url=auth_url)
|
||||
|
||||
ports = neutron.list_ports()
|
||||
for port in ports['ports']:
|
||||
new_address_pairs = []
|
||||
needs_update = False
|
||||
allowed_address_pairs = port.get('allowed_address_pairs')
|
||||
if allowed_address_pairs:
|
||||
for address_pair in allowed_address_pairs:
|
||||
ip = address_pair['ip_address']
|
||||
mac = address_pair['mac_address']
|
||||
if(netaddr.IPNetwork(ip).prefixlen == 0):
|
||||
needs_update = True
|
||||
if(netaddr.IPNetwork(ip).version == 4):
|
||||
new_address_pairs.append({'ip_address': '0.0.0.0/1',
|
||||
'mac_address': mac})
|
||||
new_address_pairs.append({'ip_address': '128.0.0.0/1',
|
||||
'mac_address': mac})
|
||||
elif(netaddr.IPNetwork(ip).version == 6):
|
||||
new_address_pairs.append({'ip_address': '::/1',
|
||||
'mac_address': mac})
|
||||
new_address_pairs.append({'ip_address': '8000::/1',
|
||||
'mac_address': mac})
|
||||
else:
|
||||
new_address_pairs.append(address_pair)
|
||||
if needs_update:
|
||||
print ("Updating port %s with new address_pairs %s" %
|
||||
(port['id'], new_address_pairs))
|
||||
neutron.update_port(
|
||||
port['id'],
|
||||
{'port': {'allowed_address_pairs': new_address_pairs}})
|
||||
|
||||
main()
|
Loading…
Reference in New Issue