[Admin-utils] NSXv recreate DHCP edge
This utility can be used to move all the networks from a specific DHCP edge, to another (new or existing) edge. This should work also for VDR router DHCP edge. Usage: nsxadmin -r dhcp-binding -o nsx-recreate --property edge-id=<edge-Id> Output example: ==== [NSX] Recreate Dhcp Edge ==== ReCreating NSXv Edge: edge-222 Deleting the old DHCP edge: edge-222 Moving network a7fd0856-923e-43a6-97c7-9980e7fabd08 to a new edge Moving subnet ae9efc04-a685-497e-aab1-1dff9abacf9c to a new edge Creating network a7fd0856-923e-43a6-97c7-9980e7fabd08 DHCP address group Network a7fd0856-923e-43a6-97c7-9980e7fabd08 was moved to edge edge-228 Moving network 7a484242-0261-4888-ba77-41bb7bbd4f9d to a new edge Moving subnet 412e89ce-7c69-494d-b525-c08c8828cdfd to a new edge Moving subnet 139f7375-afb9-41dd-bdb7-c25af772a805 to a new edge Creating network 7a484242-0261-4888-ba77-41bb7bbd4f9d DHCP address group Network 7a484242-0261-4888-ba77-41bb7bbd4f9d was moved to edge edge-228 Change-Id: I97ba4abfe50d634f5ba5b137a64e021575db1ead
This commit is contained in:
parent
7881b819e3
commit
37660fce9c
doc/source
vmware_nsx
db
plugins/nsx_v
shell
@ -79,6 +79,9 @@ DHCP Bindings
|
|||||||
|
|
||||||
nsxadmin -r dhcp-binding -o nsx-update --property edge-id=edge-15
|
nsxadmin -r dhcp-binding -o nsx-update --property edge-id=edge-15
|
||||||
|
|
||||||
|
- Recreate DHCP edge by moving all the networks to other edges::
|
||||||
|
|
||||||
|
nsxadmin -r dhcp-binding -o nsx-recreate --property edge-id=edge-222
|
||||||
|
|
||||||
Networks
|
Networks
|
||||||
~~~~~~~~
|
~~~~~~~~
|
||||||
|
@ -596,6 +596,16 @@ def get_vdr_dhcp_binding_by_vdr(session, vdr_router_id):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def get_vdr_dhcp_binding_by_edge(session, edge_id):
|
||||||
|
try:
|
||||||
|
binding = session.query(
|
||||||
|
nsxv_models.NsxvVdrDhcpBinding).filter_by(
|
||||||
|
dhcp_edge_id=edge_id).one()
|
||||||
|
return binding
|
||||||
|
except exc.NoResultFound:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def delete_vdr_dhcp_binding(session, vdr_router_id):
|
def delete_vdr_dhcp_binding(session, vdr_router_id):
|
||||||
return (session.query(nsxv_models.NsxvVdrDhcpBinding).
|
return (session.query(nsxv_models.NsxvVdrDhcpBinding).
|
||||||
filter_by(vdr_router_id=vdr_router_id).delete())
|
filter_by(vdr_router_id=vdr_router_id).delete())
|
||||||
|
@ -1923,6 +1923,19 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
|
|||||||
if binding:
|
if binding:
|
||||||
return binding['edge_id']
|
return binding['edge_id']
|
||||||
|
|
||||||
|
def _update_dhcp_service_new_edge(self, context, resource_id):
|
||||||
|
edge_id = self._get_edge_id_by_rtr_id(context, resource_id)
|
||||||
|
if edge_id:
|
||||||
|
with locking.LockManager.get_lock(str(edge_id)):
|
||||||
|
if self.metadata_proxy_handler:
|
||||||
|
LOG.debug('Update metadata for resource %s',
|
||||||
|
resource_id)
|
||||||
|
self.metadata_proxy_handler.configure_router_edge(
|
||||||
|
resource_id, context)
|
||||||
|
|
||||||
|
self.setup_dhcp_edge_fw_rules(context, self,
|
||||||
|
resource_id)
|
||||||
|
|
||||||
def _update_dhcp_service_with_subnet(self, context, subnet):
|
def _update_dhcp_service_with_subnet(self, context, subnet):
|
||||||
network_id = subnet['network_id']
|
network_id = subnet['network_id']
|
||||||
# Create DHCP port
|
# Create DHCP port
|
||||||
@ -1947,17 +1960,7 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
|
|||||||
context, network_id, address_groups=address_groups)
|
context, network_id, address_groups=address_groups)
|
||||||
|
|
||||||
if resource_id:
|
if resource_id:
|
||||||
edge_id = self._get_edge_id_by_rtr_id(context, resource_id)
|
self._update_dhcp_service_new_edge(context, resource_id)
|
||||||
if edge_id:
|
|
||||||
with locking.LockManager.get_lock(str(edge_id)):
|
|
||||||
if self.metadata_proxy_handler:
|
|
||||||
LOG.debug('Update metadata for resource %s',
|
|
||||||
resource_id)
|
|
||||||
self.metadata_proxy_handler.configure_router_edge(
|
|
||||||
resource_id, context)
|
|
||||||
|
|
||||||
self.setup_dhcp_edge_fw_rules(context, self,
|
|
||||||
resource_id)
|
|
||||||
|
|
||||||
except Exception:
|
except Exception:
|
||||||
with excutils.save_and_reraise_exception():
|
with excutils.save_and_reraise_exception():
|
||||||
|
@ -16,15 +16,22 @@
|
|||||||
import logging
|
import logging
|
||||||
import pprint
|
import pprint
|
||||||
|
|
||||||
|
from oslo_config import cfg
|
||||||
|
|
||||||
from vmware_nsx.shell.admin.plugins.common import constants
|
from vmware_nsx.shell.admin.plugins.common import constants
|
||||||
import vmware_nsx.shell.admin.plugins.common.utils as admin_utils
|
import vmware_nsx.shell.admin.plugins.common.utils as admin_utils
|
||||||
import vmware_nsx.shell.admin.plugins.nsxv.resources.utils as utils
|
import vmware_nsx.shell.admin.plugins.nsxv.resources.utils as utils
|
||||||
import vmware_nsx.shell.resources as shell
|
import vmware_nsx.shell.resources as shell
|
||||||
|
|
||||||
from neutron.callbacks import registry
|
from neutron.callbacks import registry
|
||||||
|
from neutron import context as n_context
|
||||||
|
from neutron.db import l3_db
|
||||||
|
|
||||||
from vmware_nsx._i18n import _LE, _LI
|
from vmware_nsx._i18n import _LE, _LI, _LW
|
||||||
|
from vmware_nsx.common import locking
|
||||||
from vmware_nsx.db import nsxv_db
|
from vmware_nsx.db import nsxv_db
|
||||||
|
from vmware_nsx.plugins.nsx_v.vshield.common import (
|
||||||
|
constants as nsxv_constants)
|
||||||
from vmware_nsx.plugins.nsx_v.vshield.common import exceptions
|
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 import edge_utils
|
||||||
from vmware_nsx.plugins.nsx_v.vshield import vcns_driver
|
from vmware_nsx.plugins.nsx_v.vshield import vcns_driver
|
||||||
@ -116,9 +123,180 @@ def nsx_update_dhcp_edge_binding(resource, event, trigger, **kwargs):
|
|||||||
LOG.error(_LE("Edge %s not found"), edge_id)
|
LOG.error(_LE("Edge %s not found"), edge_id)
|
||||||
|
|
||||||
|
|
||||||
|
def delete_old_dhcp_edge(context, old_edge_id, bindings):
|
||||||
|
LOG.info(_LI("Deleting the old DHCP edge: %s"), old_edge_id)
|
||||||
|
# using one of the router-ids in the bindings for the deleting
|
||||||
|
dhcp_names = [binding['router_id'] for binding in bindings]
|
||||||
|
dhcp_name = dhcp_names[0]
|
||||||
|
with locking.LockManager.get_lock(old_edge_id):
|
||||||
|
# Delete from NSXv backend
|
||||||
|
# (using the first dhcp name as the "router name")
|
||||||
|
# Note - If we will not delete the router, but free it - it will be
|
||||||
|
# immediately used as the new one, So it is better to delete it.
|
||||||
|
try:
|
||||||
|
nsxv.delete_edge(old_edge_id)
|
||||||
|
except Exception as e:
|
||||||
|
LOG.warning(_LW("Failed to delete the old edge %(id)s: %(e)s"),
|
||||||
|
{'id': old_edge_id, 'e': e})
|
||||||
|
# Continue the process anyway
|
||||||
|
# The edge may have been already deleted at the backend
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Remove bindings from Neutron DB
|
||||||
|
nsxv_db.delete_nsxv_router_binding(context.session, dhcp_name)
|
||||||
|
nsxv_db.clean_edge_vnic_binding(context.session, old_edge_id)
|
||||||
|
except Exception as e:
|
||||||
|
LOG.warning(_LW("Failed to delete the old edge %(id)s from the "
|
||||||
|
"DB : %(e)s"), {'id': old_edge_id, 'e': e})
|
||||||
|
|
||||||
|
|
||||||
|
def recreate_vdr_dhcp_edge(context, plugin, edge_manager,
|
||||||
|
old_edge_id, vdr_router_id):
|
||||||
|
"""Handle the edge recreation of a VDR router DHCP.
|
||||||
|
"""
|
||||||
|
# delete the old bindings
|
||||||
|
nsxv_db.delete_vdr_dhcp_binding(context.session, vdr_router_id)
|
||||||
|
|
||||||
|
# Add each interface port of this router to a new edge:
|
||||||
|
intf_ports = plugin._get_port_by_device_id(
|
||||||
|
context, vdr_router_id, l3_db.DEVICE_OWNER_ROUTER_INTF)
|
||||||
|
for port in intf_ports:
|
||||||
|
fixed_ips = port.get("fixed_ips", [])
|
||||||
|
if len(fixed_ips) > 0:
|
||||||
|
fixed_ip = fixed_ips[0]
|
||||||
|
subnet_id = fixed_ip['subnet_id']
|
||||||
|
subnet = plugin.get_subnet(context, subnet_id)
|
||||||
|
do_metadata = False
|
||||||
|
for fixed_ip in fixed_ips:
|
||||||
|
if fixed_ip['ip_address'] == subnet['gateway_ip']:
|
||||||
|
do_metadata = True
|
||||||
|
|
||||||
|
if do_metadata:
|
||||||
|
edge_manager.configure_dhcp_for_vdr_network(
|
||||||
|
context, subnet['network_id'], vdr_router_id)
|
||||||
|
|
||||||
|
new_binding = nsxv_db.get_vdr_dhcp_binding_by_vdr(
|
||||||
|
context.session, vdr_router_id)
|
||||||
|
if new_binding:
|
||||||
|
LOG.info(_LI("VDR router %(vdr_id)s was moved to edge %(edge_id)s"),
|
||||||
|
{'vdr_id': vdr_router_id,
|
||||||
|
'edge_id': new_binding['dhcp_edge_id']})
|
||||||
|
else:
|
||||||
|
LOG.error(_LI("VDR router %(vdr_id)s was not moved to a new edge"),
|
||||||
|
{'vdr_id': vdr_router_id})
|
||||||
|
|
||||||
|
|
||||||
|
def recreate_network_dhcp(context, plugin, edge_manager, old_edge_id, net_id):
|
||||||
|
"""Handle the DHCP edge recreation of a network
|
||||||
|
"""
|
||||||
|
LOG.info(_LI("Moving network %s to a new edge"), net_id)
|
||||||
|
# delete the old binding
|
||||||
|
resource_id = (nsxv_constants.DHCP_EDGE_PREFIX + net_id)[:36]
|
||||||
|
nsxv_db.delete_nsxv_router_binding(context.session, resource_id)
|
||||||
|
|
||||||
|
# Delete the old static binding of the networks` compute ports
|
||||||
|
port_filters = {'network_id': [net_id],
|
||||||
|
'device_owner': ['compute:None']}
|
||||||
|
compute_ports = plugin.get_ports(context, filters=port_filters)
|
||||||
|
for port in compute_ports:
|
||||||
|
# Delete old binding from the DB
|
||||||
|
nsxv_db.delete_edge_dhcp_static_binding(context.session,
|
||||||
|
old_edge_id, port['mac_address'])
|
||||||
|
|
||||||
|
# Go over all the subnets with DHCP
|
||||||
|
net_filters = {'network_id': [net_id], 'enable_dhcp': [True]}
|
||||||
|
subnets = plugin.get_subnets(context, filters=net_filters)
|
||||||
|
for subnet in subnets:
|
||||||
|
LOG.info(_LI("Moving subnet %s to a new edge"), subnet['id'])
|
||||||
|
# allocate / reuse the new dhcp edge
|
||||||
|
new_resource_id = edge_manager.create_dhcp_edge_service(
|
||||||
|
context, net_id, subnet)
|
||||||
|
if new_resource_id:
|
||||||
|
# also add fw rules and metadata, once for the new edge
|
||||||
|
plugin._update_dhcp_service_new_edge(context, resource_id)
|
||||||
|
|
||||||
|
# Update the ip of the dhcp port
|
||||||
|
LOG.info(_LI("Creating network %s DHCP address group"), net_id)
|
||||||
|
address_groups = plugin._create_network_dhcp_address_group(
|
||||||
|
context, net_id)
|
||||||
|
plugin._update_dhcp_edge_service(context, net_id, address_groups)
|
||||||
|
|
||||||
|
# find out the id of the new edge:
|
||||||
|
new_binding = nsxv_db.get_nsxv_router_binding(
|
||||||
|
context.session, resource_id)
|
||||||
|
if new_binding:
|
||||||
|
LOG.info(_LI("Network %(net_id)s was moved to edge %(edge_id)s"),
|
||||||
|
{'net_id': net_id, 'edge_id': new_binding['edge_id']})
|
||||||
|
else:
|
||||||
|
LOG.error(_LI("Network %(net_id)s was not moved to a new edge"),
|
||||||
|
{'net_id': net_id})
|
||||||
|
|
||||||
|
|
||||||
|
@admin_utils.output_header
|
||||||
|
def nsx_recreate_dhcp_edge(resource, event, trigger, **kwargs):
|
||||||
|
"""Recreate a dhcp edge with all the networks n a new NSXv edge"""
|
||||||
|
if not kwargs.get('property'):
|
||||||
|
LOG.error(_LE("Need to specify edge-id parameter"))
|
||||||
|
return
|
||||||
|
|
||||||
|
# input validation
|
||||||
|
properties = admin_utils.parse_multi_keyval_opt(kwargs['property'])
|
||||||
|
old_edge_id = properties.get('edge-id')
|
||||||
|
if not old_edge_id:
|
||||||
|
LOG.error(_LE("Need to specify edge-id parameter"))
|
||||||
|
return
|
||||||
|
LOG.info(_LI("ReCreating NSXv Edge: %s"), old_edge_id)
|
||||||
|
|
||||||
|
# init the plugin and edge manager
|
||||||
|
cfg.CONF.set_override('core_plugin',
|
||||||
|
'vmware_nsx.shell.admin.plugins.nsxv.resources'
|
||||||
|
'.utils.NsxVPluginWrapper')
|
||||||
|
plugin = utils.NsxVPluginWrapper()
|
||||||
|
nsxv_manager = vcns_driver.VcnsDriver(edge_utils.NsxVCallbacks(plugin))
|
||||||
|
edge_manager = edge_utils.EdgeManager(nsxv_manager, plugin)
|
||||||
|
context = n_context.get_admin_context()
|
||||||
|
|
||||||
|
# verify that this is a DHCP edge
|
||||||
|
bindings = nsxv_db.get_nsxv_router_bindings_by_edge(
|
||||||
|
context.session, old_edge_id)
|
||||||
|
if (not bindings or
|
||||||
|
not bindings[0]['router_id'].startswith(
|
||||||
|
nsxv_constants.DHCP_EDGE_PREFIX)):
|
||||||
|
LOG.error(_LE("Edge %(edge_id)s is not a DHCP edge"),
|
||||||
|
{'edge_id': old_edge_id})
|
||||||
|
return
|
||||||
|
|
||||||
|
# find the networks bound to this DHCP edge
|
||||||
|
networks_binding = nsxv_db.get_edge_vnic_bindings_by_edge(
|
||||||
|
context.session, old_edge_id)
|
||||||
|
network_ids = [binding['network_id'] for binding in networks_binding]
|
||||||
|
|
||||||
|
# Find out the vdr router, if this is a vdr DHCP edge
|
||||||
|
vdr_binding = nsxv_db.get_vdr_dhcp_binding_by_edge(
|
||||||
|
context.session, old_edge_id)
|
||||||
|
vdr_router_id = vdr_binding['vdr_router_id'] if vdr_binding else None
|
||||||
|
|
||||||
|
# Delete the old edge
|
||||||
|
delete_old_dhcp_edge(context, old_edge_id, bindings)
|
||||||
|
|
||||||
|
if vdr_router_id:
|
||||||
|
# recreate the edge as a VDR DHCP edge
|
||||||
|
recreate_vdr_dhcp_edge(context, plugin, edge_manager,
|
||||||
|
old_edge_id, vdr_router_id)
|
||||||
|
else:
|
||||||
|
# This is a regular DHCP edge:
|
||||||
|
# Move all the networks to other (new or existing) edge
|
||||||
|
for net_id in network_ids:
|
||||||
|
recreate_network_dhcp(context, plugin, edge_manager,
|
||||||
|
old_edge_id, net_id)
|
||||||
|
|
||||||
|
|
||||||
registry.subscribe(list_missing_dhcp_bindings,
|
registry.subscribe(list_missing_dhcp_bindings,
|
||||||
constants.DHCP_BINDING,
|
constants.DHCP_BINDING,
|
||||||
shell.Operations.LIST.value)
|
shell.Operations.LIST.value)
|
||||||
registry.subscribe(nsx_update_dhcp_edge_binding,
|
registry.subscribe(nsx_update_dhcp_edge_binding,
|
||||||
constants.DHCP_BINDING,
|
constants.DHCP_BINDING,
|
||||||
shell.Operations.NSX_UPDATE.value)
|
shell.Operations.NSX_UPDATE.value)
|
||||||
|
registry.subscribe(nsx_recreate_dhcp_edge,
|
||||||
|
constants.DHCP_BINDING,
|
||||||
|
shell.Operations.NSX_RECREATE.value)
|
||||||
|
@ -43,3 +43,8 @@ class NsxVPluginWrapper(plugin.NsxVPlugin):
|
|||||||
|
|
||||||
def _validate_config(self):
|
def _validate_config(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def _extend_get_network_dict_provider(self, context, net):
|
||||||
|
self._extend_network_dict_provider(context, net)
|
||||||
|
# skip getting the Qos policy ID because get_object calls
|
||||||
|
# plugin init again on admin-util environment
|
||||||
|
@ -44,6 +44,7 @@ class Operations(enum.Enum):
|
|||||||
NSX_CLEAN = 'nsx-clean'
|
NSX_CLEAN = 'nsx-clean'
|
||||||
NSX_UPDATE = 'nsx-update'
|
NSX_UPDATE = 'nsx-update'
|
||||||
NSX_UPDATE_SECRET = 'nsx-update-secret'
|
NSX_UPDATE_SECRET = 'nsx-update-secret'
|
||||||
|
NSX_RECREATE = 'nsx-recreate'
|
||||||
MIGRATE_TO_DYNAMIC_CRITERIA = 'migrate-to-dynamic-criteria'
|
MIGRATE_TO_DYNAMIC_CRITERIA = 'migrate-to-dynamic-criteria'
|
||||||
|
|
||||||
|
|
||||||
@ -100,7 +101,8 @@ nsxv_resources = {
|
|||||||
Operations.CLEAN.value]),
|
Operations.CLEAN.value]),
|
||||||
constants.DHCP_BINDING: Resource(constants.DHCP_BINDING,
|
constants.DHCP_BINDING: Resource(constants.DHCP_BINDING,
|
||||||
[Operations.LIST.value,
|
[Operations.LIST.value,
|
||||||
Operations.NSX_UPDATE.value]),
|
Operations.NSX_UPDATE.value,
|
||||||
|
Operations.NSX_RECREATE.value]),
|
||||||
constants.NETWORKS: Resource(constants.NETWORKS,
|
constants.NETWORKS: Resource(constants.NETWORKS,
|
||||||
[Operations.LIST.value,
|
[Operations.LIST.value,
|
||||||
Operations.NSX_UPDATE.value]),
|
Operations.NSX_UPDATE.value]),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user