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 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
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user