Merge "Add rollback for Cisco plugin update_port failure"

This commit is contained in:
Jenkins 2013-06-03 02:03:42 +00:00 committed by Gerrit Code Review
commit ffbe2cd55e
2 changed files with 64 additions and 29 deletions

View File

@ -21,6 +21,7 @@
import inspect
import logging
import sys
from novaclient.v1_1 import client as nova_client
from oslo.config import cfg
@ -213,31 +214,20 @@ class VirtualPhysicalSwitchModelV2(quantum_plugin_base_v2.QuantumPluginBaseV2):
Perform this operation in the context of the configured device
plugins.
Note that the Nexus sub-plugin does not need to be notified
(and the Nexus switch does not need to be [re]configured)
for an update network operation because the Nexus sub-plugin
is agnostic of all network-level attributes except the
segmentation ID. Furthermore, updating of the segmentation ID
is not supported by the OVS plugin since it is considered a
provider attribute, so it is not supported by this method.
"""
LOG.debug(_("update_network() called"))
args = [context, id, network]
ovs_output = self._invoke_plugin_per_device(const.VSWITCH_PLUGIN,
self._func_name(),
args)
try:
vlan_id = self._get_segmentation_id(ovs_output[0]['id'])
if not self._validate_vlan_id(vlan_id):
return ovs_output[0]
vlan_ids = self._get_all_segmentation_ids()
args = [ovs_output[0]['tenant_id'], id, {'vlan_id': vlan_id},
{'net_admin_state': ovs_output[0]['admin_state_up']},
{'vlan_ids': vlan_ids}]
self._invoke_plugin_per_device(const.NEXUS_PLUGIN,
self._func_name(),
args)
except Exception:
# TODO(dane): The call to the nexus plugin update network
# failed, so the OVS plugin should be rolled back, that is,
# "re-updated" back to the original network config.
LOG.exception(_("Unable to update network '%s' on Nexus switch"),
network['network']['name'])
raise
return ovs_output[0]
def delete_network(self, context, id):
@ -304,9 +294,10 @@ class VirtualPhysicalSwitchModelV2(quantum_plugin_base_v2.QuantumPluginBaseV2):
self._invoke_nexus_for_net_create(
context, tenant_id, net_id, instance_id)
except Exception as e:
except Exception:
# Create network on the Nexus plugin has failed, so we need
# to rollback the port creation on the VSwitch plugin.
exc_info = sys.exc_info()
try:
id = ovs_output[0]['id']
args = [context, id]
@ -316,7 +307,7 @@ class VirtualPhysicalSwitchModelV2(quantum_plugin_base_v2.QuantumPluginBaseV2):
args)
finally:
# Re-raise the original exception
raise e
raise exc_info[0], exc_info[1], exc_info[2]
return ovs_output[0]
def get_port(self, context, id, fields=None):
@ -354,12 +345,19 @@ class VirtualPhysicalSwitchModelV2(quantum_plugin_base_v2.QuantumPluginBaseV2):
return ovs_output[0]
except Exception:
# TODO(dane): The call to the nexus plugin create network
# failed, so the OVS plugin should be rolled back, that is,
# "re-updated" back to the original port config.
LOG.exception(_("Unable to update port '%s' on Nexus switch"),
port['port']['name'])
raise
exc_info = sys.exc_info()
LOG.error(_("Unable to update port '%s' on Nexus switch"),
old_port['name'], exc_info=exc_info)
try:
# Roll back vSwitch plugin to original port attributes.
args = [context, id, {'port': old_port}]
ovs_output = self._invoke_plugin_per_device(
const.VSWITCH_PLUGIN,
self._func_name(),
args)
finally:
# Re-raise the original exception
raise exc_info[0], exc_info[1], exc_info[2]
def delete_port(self, context, id):
"""Delete port.
@ -379,7 +377,8 @@ class VirtualPhysicalSwitchModelV2(quantum_plugin_base_v2.QuantumPluginBaseV2):
ovs_output = self._invoke_plugin_per_device(const.VSWITCH_PLUGIN,
self._func_name(),
args)
except Exception as e:
except Exception:
exc_info = sys.exc_info()
# Roll back the delete port on the Nexus plugin
try:
tenant_id = port['tenant_id']
@ -389,7 +388,7 @@ class VirtualPhysicalSwitchModelV2(quantum_plugin_base_v2.QuantumPluginBaseV2):
net_id, instance_id)
finally:
# Raise the original exception.
raise e
raise exc_info[0], exc_info[1], exc_info[2]
return ovs_output[0]

View File

@ -23,6 +23,7 @@ import webob.exc as wexc
from quantum.api.v2 import base
from quantum.common import exceptions as q_exc
from quantum import context
from quantum.db import db_base_plugin_v2 as base_plugin
from quantum.db import l3_db
from quantum.manager import QuantumManager
from quantum.plugins.cisco.common import cisco_constants as const
@ -407,6 +408,41 @@ class TestCiscoPortsV2(CiscoNetworkPluginV2TestCase,
)
self._assertExpectedHTTP(res.status_int, KeyError)
def test_model_update_port_rollback(self):
"""Test for proper rollback for Cisco model layer update port failure.
Test that the vSwitch plugin port configuration is rolled back
(restored) by the Cisco plugin model layer when there is a
failure in the Nexus sub-plugin for an update port operation.
"""
with self.port(fmt=self.fmt) as orig_port:
inserted_exc = ValueError
with mock.patch.object(
virt_phy_sw_v2.VirtualPhysicalSwitchModelV2,
'_invoke_nexus_for_net_create',
side_effect=inserted_exc):
# Send an update port request with a new device ID
device_id = "00fff4d0-e4a8-4a3a-8906-4c4cdafb59f1"
if orig_port['port']['device_id'] == device_id:
device_id = "600df00d-e4a8-4a3a-8906-feed600df00d"
data = {'port': {'device_id': device_id}}
port_id = orig_port['port']['id']
req = self.new_update_request('ports', data, port_id)
res = req.get_response(self.api)
# Sanity check failure result code
self._assertExpectedHTTP(res.status_int, inserted_exc)
# Check that the port still has the original device ID
plugin = base_plugin.QuantumDbPluginV2()
ctx = context.get_admin_context()
db_port = plugin._get_port(ctx, port_id)
self.assertEqual(db_port['device_id'],
orig_port['port']['device_id'])
def test_model_delete_port_rollback(self):
"""Test for proper rollback for OVS plugin delete port failure.