Merge "Extension to tell when deferred binding is in effect"
This commit is contained in:
56
neutron/extensions/ip_allocation.py
Normal file
56
neutron/extensions/ip_allocation.py
Normal 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 {}
|
@@ -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):
|
||||
|
@@ -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):
|
||||
|
Reference in New Issue
Block a user