filter backend_port response objects before updating db port args
JIRA:NCP-1743
This commit is contained in:
@@ -28,10 +28,12 @@ from quark import exceptions as q_exc
|
|||||||
from quark import ipam
|
from quark import ipam
|
||||||
from quark import network_strategy
|
from quark import network_strategy
|
||||||
from quark import plugin_views as v
|
from quark import plugin_views as v
|
||||||
|
from quark import tags
|
||||||
from quark import utils
|
from quark import utils
|
||||||
|
|
||||||
CONF = cfg.CONF
|
CONF = cfg.CONF
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
PORT_TAG_REGISTRY = tags.PORT_TAG_REGISTRY
|
||||||
STRATEGY = network_strategy.STRATEGY
|
STRATEGY = network_strategy.STRATEGY
|
||||||
|
|
||||||
|
|
||||||
@@ -56,6 +58,20 @@ def _get_net_driver(network, port=None):
|
|||||||
msg="invalid network_plugin: %s" % e)
|
msg="invalid network_plugin: %s" % e)
|
||||||
|
|
||||||
|
|
||||||
|
# NOTE(morgabra) Backend driver operations return a lot of stuff. We use a
|
||||||
|
# small subset of this data, so we filter out things we don't care about
|
||||||
|
# so we can avoid any collisions with real port data.
|
||||||
|
def _filter_backend_port(backend_port):
|
||||||
|
# Collect a list of allowed keys in the driver response
|
||||||
|
required_keys = ["uuid"]
|
||||||
|
tag_keys = [tag for tag in PORT_TAG_REGISTRY.tags.keys()]
|
||||||
|
|
||||||
|
allowed_keys = required_keys + tag_keys
|
||||||
|
for k in backend_port.keys():
|
||||||
|
if k not in allowed_keys:
|
||||||
|
del backend_port[k]
|
||||||
|
|
||||||
|
|
||||||
def split_and_validate_requested_subnets(context, net_id, segment_id,
|
def split_and_validate_requested_subnets(context, net_id, segment_id,
|
||||||
fixed_ips):
|
fixed_ips):
|
||||||
subnets = []
|
subnets = []
|
||||||
@@ -230,6 +246,7 @@ def create_port(context, port):
|
|||||||
port_id=port_id,
|
port_id=port_id,
|
||||||
security_groups=group_ids,
|
security_groups=group_ids,
|
||||||
device_id=device_id)
|
device_id=device_id)
|
||||||
|
_filter_backend_port(backend_port)
|
||||||
return backend_port
|
return backend_port
|
||||||
|
|
||||||
@cmd_mgr.undo
|
@cmd_mgr.undo
|
||||||
|
|||||||
@@ -1154,14 +1154,19 @@ class TestPortDiagnose(test_quark_plugin.TestQuarkPlugin):
|
|||||||
|
|
||||||
class TestPortNetworkPlugin(test_quark_plugin.TestQuarkPlugin):
|
class TestPortNetworkPlugin(test_quark_plugin.TestQuarkPlugin):
|
||||||
@contextlib.contextmanager
|
@contextlib.contextmanager
|
||||||
def _stubs(self, network=None, addr=None, mac=None, compat_map=None):
|
def _stubs(self, network=None, addr=None, mac=None,
|
||||||
|
compat_map=None, driver_res=None):
|
||||||
network["ipam_strategy"] = "ANY"
|
network["ipam_strategy"] = "ANY"
|
||||||
|
|
||||||
|
# Response from the backend driver
|
||||||
|
if driver_res is None:
|
||||||
|
driver_res = {"uuid": 1}
|
||||||
|
|
||||||
# Mock out the driver registry
|
# Mock out the driver registry
|
||||||
foo_driver = mock.Mock()
|
foo_driver = mock.Mock()
|
||||||
foo_driver.create_port.return_value = {"uuid": 1}
|
foo_driver.create_port.return_value = driver_res
|
||||||
bar_driver = mock.Mock()
|
bar_driver = mock.Mock()
|
||||||
bar_driver.create_port.return_value = {"uuid": 1}
|
bar_driver.create_port.return_value = driver_res
|
||||||
drivers = {"FOO": foo_driver,
|
drivers = {"FOO": foo_driver,
|
||||||
"BAR": bar_driver}
|
"BAR": bar_driver}
|
||||||
compat_map = compat_map or {}
|
compat_map = compat_map or {}
|
||||||
@@ -1352,6 +1357,82 @@ class TestPortNetworkPlugin(test_quark_plugin.TestQuarkPlugin):
|
|||||||
security_groups=[], addresses=[],
|
security_groups=[], addresses=[],
|
||||||
network_plugin=expected_network_plugin)
|
network_plugin=expected_network_plugin)
|
||||||
|
|
||||||
|
def test_create_port_network_plugin_response_no_uuid_raises(self):
|
||||||
|
network_dict = dict(id=1, tenant_id=self.context.tenant_id)
|
||||||
|
port_name = "foobar"
|
||||||
|
mac = dict(address="AA:BB:CC:DD:EE:FF")
|
||||||
|
ip = dict()
|
||||||
|
port = dict(port=dict(mac_address=mac["address"], network_id=1,
|
||||||
|
tenant_id=self.context.tenant_id, device_id=2,
|
||||||
|
name=port_name))
|
||||||
|
network = models.Network()
|
||||||
|
network.update(network_dict)
|
||||||
|
network["network_plugin"] = "FOO"
|
||||||
|
port_model = models.Port()
|
||||||
|
port_model.update(port)
|
||||||
|
port_models = port_model
|
||||||
|
|
||||||
|
with self._stubs(network=network, addr=ip,
|
||||||
|
mac=mac, driver_res={}) as (port_create,
|
||||||
|
alloc_mac,
|
||||||
|
net_find):
|
||||||
|
port_create.return_value = port_models
|
||||||
|
|
||||||
|
exc = "uuid"
|
||||||
|
with self.assertRaisesRegexp(KeyError, exc):
|
||||||
|
self.plugin.create_port(self.context, port)
|
||||||
|
|
||||||
|
def test_create_port_network_plugin_response_is_filtered(self):
|
||||||
|
network = dict(id=1, tenant_id=self.context.tenant_id,
|
||||||
|
network_plugin="FOO")
|
||||||
|
mac = dict(address="AA:BB:CC:DD:EE:FF")
|
||||||
|
port_name = "foobar"
|
||||||
|
ip = dict()
|
||||||
|
|
||||||
|
port = dict(port=dict(mac_address=mac["address"], network_id=1,
|
||||||
|
tenant_id=self.context.tenant_id, device_id=2,
|
||||||
|
name=port_name, device_owner="quark_tests",
|
||||||
|
bridge="quark_bridge", admin_state_up=False))
|
||||||
|
|
||||||
|
expected_mac = "DE:AD:BE:EF:00:00"
|
||||||
|
expected_bridge = "new_bridge"
|
||||||
|
expected_device_owner = "new_device_owner"
|
||||||
|
expected_admin_state = "new_state"
|
||||||
|
|
||||||
|
port_create_dict = {}
|
||||||
|
port_create_dict["port"] = port["port"].copy()
|
||||||
|
port_create_dict["port"]["mac_address"] = expected_mac
|
||||||
|
port_create_dict["port"]["device_owner"] = expected_device_owner
|
||||||
|
port_create_dict["port"]["bridge"] = expected_bridge
|
||||||
|
port_create_dict["port"]["admin_state_up"] = expected_admin_state
|
||||||
|
|
||||||
|
driver_res = {
|
||||||
|
"uuid": 5,
|
||||||
|
"vlan_id": 50,
|
||||||
|
"tags": [123, {"foo": "bar"}],
|
||||||
|
"id": "fail",
|
||||||
|
"randomkey": None
|
||||||
|
}
|
||||||
|
|
||||||
|
admin_ctx = self.context.elevated()
|
||||||
|
with self._stubs(network=network, addr=ip,
|
||||||
|
mac=mac, driver_res=driver_res) as (port_create,
|
||||||
|
alloc_mac,
|
||||||
|
net_find):
|
||||||
|
self.plugin.create_port(admin_ctx, port_create_dict)
|
||||||
|
|
||||||
|
alloc_mac.assert_called_once_with(
|
||||||
|
admin_ctx, network["id"], 1,
|
||||||
|
cfg.CONF.QUARK.ipam_reuse_after,
|
||||||
|
mac_address=expected_mac, use_forbidden_mac_range=False)
|
||||||
|
|
||||||
|
port_create.assert_called_once_with(
|
||||||
|
admin_ctx, bridge=expected_bridge, uuid=5, name="foobar",
|
||||||
|
admin_state_up=expected_admin_state, network_id=1,
|
||||||
|
tenant_id="fake", id=1, device_owner=expected_device_owner,
|
||||||
|
mac_address=mac["address"], device_id=2, backend_key=5,
|
||||||
|
security_groups=[], addresses=[], vlan_id=50)
|
||||||
|
|
||||||
|
|
||||||
class TestQuarkPortCreateFiltering(test_quark_plugin.TestQuarkPlugin):
|
class TestQuarkPortCreateFiltering(test_quark_plugin.TestQuarkPlugin):
|
||||||
@contextlib.contextmanager
|
@contextlib.contextmanager
|
||||||
|
|||||||
Reference in New Issue
Block a user