Merge "Enable deferred IP on Neutron ports"

This commit is contained in:
Jenkins 2016-08-02 15:30:58 +00:00 committed by Gerrit Code Review
commit 7a28e8adf2
5 changed files with 60 additions and 6 deletions

View File

@ -417,8 +417,8 @@ class ServersController(wsgi.Controller):
raise exc.HTTPBadRequest(explanation=msg) raise exc.HTTPBadRequest(explanation=msg)
if request.address is not None: if request.address is not None:
msg = _("Specified Fixed IP '%(addr)s' cannot be used " msg = _("Specified Fixed IP '%(addr)s' cannot be used "
"with port '%(port)s': port already has " "with port '%(port)s': the two cannot be "
"a Fixed IP allocated.") % { "specified together.") % {
"addr": request.address, "addr": request.address,
"port": request.port_id} "port": request.port_id}
raise exc.HTTPBadRequest(explanation=msg) raise exc.HTTPBadRequest(explanation=msg)

View File

@ -1465,7 +1465,12 @@ class API(base_api.NetworkAPI):
neutron_client=neutron) neutron_client=neutron)
if port.get('device_id', None): if port.get('device_id', None):
raise exception.PortInUse(port_id=request.port_id) raise exception.PortInUse(port_id=request.port_id)
if not port.get('fixed_ips'): deferred_ip = port.get('ip_allocation') == 'deferred'
# NOTE(carl_baldwin) A deferred IP port doesn't have an
# address here. If it fails to get one later when nova
# updates it with host info, Neutron will error which
# raises an exception.
if not deferred_ip and not port.get('fixed_ips'):
raise exception.PortRequiresFixedIP( raise exception.PortRequiresFixedIP(
port_id=request.port_id) port_id=request.port_id)
request.network_id = port['network_id'] request.network_id = port['network_id']

View File

@ -419,7 +419,8 @@ class SecurityGroupAPI(security_group_base.SecurityGroupBase):
def _has_security_group_requirements(self, port): def _has_security_group_requirements(self, port):
port_security_enabled = port.get('port_security_enabled', True) port_security_enabled = port.get('port_security_enabled', True)
has_ip = port.get('fixed_ips') has_ip = port.get('fixed_ips')
if has_ip: deferred_ip = port.get('ip_allocation') == 'deferred'
if has_ip or deferred_ip:
return port_security_enabled return port_security_enabled
return False return False

View File

@ -73,7 +73,7 @@ class TestNeutronSecurityGroupsV21(
def _create_port(self, **kwargs): def _create_port(self, **kwargs):
body = {'port': {'binding:vnic_type': model.VNIC_TYPE_NORMAL}} body = {'port': {'binding:vnic_type': model.VNIC_TYPE_NORMAL}}
fields = ['security_groups', 'device_id', 'network_id', fields = ['security_groups', 'device_id', 'network_id',
'port_security_enabled'] 'port_security_enabled', 'ip_allocation']
for field in fields: for field in fields:
if field in kwargs: if field in kwargs:
body['port'][field] = kwargs[field] body['port'][field] = kwargs[field]
@ -278,6 +278,22 @@ class TestNeutronSecurityGroupsV21(
self.manager._addSecurityGroup, self.manager._addSecurityGroup,
req, UUID_SERVER, body) req, UUID_SERVER, body)
def test_associate_deferred_ip_port(self):
sg = self._create_sg_template().get('security_group')
net = self._create_network()
self._create_port(
network_id=net['network']['id'], security_groups=[sg['id']],
port_security_enabled=True, ip_allocation='deferred',
device_id=UUID_SERVER)
self.stub_out('nova.db.instance_get_by_uuid',
test_security_groups.return_server)
body = dict(addSecurityGroup=dict(name="test"))
req = fakes.HTTPRequest.blank('/v2/fake/servers/%s/action' %
UUID_SERVER)
self.manager._addSecurityGroup(req, UUID_SERVER, body)
def test_disassociate_by_non_existing_security_group_name(self): def test_disassociate_by_non_existing_security_group_name(self):
self.stub_out('nova.db.instance_get_by_uuid', self.stub_out('nova.db.instance_get_by_uuid',
test_security_groups.return_server) test_security_groups.return_server)
@ -696,6 +712,7 @@ class MockClient(object):
'admin_state_up': p.get('admin_state_up', True), 'admin_state_up': p.get('admin_state_up', True),
'security_groups': p.get('security_groups', []), 'security_groups': p.get('security_groups', []),
'network_id': p.get('network_id'), 'network_id': p.get('network_id'),
'ip_allocation': p.get('ip_allocation'),
'binding:vnic_type': 'binding:vnic_type':
p.get('binding:vnic_type') or model.VNIC_TYPE_NORMAL} p.get('binding:vnic_type') or model.VNIC_TYPE_NORMAL}
@ -710,7 +727,7 @@ class MockClient(object):
if not port_security and ret['security_groups']: if not port_security and ret['security_groups']:
raise exception.SecurityGroupCannotBeApplied() raise exception.SecurityGroupCannotBeApplied()
if network['subnets']: if network['subnets'] and p.get('ip_allocation') != 'deferred':
ret['fixed_ips'] = [{'subnet_id': network['subnets'][0], ret['fixed_ips'] = [{'subnet_id': network['subnets'][0],
'ip_address': '10.0.0.1'}] 'ip_address': '10.0.0.1'}]
if not ret['security_groups'] and (port_security is None or if not ret['security_groups'] and (port_security is None or

View File

@ -3098,6 +3098,37 @@ class TestNeutronv2WithMock(test.TestCase):
'fake-user', 'fake-project', 'fake-user', 'fake-project',
auth_token='bff4a5a6b9eb4ea2a6efec6eefb77936') auth_token='bff4a5a6b9eb4ea2a6efec6eefb77936')
@mock.patch('nova.network.neutronv2.api.API._show_port')
def test_deferred_ip_port_immediate_allocation(self, mock_show):
port = {'network_id': 'my_netid1',
'device_id': None,
'id': uuids.port,
'fixed_ips': [], # no fixed ip
'ip_allocation': 'immediate', }
mock_show.return_value = port
requested_networks = objects.NetworkRequestList(
objects=[objects.NetworkRequest(port_id=port['id'])])
self.assertRaises(exception.PortRequiresFixedIP,
self.api.validate_networks,
self.context, requested_networks, 1)
@mock.patch('nova.network.neutronv2.api.API._show_port')
def test_deferred_ip_port_deferred_allocation(self, mock_show):
port = {'network_id': 'my_netid1',
'device_id': None,
'id': uuids.port,
'fixed_ips': [], # no fixed ip
'ip_allocation': 'deferred', }
mock_show.return_value = port
requested_networks = objects.NetworkRequestList(
objects=[objects.NetworkRequest(port_id=port['id'])])
count = self.api.validate_networks(self.context, requested_networks, 1)
self.assertEqual(1, count)
@mock.patch('oslo_concurrency.lockutils.lock') @mock.patch('oslo_concurrency.lockutils.lock')
def test_get_instance_nw_info_locks_per_instance(self, mock_lock): def test_get_instance_nw_info_locks_per_instance(self, mock_lock):
instance = objects.Instance(uuid=uuid.uuid4()) instance = objects.Instance(uuid=uuid.uuid4())