Merge "Add address format check for property"

This commit is contained in:
Jenkins 2015-05-14 05:40:07 +00:00 committed by Gerrit Code Review
commit e27831cc95
10 changed files with 116 additions and 12 deletions

View File

@ -14,6 +14,7 @@
from neutronclient.common import exceptions from neutronclient.common import exceptions
from neutronclient.neutron import v2_0 as neutronV20 from neutronclient.neutron import v2_0 as neutronV20
from neutronclient.v2_0 import client as nc from neutronclient.v2_0 import client as nc
from oslo_utils import netutils
from oslo_utils import uuidutils from oslo_utils import uuidutils
from heat.common import exception from heat.common import exception
@ -172,3 +173,10 @@ class SubnetConstraint(constraints.BaseCustomConstraint):
neutron_client = client.client('neutron') neutron_client = client.client('neutron')
neutronV20.find_resourceid_by_name_or_id( neutronV20.find_resourceid_by_name_or_id(
neutron_client, 'subnet', value) neutron_client, 'subnet', value)
class IPConstraint(constraints.BaseCustomConstraint):
def validate(self, value, context):
self._error_message = 'Invalid IP address'
return netutils.is_valid_ip(value)

View File

@ -201,7 +201,10 @@ class ElasticIpAssociation(resource.Resource):
EIP: properties.Schema( EIP: properties.Schema(
properties.Schema.STRING, properties.Schema.STRING,
_('EIP address to associate with instance.'), _('EIP address to associate with instance.'),
update_allowed=True update_allowed=True,
constraints=[
constraints.CustomConstraint('ip_addr')
]
), ),
ALLOCATION_ID: properties.Schema( ALLOCATION_ID: properties.Schema(
properties.Schema.STRING, properties.Schema.STRING,

View File

@ -78,13 +78,19 @@ class FloatingIP(neutron.NeutronResource):
FIXED_IP_ADDRESS: properties.Schema( FIXED_IP_ADDRESS: properties.Schema(
properties.Schema.STRING, properties.Schema.STRING,
_('IP address to use if the port has multiple addresses.'), _('IP address to use if the port has multiple addresses.'),
update_allowed=True update_allowed=True,
constraints=[
constraints.CustomConstraint('ip_addr')
]
), ),
FLOATING_IP_ADDRESS: properties.Schema( FLOATING_IP_ADDRESS: properties.Schema(
properties.Schema.STRING, properties.Schema.STRING,
_('IP address of the floating IP. NOTE: The default policy ' _('IP address of the floating IP. NOTE: The default policy '
'setting in Neutron restricts usage of this property to ' 'setting in Neutron restricts usage of this property to '
'administrative users only.'), 'administrative users only.'),
constraints=[
constraints.CustomConstraint('ip_addr')
],
support_status=support.SupportStatus(version='2015.2'), support_status=support.SupportStatus(version='2015.2'),
), ),
} }
@ -257,7 +263,10 @@ class FloatingIPAssociation(neutron.NeutronResource):
FIXED_IP_ADDRESS: properties.Schema( FIXED_IP_ADDRESS: properties.Schema(
properties.Schema.STRING, properties.Schema.STRING,
_('IP address to use if the port has multiple addresses.'), _('IP address to use if the port has multiple addresses.'),
update_allowed=True update_allowed=True,
constraints=[
constraints.CustomConstraint('ip_addr')
]
), ),
} }

View File

@ -278,7 +278,10 @@ class Pool(neutron.NeutronResource):
), ),
VIP_ADDRESS: properties.Schema( VIP_ADDRESS: properties.Schema(
properties.Schema.STRING, properties.Schema.STRING,
_('IP address of the vip.') _('IP address of the vip.'),
constraints=[
constraints.CustomConstraint('ip_addr')
]
), ),
VIP_CONNECTION_LIMIT: properties.Schema( VIP_CONNECTION_LIMIT: properties.Schema(
properties.Schema.INTEGER, properties.Schema.INTEGER,
@ -547,7 +550,10 @@ class PoolMember(neutron.NeutronResource):
ADDRESS: properties.Schema( ADDRESS: properties.Schema(
properties.Schema.STRING, properties.Schema.STRING,
_('IP address of the pool member on the pool network.'), _('IP address of the pool member on the pool network.'),
required=True required=True,
constraints=[
constraints.CustomConstraint('ip_addr')
]
), ),
PROTOCOL_PORT: properties.Schema( PROTOCOL_PORT: properties.Schema(
properties.Schema.INTEGER, properties.Schema.INTEGER,

View File

@ -132,7 +132,10 @@ class Port(neutron.NeutronResource):
), ),
FIXED_IP_IP_ADDRESS: properties.Schema( FIXED_IP_IP_ADDRESS: properties.Schema(
properties.Schema.STRING, properties.Schema.STRING,
_('IP address desired in the subnet for this port.') _('IP address desired in the subnet for this port.'),
constraints=[
constraints.CustomConstraint('ip_addr')
]
), ),
}, },
), ),
@ -166,7 +169,10 @@ class Port(neutron.NeutronResource):
ALLOWED_ADDRESS_PAIR_IP_ADDRESS: properties.Schema( ALLOWED_ADDRESS_PAIR_IP_ADDRESS: properties.Schema(
properties.Schema.STRING, properties.Schema.STRING,
_('IP address to allow through this port.'), _('IP address to allow through this port.'),
required=True required=True,
constraints=[
constraints.CustomConstraint('ip_addr')
]
), ),
}, },
) )

View File

@ -11,6 +11,8 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
from oslo_utils import netutils
from heat.common import exception from heat.common import exception
from heat.common.i18n import _ from heat.common.i18n import _
from heat.engine import attributes from heat.engine import attributes
@ -130,11 +132,17 @@ class Subnet(neutron.NeutronResource):
schema={ schema={
ALLOCATION_POOL_START: properties.Schema( ALLOCATION_POOL_START: properties.Schema(
properties.Schema.STRING, properties.Schema.STRING,
required=True required=True,
constraints=[
constraints.CustomConstraint('ip_addr')
]
), ),
ALLOCATION_POOL_END: properties.Schema( ALLOCATION_POOL_END: properties.Schema(
properties.Schema.STRING, properties.Schema.STRING,
required=True required=True,
constraints=[
constraints.CustomConstraint('ip_addr')
]
), ),
}, },
) )
@ -155,7 +163,10 @@ class Subnet(neutron.NeutronResource):
), ),
ROUTE_NEXTHOP: properties.Schema( ROUTE_NEXTHOP: properties.Schema(
properties.Schema.STRING, properties.Schema.STRING,
required=True required=True,
constraints=[
constraints.CustomConstraint('ip_addr')
]
), ),
}, },
), ),
@ -247,6 +258,13 @@ class Subnet(neutron.NeutronResource):
'they must be equal.') 'they must be equal.')
raise exception.StackValidationFailed(message=msg) raise exception.StackValidationFailed(message=msg)
gateway_ip = self.properties.get(self.GATEWAY_IP)
if (gateway_ip and gateway_ip not in ['~', ''] and
not netutils.is_valid_ip(gateway_ip)):
msg = (_('Gateway IP address "%(gateway)" is in '
'invalid format.'), gateway_ip)
raise exception.StackValidationFailed(message=msg)
def handle_create(self): def handle_create(self):
props = self.prepare_properties( props = self.prepare_properties(
self.properties, self.properties,

View File

@ -339,7 +339,10 @@ class Server(stack_user.StackUser):
NETWORK_FIXED_IP: properties.Schema( NETWORK_FIXED_IP: properties.Schema(
properties.Schema.STRING, properties.Schema.STRING,
_('Fixed IP address to specify for the port ' _('Fixed IP address to specify for the port '
'created on the requested network.') 'created on the requested network.'),
constraints=[
constraints.CustomConstraint('ip_addr')
]
), ),
NETWORK_PORT: properties.Schema( NETWORK_PORT: properties.Schema(
properties.Schema.STRING, properties.Schema.STRING,

View File

@ -149,7 +149,10 @@ class OSDBInstance(resource.Resource):
), ),
V4_FIXED_IP: properties.Schema( V4_FIXED_IP: properties.Schema(
properties.Schema.STRING, properties.Schema.STRING,
_('Fixed IPv4 address for this NIC.') _('Fixed IPv4 address for this NIC.'),
constraints=[
constraints.CustomConstraint('ip_addr')
]
), ),
}, },
), ),

View File

@ -182,3 +182,50 @@ class NeutronConstraintsValidate(common.HeatTestCase):
self.assertFalse(constraint.validate("bar", ctx)) self.assertFalse(constraint.validate("bar", ctx))
mock_find.assert_has_calls([mock.call(nc, self.resource_type, 'foo'), mock_find.assert_has_calls([mock.call(nc, self.resource_type, 'foo'),
mock.call(nc, self.resource_type, 'bar')]) mock.call(nc, self.resource_type, 'bar')])
class TestIPConstraint(common.HeatTestCase):
def setUp(self):
super(TestIPConstraint, self).setUp()
self.constraint = neutron.IPConstraint()
def test_validate_ipv4_format(self):
validate_format = [
'1.1.1.1',
'1.0.1.1',
'255.255.255.255'
]
for ip in validate_format:
self.assertTrue(self.constraint.validate(ip, None))
def test_invalidate_ipv4_format(self):
invalidate_format = [
'1.1.1.',
'1.1.1.256',
'invalidate format',
'1.a.1.1'
]
for ip in invalidate_format:
self.assertFalse(self.constraint.validate(ip, None))
def test_validate_ipv6_format(self):
validate_format = [
'2002:2002::20c:29ff:fe7d:811a',
'::1',
'2002::',
'2002::1',
]
for ip in validate_format:
self.assertTrue(self.constraint.validate(ip, None))
def test_invalidate_ipv6_format(self):
invalidate_format = [
'2002::2001::1',
'2002::g',
'invalidate format',
'2001::0::',
'20c:29ff:fe7d:811a'
]
for ip in invalidate_format:
self.assertFalse(self.constraint.validate(ip, None))

View File

@ -73,6 +73,7 @@ heat.constraints =
cinder.vtype = heat.engine.clients.os.cinder:VolumeTypeConstraint cinder.vtype = heat.engine.clients.os.cinder:VolumeTypeConstraint
sahara.image = heat.engine.clients.os.sahara:ImageConstraint sahara.image = heat.engine.clients.os.sahara:ImageConstraint
trove.flavor = heat.engine.clients.os.trove:FlavorConstraint trove.flavor = heat.engine.clients.os.trove:FlavorConstraint
ip_addr = heat.engine.clients.os.neutron:IPConstraint
heat.stack_lifecycle_plugins = heat.stack_lifecycle_plugins =