Merge pull request #368 from insequent/Replacing_post_update_logic
Removing POST update logic
This commit is contained in:
commit
f4ad7bca8a
@ -1,99 +0,0 @@
|
||||
# Copyright (c) 2013 OpenStack Foundation
|
||||
#
|
||||
# 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 import manager
|
||||
from neutron import wsgi
|
||||
|
||||
RESOURCE_NAME = "port"
|
||||
RESOURCE_COLLECTION = RESOURCE_NAME + "s"
|
||||
EXTENDED_ATTRIBUTES_2_0 = {
|
||||
RESOURCE_COLLECTION: {
|
||||
"network_id": {"allow_post": True, "default": '',
|
||||
"is_visible": True},
|
||||
"tenant_id": {"allow_post": True, "default": '',
|
||||
"is_visible": True},
|
||||
"segment_id": {"allow_post": True, "default": False},
|
||||
"bridge": {'allow_post': False, 'allow_put': False,
|
||||
'default': False, 'is_visible': True}}}
|
||||
|
||||
|
||||
class QuarkPortsUpdateHandler(object):
|
||||
def __init__(self, plugin):
|
||||
self._plugin = plugin
|
||||
|
||||
def handle(self, request, response):
|
||||
deserializer = wsgi.JSONDeserializer()
|
||||
serializer = wsgi.JSONDictSerializer()
|
||||
|
||||
path = [part for part in request.path_url.split("/") if part]
|
||||
id = path[-1].split('.')[0]
|
||||
|
||||
body = None
|
||||
if request.body:
|
||||
body = deserializer.deserialize(request.body)['body']
|
||||
|
||||
api_response = self._plugin.post_update_port(request.context,
|
||||
id,
|
||||
body)
|
||||
return serializer.serialize({"port": api_response})
|
||||
|
||||
|
||||
class Ports_quark(object):
|
||||
"""Extends ports for quark API purposes.
|
||||
|
||||
* Allows for DELETE (disassociation of port) with IP address
|
||||
* Allows for POST with fixed_ip in body to associate additional IPs
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def get_name(cls):
|
||||
return "Quark Ports API Extension"
|
||||
|
||||
@classmethod
|
||||
def get_alias(cls):
|
||||
return "ports_quark"
|
||||
|
||||
@classmethod
|
||||
def get_description(cls):
|
||||
return "Quark Ports API Extension"
|
||||
|
||||
@classmethod
|
||||
def get_namespace(cls):
|
||||
return ("http://docs.openstack.org/network/ext/"
|
||||
"port_disassociate/api/v2.0")
|
||||
|
||||
@classmethod
|
||||
def get_updated(cls):
|
||||
return "2013-03-25T19:00:00-00:00"
|
||||
|
||||
def get_extended_resources(self, version):
|
||||
if version == "2.0":
|
||||
return EXTENDED_ATTRIBUTES_2_0
|
||||
else:
|
||||
return {}
|
||||
|
||||
@classmethod
|
||||
def get_request_extensions(cls):
|
||||
exts = []
|
||||
|
||||
quark_ports_update_handler = QuarkPortsUpdateHandler(
|
||||
manager.NeutronManager.get_plugin())
|
||||
extension = extensions.RequestExtension(
|
||||
"POST", "/ports/:(id)",
|
||||
quark_ports_update_handler.handle)
|
||||
exts.append(extension)
|
||||
|
||||
return exts
|
@ -119,10 +119,9 @@ def sessioned(func):
|
||||
class Plugin(neutron_plugin_base_v2.NeutronPluginBaseV2,
|
||||
sg_ext.SecurityGroupPluginBase):
|
||||
supported_extension_aliases = ["mac_address_ranges", "routes",
|
||||
"ip_addresses", "ports_quark",
|
||||
"security-group", "diagnostics",
|
||||
"subnets_quark", "provider",
|
||||
"ip_policies", "quotas",
|
||||
"ip_addresses", "security-group",
|
||||
"diagnostics", "subnets_quark",
|
||||
"provider", "ip_policies", "quotas",
|
||||
"networks_quark", "router",
|
||||
"ip_availabilities"]
|
||||
|
||||
@ -133,7 +132,7 @@ class Plugin(neutron_plugin_base_v2.NeutronPluginBaseV2,
|
||||
"""Will add the tenant_id to the context from body.
|
||||
|
||||
It is assumed that the body must have a tenant_id because neutron
|
||||
core would have never got here in such a situation.
|
||||
core could never have gotten here otherwise.
|
||||
"""
|
||||
if context.tenant_id is None:
|
||||
context.tenant_id = resource["tenant_id"]
|
||||
@ -247,10 +246,6 @@ class Plugin(neutron_plugin_base_v2.NeutronPluginBaseV2,
|
||||
self._fix_missing_tenant_id(context, port["port"])
|
||||
return ports.create_port(context, port)
|
||||
|
||||
@sessioned
|
||||
def post_update_port(self, context, id, port):
|
||||
return ports.post_update_port(context, id, port)
|
||||
|
||||
@sessioned
|
||||
def get_port(self, context, id, fields=None):
|
||||
return ports.get_port(context, id, fields)
|
||||
|
@ -37,8 +37,8 @@ STRATEGY = network_strategy.STRATEGY
|
||||
# HACK(amir): RM9305: do not allow a tenant to associate a network to a port
|
||||
# that does not belong to them unless it is publicnet or servicenet
|
||||
def _raise_if_unauthorized(tenant_id, net):
|
||||
if (not STRATEGY.is_parent_network(net["id"])
|
||||
and net["tenant_id"] != tenant_id):
|
||||
if (not STRATEGY.is_parent_network(net["id"]) and
|
||||
net["tenant_id"] != tenant_id):
|
||||
raise exceptions.NotAuthorized()
|
||||
|
||||
|
||||
@ -403,58 +403,6 @@ def update_port(context, id, port):
|
||||
return v._make_port_dict(port_db)
|
||||
|
||||
|
||||
def post_update_port(context, id, port):
|
||||
LOG.info("post_update_port %s for tenant %s" % (id, context.tenant_id))
|
||||
if not port.get("port"):
|
||||
raise exceptions.BadRequest(resource="ports",
|
||||
msg="Port body required")
|
||||
|
||||
port_db = db_api.port_find(context, id=id, scope=db_api.ONE)
|
||||
if not port_db:
|
||||
raise exceptions.PortNotFound(port_id=id, net_id="")
|
||||
|
||||
port = port["port"]
|
||||
if "fixed_ips" in port and port["fixed_ips"]:
|
||||
for ip in port["fixed_ips"]:
|
||||
address = None
|
||||
ipam_driver = ipam.IPAM_REGISTRY.get_strategy(
|
||||
port_db["network"]["ipam_strategy"])
|
||||
if ip:
|
||||
if "ip_id" in ip:
|
||||
ip_id = ip["ip_id"]
|
||||
address = db_api.ip_address_find(
|
||||
context, id=ip_id, tenant_id=context.tenant_id,
|
||||
scope=db_api.ONE)
|
||||
elif "ip_address" in ip:
|
||||
ip_address = ip["ip_address"]
|
||||
net_address = netaddr.IPAddress(ip_address)
|
||||
address = db_api.ip_address_find(
|
||||
context, ip_address=net_address,
|
||||
network_id=port_db["network_id"],
|
||||
tenant_id=context.tenant_id, scope=db_api.ONE)
|
||||
if not address:
|
||||
address = ipam_driver.allocate_ip_address(
|
||||
context, port_db["network_id"], id,
|
||||
CONF.QUARK.ipam_reuse_after,
|
||||
ip_addresses=[ip_address])
|
||||
else:
|
||||
address = ipam_driver.allocate_ip_address(
|
||||
context, port_db["network_id"], id,
|
||||
CONF.QUARK.ipam_reuse_after)
|
||||
|
||||
address["deallocated"] = 0
|
||||
|
||||
already_contained = False
|
||||
for port_address in port_db["ip_addresses"]:
|
||||
if address["id"] == port_address["id"]:
|
||||
already_contained = True
|
||||
break
|
||||
|
||||
if not already_contained:
|
||||
port_db["ip_addresses"].append(address)
|
||||
return v._make_port_dict(port_db)
|
||||
|
||||
|
||||
def get_port(context, id, fields=None):
|
||||
"""Retrieve a port.
|
||||
|
||||
|
@ -1,44 +0,0 @@
|
||||
# Copyright 2015 Openstack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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.
|
||||
|
||||
import json
|
||||
import mock
|
||||
from oslo_log import log as logging
|
||||
|
||||
from quark.api.extensions import ports_quark
|
||||
from quark.tests.functional.base import BaseFunctionalTest
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class TestAPIExtensionPortsQuark(BaseFunctionalTest):
|
||||
def test_QuarkPortsUpdateHandler(self):
|
||||
mock_plugin = mock.MagicMock()
|
||||
mock_request = mock.MagicMock()
|
||||
mock_response = mock.MagicMock()
|
||||
body = '"lots of stuff"'
|
||||
port_id = "I_am_a_port"
|
||||
|
||||
handler = ports_quark.QuarkPortsUpdateHandler(mock_plugin)
|
||||
self.assertEqual(handler._plugin, mock_plugin)
|
||||
|
||||
mock_plugin.post_update_port.return_value = {"id": port_id,
|
||||
"body": body.strip('"')}
|
||||
mock_request.body = body
|
||||
mock_request.path_url = '/v2.0/ports/{}'.format(port_id)
|
||||
expected = ('{{"port": {{"id": "{0}", "body": "{1}"}}}}'
|
||||
''.format(port_id, body.strip('"')))
|
||||
result = handler.handle(mock_request, mock_response)
|
||||
self.assertEqual(json.loads(expected), json.loads(result))
|
@ -1136,143 +1136,6 @@ class TestQuarkUpdatePortSetsIps(test_quark_plugin.TestQuarkPlugin):
|
||||
self.assertTrue(self.called)
|
||||
|
||||
|
||||
class TestQuarkPostUpdatePort(test_quark_plugin.TestQuarkPlugin):
|
||||
@contextlib.contextmanager
|
||||
def _stubs(self, port, addr, addr2=None, port_ips=None):
|
||||
port_model = None
|
||||
addr_model = None
|
||||
addr_model2 = None
|
||||
if port:
|
||||
port_model = models.Port()
|
||||
port_model.update(port)
|
||||
if port_ips:
|
||||
port_model["ip_addresses"] = []
|
||||
for ip in port_ips:
|
||||
ip_mod = models.IPAddress()
|
||||
ip_mod.update(ip)
|
||||
port_model["ip_addresses"].append(ip_mod)
|
||||
net_model = models.Network()
|
||||
net_model["ipam_strategy"] = "ANY"
|
||||
port_model["network"] = net_model
|
||||
|
||||
if addr:
|
||||
addr_model = models.IPAddress()
|
||||
addr_model.update(addr)
|
||||
if addr2:
|
||||
addr_model2 = models.IPAddress()
|
||||
addr_model2.update(addr2)
|
||||
with contextlib.nested(
|
||||
mock.patch("quark.db.api.port_find"),
|
||||
mock.patch("quark.ipam.QuarkIpam.allocate_ip_address"),
|
||||
mock.patch("quark.db.api.ip_address_find"),
|
||||
) as (port_find, alloc_ip, ip_find):
|
||||
port_find.return_value = port_model
|
||||
alloc_ip.return_value = addr_model2 if addr_model2 else addr_model
|
||||
ip_find.return_value = addr_model
|
||||
yield port_find, alloc_ip, ip_find
|
||||
|
||||
def test_post_update_port_no_ports(self):
|
||||
with self._stubs(port=None, addr=None):
|
||||
with self.assertRaises(exceptions.PortNotFound):
|
||||
self.plugin.post_update_port(self.context, 1,
|
||||
{"port": {"network_id": 1}})
|
||||
|
||||
def test_post_update_port_fixed_ips_empty_body(self):
|
||||
port = dict(port=dict(network_id=1, tenant_id=self.context.tenant_id,
|
||||
device_id=2))
|
||||
with self._stubs(port=port, addr=None):
|
||||
with self.assertRaises(exceptions.BadRequest):
|
||||
self.plugin.post_update_port(self.context, 1, {})
|
||||
with self.assertRaises(exceptions.BadRequest):
|
||||
self.plugin.post_update_port(self.context, 1, {"port": {}})
|
||||
|
||||
def test_post_update_port_fixed_ips_ip(self):
|
||||
new_port_ip = dict(port=dict(fixed_ips=[dict()]))
|
||||
port = dict(port=dict(network_id=1, tenant_id=self.context.tenant_id,
|
||||
device_id=2))
|
||||
ip = dict(id=1, address=netaddr.IPAddress('192.168.1.100'),
|
||||
address_readable="192.168.1.100", subnet_id=1, network_id=2,
|
||||
version=4, deallocated=True)
|
||||
with self._stubs(port=port, addr=ip) as (port_find, alloc_ip, ip_find):
|
||||
response = self.plugin.post_update_port(self.context, 1,
|
||||
new_port_ip)
|
||||
self.assertEqual(port_find.call_count, 1)
|
||||
self.assertEqual(alloc_ip.call_count, 1)
|
||||
self.assertEqual(ip_find.call_count, 0)
|
||||
self.assertEqual(response["fixed_ips"][0]["ip_address"],
|
||||
"192.168.1.100")
|
||||
|
||||
def test_post_update_port_fixed_ips_ip_id(self):
|
||||
new_port_ip = dict(port=dict(fixed_ips=[dict(ip_id=1)]))
|
||||
port = dict(port=dict(network_id=1, tenant_id=self.context.tenant_id,
|
||||
device_id=2))
|
||||
ip = dict(id=1, address=netaddr.IPAddress('192.168.1.100'),
|
||||
address_readable="192.168.1.100", subnet_id=1, network_id=2,
|
||||
version=4, deallocated=True)
|
||||
with self._stubs(port=port, addr=ip) as (port_find, alloc_ip, ip_find):
|
||||
response = self.plugin.post_update_port(self.context, 1,
|
||||
new_port_ip)
|
||||
self.assertEqual(port_find.call_count, 1)
|
||||
self.assertEqual(alloc_ip.call_count, 0)
|
||||
self.assertEqual(ip_find.call_count, 1)
|
||||
self.assertEqual(response["fixed_ips"][0]["ip_address"],
|
||||
"192.168.1.100")
|
||||
|
||||
def test_post_update_port_fixed_ips_ip_address_exists(self):
|
||||
new_port_ip = dict(port=dict(fixed_ips=[dict(
|
||||
ip_address="192.168.1.100")]))
|
||||
port = dict(port=dict(network_id=1, tenant_id=self.context.tenant_id,
|
||||
device_id=2))
|
||||
ip = dict(id=1, address=netaddr.IPAddress('192.168.1.100'),
|
||||
address_readable="192.168.1.100", subnet_id=1, network_id=2,
|
||||
version=4, deallocated=True)
|
||||
with self._stubs(port=port, addr=ip) as (port_find, alloc_ip, ip_find):
|
||||
response = self.plugin.post_update_port(self.context, 1,
|
||||
new_port_ip)
|
||||
self.assertEqual(port_find.call_count, 1)
|
||||
self.assertEqual(alloc_ip.call_count, 0)
|
||||
self.assertEqual(ip_find.call_count, 1)
|
||||
self.assertEqual(response["fixed_ips"][0]["ip_address"],
|
||||
"192.168.1.100")
|
||||
|
||||
def test_post_update_port_fixed_ips_ip_address_doesnt_exist(self):
|
||||
new_port_ip = dict(port=dict(fixed_ips=[dict(
|
||||
ip_address="192.168.1.101")]))
|
||||
port = dict(port=dict(network_id=1, tenant_id=self.context.tenant_id,
|
||||
device_id=2))
|
||||
ip = dict(id=1, address=3232235876, address_readable="192.168.1.101",
|
||||
subnet_id=1, network_id=2, version=4, deallocated=True)
|
||||
with self._stubs(port=port, addr=None, addr2=ip) as (port_find,
|
||||
alloc_ip,
|
||||
ip_find):
|
||||
response = self.plugin.post_update_port(self.context, 1,
|
||||
new_port_ip)
|
||||
self.assertEqual(port_find.call_count, 1)
|
||||
self.assertEqual(alloc_ip.call_count, 1)
|
||||
self.assertEqual(ip_find.call_count, 1)
|
||||
self.assertEqual(response["fixed_ips"][0]["ip_address"],
|
||||
"192.168.1.101")
|
||||
|
||||
def test_post_update_port_already_has_ip(self):
|
||||
new_port_ip = dict(port=dict(fixed_ips=[dict()]))
|
||||
port = dict(port=dict(network_id=1, tenant_id=self.context.tenant_id,
|
||||
device_id=2))
|
||||
ip = dict(id=1, address=netaddr.IPAddress('192.168.1.100'),
|
||||
address_readable="192.168.1.100", subnet_id=1, network_id=2,
|
||||
version=4, deallocated=True)
|
||||
port_ips = [ip]
|
||||
with self._stubs(port=port, addr=ip, port_ips=port_ips) as (port_find,
|
||||
alloc_ip,
|
||||
ip_find):
|
||||
response = self.plugin.post_update_port(self.context, 1,
|
||||
new_port_ip)
|
||||
self.assertEqual(port_find.call_count, 1)
|
||||
self.assertEqual(alloc_ip.call_count, 1)
|
||||
self.assertEqual(ip_find.call_count, 0)
|
||||
self.assertEqual(response["fixed_ips"][0]["ip_address"],
|
||||
"192.168.1.100")
|
||||
|
||||
|
||||
class TestQuarkCreatePortOnSharedNetworks(test_quark_plugin.TestQuarkPlugin):
|
||||
@contextlib.contextmanager
|
||||
def _stubs(self, port=None, network=None, addr=None, mac=None):
|
||||
|
Loading…
x
Reference in New Issue
Block a user