NSX|V rename backend edge name when router is being renamed

when exclusive/distributed router is being renamed, also rename the backed edge

Change-Id: Ida0a96ec8b33d990a8ac0ba61982ec58465678c7
This commit is contained in:
Adit Sarfaty 2016-04-24 12:35:32 +03:00
parent 2aadfa6e38
commit 57a5d18e43
6 changed files with 101 additions and 9 deletions

View File

@ -117,6 +117,8 @@ class RouterDistributedDriver(router_driver.RouterBaseDriver):
if 'admin_state_up' in r:
self.plugin._update_router_admin_state(
context, router_id, self.get_type(), r['admin_state_up'])
if 'name' in r:
self.edge_manager.rename_lrouter(context, router_id, r['name'])
return self.plugin.get_router(context, router_id)
def delete_router(self, context, router_id):

View File

@ -63,6 +63,8 @@ class RouterExclusiveDriver(router_driver.RouterBaseDriver):
if 'admin_state_up' in r:
self.plugin._update_router_admin_state(
context, router_id, self.get_type(), r['admin_state_up'])
if 'name' in r:
self.edge_manager.rename_lrouter(context, router_id, r['name'])
return self.plugin.get_router(context, router_id)
def detach_router(self, context, router_id, router):

View File

@ -26,6 +26,7 @@ from vmware_nsx.common import nsxv_constants
from vmware_nsx.common import utils
from vmware_nsx.plugins.nsx_v.vshield.common import constants
from vmware_nsx.plugins.nsx_v.vshield.common import exceptions
from vmware_nsx.plugins.nsx_v.vshield import edge_utils
from vmware_nsx.plugins.nsx_v.vshield.tasks import (
constants as task_constants)
from vmware_nsx.plugins.nsx_v.vshield.tasks import tasks
@ -451,6 +452,27 @@ class EdgeApplianceDriver(object):
return status
def _rename_edge(self, task):
edge_id = task.userdata['edge_id']
LOG.debug("start rename edge %s", edge_id)
try:
# First get the current edge structure
# [0] is the status, [1] is the body
edge = self.vcns.get_edge(edge_id)[1]
# remove some data that will make the update fail
edge_utils.remove_irrelevant_keys_from_edge_request(edge)
# set the new name in the request
edge['name'] = task.userdata['name']
# update the edge
self.vcns.update_edge(edge_id, edge)
status = task_constants.TaskStatus.COMPLETED
except exceptions.VcnsApiException as e:
LOG.error(_LE("Failed to rename edge: %s"),
e.response)
status = task_constants.TaskStatus.ERROR
return status
def _delete_edge(self, task):
edge_id = task.userdata['edge_id']
LOG.debug("VCNS: start destroying edge %s", edge_id)
@ -616,6 +638,21 @@ class EdgeApplianceDriver(object):
self.task_manager.add(task)
return task
def rename_edge(self, router_id, edge_id, name):
"""rename edge."""
task_name = 'rename-%s' % name
userdata = {
'edge_id': edge_id,
'name': name
}
task = tasks.Task(task_name, router_id,
self._rename_edge,
userdata=userdata)
task.add_result_monitor(self.callbacks.edge_rename_result)
self.task_manager.add(task)
return task
def delete_edge(self, resource_id, edge_id, jobdata=None, dist=False):
task_name = 'delete-%s' % edge_id
userdata = {

View File

@ -705,14 +705,16 @@ class EdgeManager(object):
router_id = (vcns_const.DHCP_EDGE_PREFIX + network_id)[:36]
self._free_edge_appliance(context, router_id)
def _build_lrouter_name(self, router_id, router_name):
return (
router_name[:nsxv_constants.ROUTER_NAME_LENGTH - len(router_id)] +
'-' + router_id)
def create_lrouter(
self, context, lrouter, lswitch=None, dist=False,
appliance_size=vcns_const.SERVICE_SIZE_MAPPING['router']):
"""Create an edge for logical router support."""
router_name = (
lrouter['name'][:nsxv_constants.ROUTER_NAME_LENGTH -
len(lrouter['id'])] +
'-' + lrouter['id'])
router_name = self._build_lrouter_name(lrouter['id'], lrouter['name'])
self._allocate_edge_appliance(
context, lrouter['id'], router_name,
appliance_size=appliance_size,
@ -721,6 +723,19 @@ class EdgeManager(object):
def delete_lrouter(self, context, router_id, dist=False):
self._free_edge_appliance(context, router_id)
def rename_lrouter(self, context, router_id, new_name):
binding = nsxv_db.get_nsxv_router_binding(context.session, router_id)
if not binding or not binding['edge_id']:
LOG.warning(_LW("router binding for router: %s "
"not found"), router_id)
return
edge_id = binding['edge_id']
with locking.LockManager.get_lock(str(edge_id)):
router_name = self._build_lrouter_name(router_id, new_name)
task = self.nsxv_manager.rename_edge(
router_id, edge_id, router_name)
task.wait(task_const.TaskState.RESULT)
def update_dhcp_edge_bindings(self, context, network_id):
"""Reconfigure the DHCP to the edge."""
resource_id = (vcns_const.DHCP_EDGE_PREFIX + network_id)[:36]
@ -1672,6 +1687,16 @@ def delete_lrouter(nsxv_manager, context, router_id, dist=False):
LOG.warning(_LW("router binding for router: %s not found"), router_id)
def remove_irrelevant_keys_from_edge_request(edge_request):
"""Remove some unnecessary keys from the edge request.
Having these keys fail the update edge NSX transaction
"""
for key in ['status', 'datacenterMoid', 'fqdn', 'version',
'type', 'tenant', 'datacenterName',
'hypervisorAssist', 'universal', 'enableFips']:
edge_request.pop(key, None)
def _retrieve_nsx_switch_id(context, network_id):
"""Helper method to retrieve backend switch ID."""
bindings = nsxv_db.get_network_bindings(context.session, network_id)
@ -2215,6 +2240,9 @@ class NsxVCallbacks(object):
except sa_exc.NoResultFound:
LOG.warning(_LW("Router Binding for %s not found"), router_id)
def edge_rename_result(self, task):
LOG.debug("edge_rename_result %d", task.status)
def interface_update_result(self, task):
LOG.debug("interface_update_result %d", task.status)

View File

@ -26,6 +26,7 @@ from vmware_nsx.common import nsxv_constants
from vmware_nsx.db import nsxv_db
from vmware_nsx.db import nsxv_models
from vmware_nsx.plugins.nsx_v.vshield.common import constants as vcns_const
from vmware_nsx.plugins.nsx_v.vshield import edge_utils
from vmware_nsx.shell.admin.plugins.common import constants
from vmware_nsx.shell.admin.plugins.common import formatters
import vmware_nsx.shell.admin.plugins.common.utils as admin_utils
@ -202,11 +203,8 @@ def nsx_fix_name_mismatch(resource, event, trigger, **kwargs):
LOG.info(_LI("Edge rename aborted by user"))
return
LOG.info(_LI("Edge rename started"))
# having these keys fail the NSX transaction
for key in ['status', 'datacenterMoid', 'fqdn', 'version',
'type', 'tenant', 'datacenterName',
'hypervisorAssist', 'universal', 'enableFips']:
edge.pop(key, None)
# remove some keys that will fail the NSX transaction
edge_utils.remove_irrelevant_keys_from_edge_request(edge)
try:
LOG.error(_LE("Update edge..."))
nsxv.update_edge(edge_id, edge)

View File

@ -57,10 +57,13 @@ from vmware_nsx.extensions import routersize as router_size
from vmware_nsx.extensions import routertype as router_type
from vmware_nsx.extensions import securitygrouplogging
from vmware_nsx.extensions import vnicindex as ext_vnic_idx
from vmware_nsx.plugins.nsx_v.drivers import (
exclusive_router_driver as ex_router_driver)
from vmware_nsx.plugins.nsx_v.drivers import (
shared_router_driver as router_driver)
from vmware_nsx.plugins.nsx_v import md_proxy
from vmware_nsx.plugins.nsx_v.vshield.common import constants as vcns_const
from vmware_nsx.plugins.nsx_v.vshield import edge_appliance_driver
from vmware_nsx.plugins.nsx_v.vshield import edge_firewall_driver
from vmware_nsx.plugins.nsx_v.vshield import edge_utils
from vmware_nsx.plugins.nsx_v.vshield.tasks import (
@ -2473,6 +2476,28 @@ class TestExclusiveRouterTestCase(L3NatTest, L3NatTestCaseBase,
uuidutils.generate_uuid(),
expected_code=webob.exc.HTTPNotFound.code)
def test_router_rename(self):
with self.router(name='old_name') as r:
with mock.patch.object(edge_appliance_driver.EdgeApplianceDriver,
'rename_edge') as edge_rename:
new_name = 'new_name'
router_id = r['router']['id']
# get the edge of this router
plugin = manager.NeutronManager.get_plugin()
router_obj = ex_router_driver.RouterExclusiveDriver(plugin)
ctx = context.get_admin_context()
edge_id = router_obj._get_edge_id_or_raise(ctx, router_id)
# update the name
body = self._update('routers', router_id,
{'router': {'name': new_name}})
self.assertEqual(new_name, body['router']['name'])
edge_rename.assert_called_once_with(
router_id,
edge_id,
new_name + '-' + router_id)
def _test_router_update_gateway_on_l3_ext_net(self, vlan_id=None,
validate_ext_gw=False,
distributed=False):