diff --git a/heat/engine/resources/openstack/neutron/subnet.py b/heat/engine/resources/openstack/neutron/subnet.py index 316428823..26a8f96df 100644 --- a/heat/engine/resources/openstack/neutron/subnet.py +++ b/heat/engine/resources/openstack/neutron/subnet.py @@ -345,10 +345,10 @@ class Subnet(neutron.NeutronResource): subnetpool = self.properties[self.SUBNETPOOL] prefixlen = self.properties[self.PREFIXLEN] cidr = self.properties[self.CIDR] - if subnetpool and cidr: + if subnetpool is not None and cidr: raise exception.ResourcePropertyConflict(self.SUBNETPOOL, self.CIDR) - if not subnetpool and not cidr: + if subnetpool is None and not cidr: raise exception.PropertyUnspecifiedError(self.SUBNETPOOL, self.CIDR) if prefixlen and cidr: diff --git a/heat/tests/openstack/neutron/test_neutron_subnet.py b/heat/tests/openstack/neutron/test_neutron_subnet.py index ff3679b39..7f77cb4ee 100644 --- a/heat/tests/openstack/neutron/test_neutron_subnet.py +++ b/heat/tests/openstack/neutron/test_neutron_subnet.py @@ -22,6 +22,7 @@ from heat.common import template_format from heat.engine.clients.os import neutron from heat.engine.clients.os import openstacksdk from heat.engine.hot import functions as hot_funcs +from heat.engine import resource from heat.engine.resources.openstack.neutron import subnet from heat.engine import rsrc_defn from heat.engine import scheduler @@ -612,6 +613,45 @@ class NeutronSubnetTest(common.HeatTestCase): "subnetpool, cidr.") self.assertEqual(msg, six.text_type(ex)) + def test_validate_subnetpool_ref_with_cidr(self): + t = template_format.parse(neutron_template) + props = t['resources']['sub_net']['properties'] + props['subnetpool'] = {'get_resource': 'subnetpool'} + props = t['resources']['sub_net']['properties'] + stack = utils.parse_stack(t) + snippet = rsrc_defn.ResourceDefinition('subnetpool', + 'OS::Neutron::SubnetPool') + res = resource.Resource('subnetpool', snippet, stack) + stack.add_resource(res) + self.patchobject(stack['subnetpool'], 'FnGetRefId', + return_value=None) + self.patchobject(stack['net'], 'FnGetRefId', + return_value='fc68ea2c-b60b-4b4f-bd82-94ec81110766') + rsrc = stack['sub_net'] + ex = self.assertRaises(exception.ResourcePropertyConflict, + rsrc.validate) + msg = ("Cannot define the following properties at the same time: " + "subnetpool, cidr.") + self.assertEqual(msg, six.text_type(ex)) + + def test_validate_subnetpool_ref_no_cidr(self): + t = template_format.parse(neutron_template) + props = t['resources']['sub_net']['properties'] + del props['cidr'] + props['subnetpool'] = {'get_resource': 'subnetpool'} + props = t['resources']['sub_net']['properties'] + stack = utils.parse_stack(t) + snippet = rsrc_defn.ResourceDefinition('subnetpool', + 'OS::Neutron::SubnetPool') + res = resource.Resource('subnetpool', snippet, stack) + stack.add_resource(res) + self.patchobject(stack['subnetpool'], 'FnGetRefId', + return_value=None) + self.patchobject(stack['net'], 'FnGetRefId', + return_value='fc68ea2c-b60b-4b4f-bd82-94ec81110766') + rsrc = stack['sub_net'] + self.assertIsNone(rsrc.validate()) + def test_validate_both_prefixlen_cidr(self): t = template_format.parse(neutron_template) props = t['resources']['sub_net']['properties']