filter backend_port response objects before updating db port args

JIRA:NCP-1743
This commit is contained in:
Brad Morgan
2015-10-23 17:00:10 -07:00
parent 5552fd7a13
commit c0d7e7b435
2 changed files with 101 additions and 3 deletions

View File

@@ -28,10 +28,12 @@ from quark import exceptions as q_exc
from quark import ipam
from quark import network_strategy
from quark import plugin_views as v
from quark import tags
from quark import utils
CONF = cfg.CONF
LOG = logging.getLogger(__name__)
PORT_TAG_REGISTRY = tags.PORT_TAG_REGISTRY
STRATEGY = network_strategy.STRATEGY
@@ -56,6 +58,20 @@ def _get_net_driver(network, port=None):
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,
fixed_ips):
subnets = []
@@ -230,6 +246,7 @@ def create_port(context, port):
port_id=port_id,
security_groups=group_ids,
device_id=device_id)
_filter_backend_port(backend_port)
return backend_port
@cmd_mgr.undo

View File

@@ -1154,14 +1154,19 @@ class TestPortDiagnose(test_quark_plugin.TestQuarkPlugin):
class TestPortNetworkPlugin(test_quark_plugin.TestQuarkPlugin):
@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"
# Response from the backend driver
if driver_res is None:
driver_res = {"uuid": 1}
# Mock out the driver registry
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.create_port.return_value = {"uuid": 1}
bar_driver.create_port.return_value = driver_res
drivers = {"FOO": foo_driver,
"BAR": bar_driver}
compat_map = compat_map or {}
@@ -1352,6 +1357,82 @@ class TestPortNetworkPlugin(test_quark_plugin.TestQuarkPlugin):
security_groups=[], addresses=[],
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):
@contextlib.contextmanager