Description of problem: When deploying the undercloud, if you specify a non-normalized cidr in undercloud.conf for the control plane, such as 192.168.225.1/24, the deployment succeeds and the subnet is created correctly with 192.168.225.0/24. If you attempt to perform a minor update to the undercloud, it fails because it looks for a network with the value in undercloud.conf (192.168.225.1/24), doesn't find it (because it's really 192.168.225.0/24) and then attempts to create the network for 192.168.225.1/24 which fails due to overlapping IP addresses. Version-Release number of selected component (if applicable): AFAIK, this issue exists in both OSP13 and OSP14. How reproducible: Steps to Reproduce: 1. 2. 3. Actual results: Expected results: Additional info:
Neutron converts/normalizes the value provided as CIDR in a pre-commit method: https://opendev.org/openstack/neutron/src/branch/master/neutron/db/db_base_plugin_v2.py#L820 818 # turn the CIDR into a proper subnet 819 net = netaddr.IPNetwork(s['cidr']) 820 subnet['subnet']['cidr'] = '%s/%s' % (net.network, net.prefixlen) This explain why we can create a subnet without the actual network address in the CIDR. However when listing subnets and querying with a CIDR that does not use the actual network address, the result is empty: $ curl -s -H "X-Auth-Token: $(openstack token issue -c id -f value)" -H "Content-Type: application/json" http://192.168.122.103:9696/v2.0/subnets?cidr=192.168.100.1/24 | json_reformat { "subnets": [ ] } Looks like this patch would fix it neutron side: --- a/neutron/db/db_base_plugin_common.py +++ b/neutron/db/db_base_plugin_common.py @@ -300,6 +300,12 @@ class DbBasePluginCommon(object): page_reverse=False): pager = base_obj.Pager(sorts, limit, page_reverse, marker) filters = filters or {} + if filters.get('cidr'): + cidr_list = [] + for cidr in filters['cidr']: + net = netaddr.IPNetwork(cidr) + cidr_list.append('%s/%s' % (net.network, net.prefixlen)) + filters.update({'cidr': cidr_list}) # TODO(ihrachys) remove explicit reader usage when subnet OVO switches # to engine facade by default with db_api.CONTEXT_READER.using(context):