]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Encapsulate some port properties in the PortContext
authorarmando-migliaccio <armamig@gmail.com>
Fri, 18 Jul 2014 00:22:49 +0000 (17:22 -0700)
committerarmando-migliaccio <armamig@gmail.com>
Thu, 24 Jul 2014 23:40:59 +0000 (16:40 -0700)
Bindings to host or status may need further encapsulation
to avoid exposing mechanism drivers to underlying DB model
details. This was particularly true in the case of the
l2pop mech driver.

As a result, some docstrings were reworded, and the newly
introduced properties used directly in the mech drivers.

Partially-implements: blueprint neutron-ovs-dvr
Supports blueprint: ml2-hierarchical-port-binding

Change-Id: If2a373ef04d19b164585fb4bde4fe6e0cfaf43be

neutron/plugins/ml2/driver_api.py
neutron/plugins/ml2/driver_context.py
neutron/plugins/ml2/drivers/arista/mechanism_arista.py
neutron/plugins/ml2/drivers/cisco/apic/mechanism_apic.py
neutron/plugins/ml2/drivers/cisco/nexus/mech_cisco_nexus.py
neutron/plugins/ml2/drivers/l2pop/mech_driver.py
neutron/tests/unit/ml2/_test_mech_agent.py
neutron/tests/unit/ml2/drivers/arista/test_arista_mechanism_driver.py
neutron/tests/unit/ml2/drivers/cisco/apic/test_cisco_apic_mechanism_driver.py

index 8b0484d13f26b12a3bc0c201353bc77dbd52c34e..779ebdf92d2efe070690332d4a71085f9ae9286d 100644 (file)
@@ -149,21 +149,23 @@ class NetworkContext(object):
 
     @abc.abstractproperty
     def current(self):
-        """Return the current state of the network.
+        """Return the network in its current configuration.
 
-        Return the current state of the network, as defined by
-        NeutronPluginBaseV2.create_network and all extensions in the
-        ml2 plugin.
+        Return the network, as defined by NeutronPluginBaseV2.
+        create_network and all extensions in the ml2 plugin, with
+        all its properties 'current' at the time the context was
+        established.
         """
         pass
 
     @abc.abstractproperty
     def original(self):
-        """Return the original state of the network.
+        """Return the network in its original configuration.
 
-        Return the original state of the network, prior to a call to
-        update_network. Method is only valid within calls to
-        update_network_precommit and update_network_postcommit.
+        Return the network, with all its properties set to their
+        original values prior to a call to update_network. Method is
+        only valid within calls to update_network_precommit and
+        update_network_postcommit.
         """
         pass
 
@@ -185,21 +187,23 @@ class SubnetContext(object):
 
     @abc.abstractproperty
     def current(self):
-        """Return the current state of the subnet.
+        """Return the subnet in its current configuration.
 
-        Return the current state of the subnet, as defined by
-        NeutronPluginBaseV2.create_subnet and all extensions in the
-        ml2 plugin.
+        Return the subnet, as defined by NeutronPluginBaseV2.
+        create_subnet and all extensions in the ml2 plugin, with
+        all its properties 'current' at the time the context was
+        established.
         """
         pass
 
     @abc.abstractproperty
     def original(self):
-        """Return the original state of the subnet.
+        """Return the subnet in its original configuration.
 
-        Return the original state of the subnet, prior to a call to
-        update_subnet. Method is only valid within calls to
-        update_subnet_precommit and update_subnet_postcommit.
+        Return the subnet, with all its properties set to their
+        original values prior to a call to update_subnet. Method is
+        only valid within calls to update_subnet_precommit and
+        update_subnet_postcommit.
         """
         pass
 
@@ -216,21 +220,37 @@ class PortContext(object):
 
     @abc.abstractproperty
     def current(self):
-        """Return the current state of the port.
+        """Return the port in its current configuration.
 
-        Return the current state of the port, as defined by
-        NeutronPluginBaseV2.create_port and all extensions in the ml2
-        plugin.
+        Return the port, as defined by NeutronPluginBaseV2.
+        create_port and all extensions in the ml2 plugin, with
+        all its properties 'current' at the time the context was
+        established.
         """
         pass
 
     @abc.abstractproperty
     def original(self):
-        """Return the original state of the port.
+        """Return the port in its original configuration.
 
-        Return the original state of the port, prior to a call to
-        update_port. Method is only valid within calls to
-        update_port_precommit and update_port_postcommit.
+        Return the port, with all its properties set to their
+        original values prior to a call to update_port. Method is
+        only valid within calls to update_port_precommit and
+        update_port_postcommit.
+        """
+        pass
+
+    @abc.abstractproperty
+    def status(self):
+        """Return the status of the current port."""
+        pass
+
+    @abc.abstractproperty
+    def original_status(self):
+        """Return the status of the original port.
+
+        The method is only valid within calls to update_port_precommit and
+        update_port_postcommit.
         """
         pass
 
@@ -254,6 +274,20 @@ class PortContext(object):
         """
         pass
 
+    @abc.abstractproperty
+    def host(self):
+        """Return the host associated with the 'current' port."""
+        pass
+
+    @abc.abstractproperty
+    def original_host(self):
+        """Return the host associated with the 'original' port.
+
+        Method is only valid within calls to update_port_precommit
+        and update_port_postcommit.
+        """
+        pass
+
     @abc.abstractproperty
     def bound_driver(self):
         """Return the currently bound mechanism driver name."""
index 08f9b12c93281bed4cc443758bb9f995e7f96be2..62b5782171454378a14bd9700fced0cc2ce759c9 100644 (file)
@@ -13,6 +13,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+from neutron.extensions import portbindings
 from neutron.openstack.common import jsonutils
 from neutron.plugins.ml2 import db
 from neutron.plugins.ml2 import driver_api as api
@@ -93,6 +94,14 @@ class PortContext(MechanismDriverContext, api.PortContext):
     def original(self):
         return self._original_port
 
+    @property
+    def status(self):
+        return self._port['status']
+
+    @property
+    def original_status(self):
+        return self._original_port['status']
+
     @property
     def network(self):
         return self._network_context
@@ -112,6 +121,14 @@ class PortContext(MechanismDriverContext, api.PortContext):
                 if segment[api.ID] == self._original_bound_segment_id:
                     return segment
 
+    @property
+    def host(self):
+        return self._port.get(portbindings.HOST_ID)
+
+    @property
+    def original_host(self):
+        return self._original_port.get(portbindings.HOST_ID)
+
     @property
     def bound_driver(self):
         return self._binding.driver
index a86d542d9468553128bcc4e9bb1f9856fd836aec..08a1696b159db00d3832c61515fbed05a67b19ea 100644 (file)
@@ -19,7 +19,6 @@ import jsonrpclib
 from oslo.config import cfg
 
 from neutron.common import constants as n_const
-from neutron.extensions import portbindings
 from neutron.openstack.common import log as logging
 from neutron.plugins.ml2.common import exceptions as ml2_exc
 from neutron.plugins.ml2 import driver_api
@@ -801,7 +800,7 @@ class AristaDriver(driver_api.MechanismDriver):
         port = context.current
         device_id = port['device_id']
         device_owner = port['device_owner']
-        host = port[portbindings.HOST_ID]
+        host = context.host
 
         # device_id and device_owner are set on VM boot
         is_vm_boot = device_id and device_owner
@@ -822,7 +821,7 @@ class AristaDriver(driver_api.MechanismDriver):
         port = context.current
         device_id = port['device_id']
         device_owner = port['device_owner']
-        host = port[portbindings.HOST_ID]
+        host = context.host
 
         # device_id and device_owner are set on VM boot
         is_vm_boot = device_id and device_owner
@@ -885,7 +884,7 @@ class AristaDriver(driver_api.MechanismDriver):
 
         device_id = port['device_id']
         device_owner = port['device_owner']
-        host = port[portbindings.HOST_ID]
+        host = context.host
         is_vm_boot = device_id and device_owner
 
         if host and is_vm_boot:
@@ -926,7 +925,7 @@ class AristaDriver(driver_api.MechanismDriver):
         """Delete information about a VM and host from the DB."""
         port = context.current
 
-        host_id = port[portbindings.HOST_ID]
+        host_id = context.host
         device_id = port['device_id']
         tenant_id = port['tenant_id']
         network_id = port['network_id']
@@ -947,7 +946,7 @@ class AristaDriver(driver_api.MechanismDriver):
         """
         port = context.current
         device_id = port['device_id']
-        host = port[portbindings.HOST_ID]
+        host = context.host
         port_id = port['id']
         network_id = port['network_id']
         tenant_id = port['tenant_id']
index d5297df68ae010671e27225e680eabce3f4b81a8..f526fd7467ecd6ace21b850c8106b2815a147ef1 100644 (file)
@@ -93,7 +93,7 @@ class APICMechanismDriver(api.MechanismDriver):
             # Not a compute port, return
             return
 
-        host = port.get(portbindings.HOST_ID)
+        host = context.host
         # Check host that the dhcp agent is running on
         filters = {'device_owner': 'network:dhcp',
                    'network_id': network}
index 8db75282971601ec41351f796eb02552020ab80a..e77212ffbae65b32eeff0486780067f4294e1a46 100644 (file)
@@ -155,8 +155,7 @@ class CiscoNexusMechanismDriver(api.MechanismDriver):
 
     def _is_vm_migration(self, context):
         if not context.bound_segment and context.original_bound_segment:
-            return (context.current.get(portbindings.HOST_ID) !=
-                    context.original.get(portbindings.HOST_ID))
+            return context.host != context.original_host
 
     def _port_action(self, port, segment, func):
         """Verify configuration and then process event."""
index 531dd5ee33f303df6e690f3b63174cfcb0a0d307..ede0f8df4ec9b5a33c6b858d65d3b3798d7636df 100644 (file)
@@ -48,7 +48,8 @@ class L2populationMechanismDriver(api.MechanismDriver,
                  ip['ip_address']] for ip in port['fixed_ips']]
 
     def delete_port_postcommit(self, context):
-        fanout_msg = self._update_port_down(context, context.current)
+        fanout_msg = self._update_port_down(
+            context, context.current, context.host)
         if fanout_msg:
             self.L2populationAgentNotify.remove_fdb_entries(
                 self.rpc_ctx, fanout_msg)
@@ -67,7 +68,8 @@ class L2populationMechanismDriver(api.MechanismDriver,
     def _fixed_ips_changed(self, context, orig, port, diff_ips):
         orig_ips, port_ips = diff_ips
 
-        port_infos = self._get_port_infos(context, orig)
+        port_infos = self._get_port_infos(
+            context, orig, context.original_host)
         if not port_infos:
             return
         agent, agent_ip, segment, port_fdb_entries = port_infos
@@ -96,30 +98,34 @@ class L2populationMechanismDriver(api.MechanismDriver,
         diff_ips = self._get_diff_ips(orig, port)
         if diff_ips:
             self._fixed_ips_changed(context, orig, port, diff_ips)
-        if (port['binding:host_id'] != orig['binding:host_id']
-            and port['status'] == const.PORT_STATUS_ACTIVE
+        if (context.host != context.original_host
+            and context.status == const.PORT_STATUS_ACTIVE
             and not self.migrated_ports.get(orig['id'])):
             # The port has been migrated. We have to store the original
             # binding to send appropriate fdb once the port will be set
             # on the destination host
-            self.migrated_ports[orig['id']] = orig
-        elif port['status'] != orig['status']:
-            if port['status'] == const.PORT_STATUS_ACTIVE:
+            self.migrated_ports[orig['id']] = (
+                (orig, context.original_host))
+        elif context.status != context.original_status:
+            if context.status == const.PORT_STATUS_ACTIVE:
                 self._update_port_up(context)
-            elif port['status'] == const.PORT_STATUS_DOWN:
-                fdb_entries = self._update_port_down(context, port)
+            elif context.status == const.PORT_STATUS_DOWN:
+                fdb_entries = self._update_port_down(
+                    context, port, context.host)
                 self.L2populationAgentNotify.remove_fdb_entries(
                     self.rpc_ctx, fdb_entries)
-            elif port['status'] == const.PORT_STATUS_BUILD:
+            elif context.status == const.PORT_STATUS_BUILD:
                 orig = self.migrated_ports.pop(port['id'], None)
                 if orig:
-                    # this port has been migrated : remove its entries from fdb
-                    fdb_entries = self._update_port_down(context, orig)
+                    original_port = orig[0]
+                    original_host = orig[1]
+                    # this port has been migrated: remove its entries from fdb
+                    fdb_entries = self._update_port_down(
+                        context, original_port, original_host)
                     self.L2populationAgentNotify.remove_fdb_entries(
                         self.rpc_ctx, fdb_entries)
 
-    def _get_port_infos(self, context, port):
-        agent_host = port['binding:host_id']
+    def _get_port_infos(self, context, port, agent_host):
         if not agent_host:
             return
 
@@ -150,14 +156,14 @@ class L2populationMechanismDriver(api.MechanismDriver,
         return agent, agent_ip, segment, fdb_entries
 
     def _update_port_up(self, context):
-        port_context = context.current
-        port_infos = self._get_port_infos(context, port_context)
+        port = context.current
+        agent_host = context.host
+        port_infos = self._get_port_infos(context, port, agent_host)
         if not port_infos:
             return
         agent, agent_ip, segment, port_fdb_entries = port_infos
 
-        agent_host = port_context['binding:host_id']
-        network_id = port_context['network_id']
+        network_id = port['network_id']
 
         session = db_api.get_session()
         agent_active_ports = self.get_agent_network_active_port_count(
@@ -209,14 +215,13 @@ class L2populationMechanismDriver(api.MechanismDriver,
         self.L2populationAgentNotify.add_fdb_entries(self.rpc_ctx,
                                                      other_fdb_entries)
 
-    def _update_port_down(self, context, port_context):
-        port_infos = self._get_port_infos(context, port_context)
+    def _update_port_down(self, context, port, agent_host):
+        port_infos = self._get_port_infos(context, port, agent_host)
         if not port_infos:
             return
         agent, agent_ip, segment, port_fdb_entries = port_infos
 
-        agent_host = port_context['binding:host_id']
-        network_id = port_context['network_id']
+        network_id = port['network_id']
 
         session = db_api.get_session()
         agent_active_ports = self.get_agent_network_active_port_count(
index 4fbdc10e5ce91f6698cf6a49a8335783a8c059af..79f108e3a4d46c1966c8b2bfc7a7c622ba249d4c 100644 (file)
@@ -59,6 +59,14 @@ class FakePortContext(api.PortContext):
     def original(self):
         return None
 
+    @property
+    def status(self):
+        return 'DOWN'
+
+    @property
+    def original_status(self):
+        return None
+
     @property
     def network(self):
         return self._network_context
@@ -74,6 +82,14 @@ class FakePortContext(api.PortContext):
     def original_bound_segment(self):
         return None
 
+    @property
+    def host(self):
+        return ''
+
+    @property
+    def original_host(self):
+        return None
+
     @property
     def bound_driver(self):
         return None
index 42028a8fe32cf7e117b0e0c307f794ae2060da78..8749d50734639e5e05ae962c7bc338dd5a466688 100644 (file)
@@ -18,6 +18,7 @@ from oslo.config import cfg
 
 from neutron.common import constants as n_const
 import neutron.db.api as ndb
+from neutron.extensions import portbindings
 from neutron.plugins.ml2.drivers.arista import db
 from neutron.plugins.ml2.drivers.arista import exceptions as arista_exc
 from neutron.plugins.ml2.drivers.arista import mechanism_arista as arista
@@ -723,3 +724,11 @@ class FakePortContext(object):
     @property
     def network(self):
         return self._network_context
+
+    @property
+    def host(self):
+        return self._port.get(portbindings.HOST_ID)
+
+    @property
+    def original_host(self):
+        return self._original_port.get(portbindings.HOST_ID)
index 6addd43827dcde0bf519fc4174c73dadbd0d565b..fbd30e67d17a95f1b669b36377e57a67165c864f 100644 (file)
@@ -19,6 +19,7 @@ import mock
 
 from oslo.config import cfg
 
+from neutron.extensions import portbindings
 from neutron.plugins.ml2.drivers.cisco.apic import mechanism_apic as md
 from neutron.plugins.ml2.drivers import type_vlan  # noqa
 from neutron.tests import base
@@ -224,3 +225,11 @@ class FakePortContext(object):
 
     def set_binding(self, segment_id, vif_type, cap_port_filter):
         pass
+
+    @property
+    def host(self):
+        return self._port.get(portbindings.HOST_ID)
+
+    @property
+    def original_host(self):
+        return self._original_port.get(portbindings.HOST_ID)