From 28d2e699b577800b866c33b05de5ff477e4c420d Mon Sep 17 00:00:00 2001 From: Kevin Benton Date: Sun, 22 Jan 2017 16:47:53 -0800 Subject: [PATCH] Fixes to allow OVO deserializion of ports/networks A few fixes required to allow deserialization/serialization of OVO resources. * Set shared to False when context is missing for RBAC calculations * Parse strings received from json into netaddr objects Partially-Implements: blueprint push-notifications Change-Id: I1609014d6100a0c410c66d159f9e682d8aa3e7ba --- neutron/objects/common_types.py | 17 +++++++++++++++++ neutron/objects/rbac_db.py | 11 ++++++++--- neutron/tests/unit/objects/test_common_types.py | 16 +++++++++++----- neutron/tests/unit/objects/test_rbac_db.py | 4 ++++ 4 files changed, 40 insertions(+), 8 deletions(-) diff --git a/neutron/objects/common_types.py b/neutron/objects/common_types.py index d51c4a8b231..65129abfa4e 100644 --- a/neutron/objects/common_types.py +++ b/neutron/objects/common_types.py @@ -24,6 +24,7 @@ import six from neutron._i18n import _ from neutron.common import constants +from neutron.common import utils from neutron.objects import exceptions as o_exc from neutron.plugins.common import constants as plugin_constants @@ -205,6 +206,14 @@ class MACAddress(obj_fields.FieldType): def to_primitive(obj, attr, value): return str(value) + @staticmethod + def from_primitive(obj, attr, value): + try: + return utils.AuthenticEUI(value) + except Exception: + msg = _("Field value %s is not a netaddr.EUI") % value + raise ValueError(msg) + class MACAddressField(obj_fields.AutoTypedField): AUTO_TYPE = MACAddress() @@ -264,6 +273,14 @@ class IPNetwork(obj_fields.FieldType): def to_primitive(obj, attr, value): return str(value) + @staticmethod + def from_primitive(obj, attr, value): + try: + return utils.AuthenticIPNetwork(value) + except Exception: + msg = _("Field value %s is not a netaddr.IPNetwork") % value + raise ValueError(msg) + class IPNetworkField(obj_fields.AutoTypedField): AUTO_TYPE = IPNetwork() diff --git a/neutron/objects/rbac_db.py b/neutron/objects/rbac_db.py index 5f4bac52136..17c9dad5842 100644 --- a/neutron/objects/rbac_db.py +++ b/neutron/objects/rbac_db.py @@ -254,9 +254,14 @@ def _create_hook(self, orig_create): def _to_dict_hook(self, to_dict_orig): dct = to_dict_orig(self) - dct['shared'] = self.is_shared_with_tenant(self.obj_context, - self.id, - self.obj_context.tenant_id) + if self.obj_context: + dct['shared'] = self.is_shared_with_tenant(self.obj_context, + self.id, + self.obj_context.tenant_id) + else: + # most OVO objects on an agent will not have a context set on the + # object because they will be generated from obj_from_primitive. + dct['shared'] = False return dct diff --git a/neutron/tests/unit/objects/test_common_types.py b/neutron/tests/unit/objects/test_common_types.py index 2eab7e0308b..2c1b1a53457 100644 --- a/neutron/tests/unit/objects/test_common_types.py +++ b/neutron/tests/unit/objects/test_common_types.py @@ -52,8 +52,11 @@ class TestField(object): _context = 'context' for prim_val, out_val in self.from_primitive_values: - self.assertEqual(out_val, self.field.from_primitive( - ObjectLikeThing, 'attr', prim_val)) + from_prim = self.field.from_primitive(ObjectLikeThing, 'attr', + prim_val) + self.assertEqual(out_val, from_prim) + # ensure it's coercable for sanity + self.field.coerce('obj', 'attr', from_prim) @abc.abstractmethod def test_stringify(self): @@ -117,8 +120,10 @@ class MACAddressFieldTest(test_base.BaseTestCase, TestField): # if they represent a valid MAC address tools.get_random_mac(), ] - self.to_primitive_values = self.coerce_good_values - self.from_primitive_values = self.coerce_good_values + self.to_primitive_values = ((a1, str(a2)) + for a1, a2 in self.coerce_good_values) + self.from_primitive_values = ((a2, a1) + for a1, a2 in self.to_primitive_values) def test_stringify(self): for in_val, out_val in self.coerce_good_values: @@ -142,7 +147,8 @@ class IPNetworkFieldTest(test_base.BaseTestCase, TestField): ] self.to_primitive_values = ((a1, str(a2)) for a1, a2 in self.coerce_good_values) - self.from_primitive_values = self.coerce_good_values + self.from_primitive_values = ((a2, a1) + for a1, a2 in self.to_primitive_values) def test_stringify(self): for in_val, out_val in self.coerce_good_values: diff --git a/neutron/tests/unit/objects/test_rbac_db.py b/neutron/tests/unit/objects/test_rbac_db.py index fe230b9c794..ebd4bb292df 100644 --- a/neutron/tests/unit/objects/test_rbac_db.py +++ b/neutron/tests/unit/objects/test_rbac_db.py @@ -281,6 +281,10 @@ class RbacNeutronDbObjectTestCase(test_base.BaseObjectIfaceTestCase, attach_rbac_mock.assert_called_with( obj_id, test_neutron_obj.obj_context.tenant_id) + def test_shared_field_false_without_context(self): + test_neutron_obj = self._test_class() + self.assertFalse(test_neutron_obj.to_dict()['shared']) + @mock.patch.object(_test_class, 'attach_rbac') @mock.patch.object(obj_db_api, 'get_object', return_value=['fake_rbac_policy'])