Merge "Extension to tell when deferred binding is in effect"

This commit is contained in:
Jenkins
2016-07-11 21:21:17 +00:00
committed by Gerrit Code Review
3 changed files with 101 additions and 2 deletions

View File

@@ -0,0 +1,56 @@
# Copyright (c) 2016 Hewlett Packard Enterprise Development Company, L.P.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from neutron.api import extensions
from neutron.api.v2 import attributes
IP_ALLOCATION = 'ip_allocation'
IP_ALLOCATION_IMMEDIATE = 'immediate'
IP_ALLOCATION_DEFERRED = 'deferred'
IP_ALLOCATION_NONE = 'none'
# Attribute Map
RESOURCE_ATTRIBUTE_MAP = {
attributes.PORTS: {
IP_ALLOCATION: {'allow_post': False,
'allow_put': False,
'is_visible': True, },
},
}
class Ip_allocation(extensions.ExtensionDescriptor):
"""Extension indicates when ports use deferred or no IP allocation."""
@classmethod
def get_name(cls):
return "IP Allocation"
@classmethod
def get_alias(cls):
return "ip_allocation"
@classmethod
def get_description(cls):
return "IP allocation extension."
@classmethod
def get_updated(cls):
return "2016-06-10T23:00:00-00:00"
def get_extended_resources(self, version):
if version == "2.0":
return RESOURCE_ATTRIBUTE_MAP
else:
return {}

View File

@@ -17,7 +17,9 @@
from neutron.api.v2 import attributes
from neutron.db import common_db_mixin
from neutron.extensions import ip_allocation
from neutron.extensions import segment
from neutron import manager
from neutron.services.segments import db
@@ -25,15 +27,28 @@ def _extend_subnet_dict_binding(plugin, subnet_res, subnet_db):
subnet_res['segment_id'] = subnet_db.get('segment_id')
def _extend_port_dict_binding(plugin, port_res, port_db):
if not manager.NeutronManager.get_service_plugins().get('segments'):
return
if port_res.get('fixed_ips'):
value = ip_allocation.IP_ALLOCATION_IMMEDIATE
else:
value = ip_allocation.IP_ALLOCATION_DEFERRED
port_res[ip_allocation.IP_ALLOCATION] = value
class Plugin(db.SegmentDbMixin, segment.SegmentPluginBase):
_instance = None
supported_extension_aliases = ["segment"]
supported_extension_aliases = ["segment", "ip_allocation"]
def __init__(self):
common_db_mixin.CommonDbMixin.register_dict_extend_funcs(
attributes.SUBNETS, [_extend_subnet_dict_binding])
common_db_mixin.CommonDbMixin.register_dict_extend_funcs(
attributes.PORTS, [_extend_port_dict_binding])
@classmethod
def get_instance(cls):

View File

@@ -25,6 +25,7 @@ from neutron.db import agentschedulers_db
from neutron.db import db_base_plugin_v2
from neutron.db import portbindings_db
from neutron.db import segments_db
from neutron.extensions import ip_allocation
from neutron.extensions import portbindings
from neutron.extensions import segment as ext_segment
from neutron.plugins.common import constants as p_constants
@@ -109,7 +110,7 @@ class SegmentTestPlugin(db_base_plugin_v2.NeutronDbPluginV2,
__native_pagination_support = True
__native_sorting_support = True
supported_extension_aliases = ["segment", "binding"]
supported_extension_aliases = ["segment", "binding", "ip_allocation"]
def get_plugin_description(self):
return "Network Segments"
@@ -643,6 +644,8 @@ class TestSegmentAwareIpam(SegmentTestCase):
tenant_id=network['network']['tenant_id'],
arg_list=(portbindings.HOST_ID,),
**{portbindings.HOST_ID: 'fakehost'})
res = self.deserialize(self.fmt, response)
self._validate_immediate_ip_allocation(res['port']['id'])
# Since host mapped to middle segment, IP must come from middle subnet
self._assert_one_ip_in_subnet(response, subnets[1]['subnet']['cidr'])
@@ -686,6 +689,9 @@ class TestSegmentAwareIpam(SegmentTestCase):
arg_list=(portbindings.HOST_ID,),
**{portbindings.HOST_ID: 'fakehost'})
res = self.deserialize(self.fmt, response)
self._validate_immediate_ip_allocation(res['port']['id'])
# Since the subnet is not on a segment, fall back to it
self._assert_one_ip_in_subnet(response, subnet['subnet']['cidr'])
@@ -775,6 +781,7 @@ class TestSegmentAwareIpam(SegmentTestCase):
arg_list=(portbindings.HOST_ID,),
**{portbindings.HOST_ID: 'fakehost'})
port = self.deserialize(self.fmt, response)
self._validate_deferred_ip_allocation(port['port']['id'])
# Create the subnet and try to update the port to get an IP
with self.subnet(network=network,
@@ -790,6 +797,24 @@ class TestSegmentAwareIpam(SegmentTestCase):
self.assertEqual(webob.exc.HTTPOk.code, response.status_int)
self._assert_one_ip_in_subnet(response, subnet['subnet']['cidr'])
def _validate_deferred_ip_allocation(self, port_id):
request = self.new_show_request('ports', port_id)
response = self.deserialize(self.fmt, request.get_response(self.api))
self.assertEqual(ip_allocation.IP_ALLOCATION_DEFERRED,
response['port'][ip_allocation.IP_ALLOCATION])
ips = response['port']['fixed_ips']
self.assertEqual(0, len(ips))
def _validate_immediate_ip_allocation(self, port_id):
request = self.new_show_request('ports', port_id)
response = self.deserialize(self.fmt, request.get_response(self.api))
self.assertEqual(ip_allocation.IP_ALLOCATION_IMMEDIATE,
response['port'][ip_allocation.IP_ALLOCATION])
ips = response['port']['fixed_ips']
self.assertNotEqual(0, len(ips))
def _create_deferred_ip_port(self, network):
response = self._create_port(self.fmt,
net_id=network['network']['id'],
@@ -797,6 +822,9 @@ class TestSegmentAwareIpam(SegmentTestCase):
port = self.deserialize(self.fmt, response)
ips = port['port']['fixed_ips']
self.assertEqual(0, len(ips))
self._validate_deferred_ip_allocation(port['port']['id'])
return port
def test_port_update_deferred_allocation(self):