You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
231 lines
9.2 KiB
231 lines
9.2 KiB
# Copyright 2020 VMware, Inc. All rights reserved. |
|
# |
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may |
|
# not use this file except in compliance with the License. You may obtain |
|
# a copy of the License at |
|
# |
|
# http://www.apache.org/licenses/LICENSE-2.0 |
|
# |
|
# Unless required by applicable law or agreed to in writing, software |
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
|
# License for the specific language governing permissions and limitations |
|
# under the License. |
|
|
|
import copy |
|
import sys |
|
|
|
import netaddr |
|
|
|
from neutron_lib.callbacks import registry |
|
from oslo_log import log as logging |
|
from oslo_serialization import jsonutils |
|
|
|
from vmware_nsx.shell.admin.plugins.common import constants |
|
from vmware_nsx.shell.admin.plugins.common import utils as admin_utils |
|
from vmware_nsx.shell.admin.plugins.nsxp.resources import utils as p_utils |
|
from vmware_nsx.shell.admin.plugins.nsxv3.resources import migration |
|
from vmware_nsx.shell import resources as shell |
|
from vmware_nsxlib.v3.policy import constants as policy_constants |
|
|
|
LOG = logging.getLogger(__name__) |
|
|
|
|
|
@admin_utils.output_header |
|
def cleanup_db_mappings(resource, event, trigger, **kwargs): |
|
"""Delete all entries from nsx-t mapping tables in DB""" |
|
return migration.MP2Policy_cleanup_db_mappings( |
|
resource, event, trigger, **kwargs) |
|
|
|
|
|
@admin_utils.output_header |
|
def post_v2t_migration_cleanups(resource, event, trigger, **kwargs): |
|
"""Cleanup unneeded migrated resources after v2t migration is done""" |
|
nsxpolicy = p_utils.get_connected_nsxpolicy() |
|
# Clean all migrated DFW sections |
|
sections = nsxpolicy.comm_map.list(policy_constants.DEFAULT_DOMAIN) |
|
for section in sections: |
|
# Look for the tag marking the migrated sections |
|
for tag in section.get('tags', []): |
|
if tag['scope'] == 'v_origin': |
|
LOG.info("Deleting migrated: %s", tag['tag']) |
|
nsxpolicy.comm_map.delete(policy_constants.DEFAULT_DOMAIN, |
|
section['id']) |
|
continue |
|
|
|
# Cleanup migrated DVS ports (belong to the edges that are not in use) |
|
segments = nsxpolicy.segment.list() |
|
for seg in segments: |
|
# Skip non-neutron segments |
|
if not p_utils.is_neutron_resource(seg): |
|
continue |
|
ports = nsxpolicy.segment_port.list(seg['id']) |
|
# Find the non-neutron ports and delete them |
|
for port in ports: |
|
if not p_utils.is_neutron_resource(port): |
|
nsxpolicy.segment_port.delete(seg['id'], port['id']) |
|
LOG.error("Deleted migrated non-neutron port %s", port['id']) |
|
|
|
|
|
@admin_utils.output_header |
|
def migration_tier0_redistribute(resource, event, trigger, **kwargs): |
|
"""Disable/Restore tier0s route redistribution during V2T migration""" |
|
errmsg = ("Need to specify --property action=disable/restore and a comma " |
|
"separated tier0 list as --property tier0s") |
|
if not kwargs.get('property'): |
|
LOG.error("%s", errmsg) |
|
return |
|
properties = admin_utils.parse_multi_keyval_opt(kwargs['property']) |
|
action = properties.get('action') |
|
tier0string = properties.get('tier0s') |
|
state_filename = properties.get('state-file') |
|
if not tier0string or not action or not state_filename: |
|
LOG.error("%s", errmsg) |
|
return |
|
|
|
tier0s = tier0string.split(",") |
|
nsxpolicy = p_utils.get_connected_nsxpolicy() |
|
|
|
if action.lower() == 'disable': |
|
try: |
|
f = open(state_filename, "r") |
|
orig_conf_map = jsonutils.loads(f.read()) |
|
f.close() |
|
except Exception: |
|
LOG.info("State file %s not found:", state_filename) |
|
orig_conf_map = {} |
|
for tier0 in tier0s: |
|
# get the current config |
|
try: |
|
orig_conf = nsxpolicy.tier0.get_route_redistribution_config( |
|
tier0) |
|
except Exception: |
|
LOG.error("Did not find Tier0 %s", tier0) |
|
continue |
|
if not orig_conf: |
|
LOG.info("Tier0 %s does not have route redistribution config", |
|
tier0) |
|
continue |
|
fixed_conf = copy.deepcopy(orig_conf) |
|
if (not (orig_conf['bgp_enabled'] or |
|
orig_conf['ospf_enabled'] or |
|
orig_conf.get('redistribution_rules'))): |
|
# Already disabled |
|
LOG.info("Tier0 %s route redistribution config was not " |
|
"changed because it is disabled", tier0) |
|
continue |
|
# Check if any of the rules have tier1 flags enabled |
|
rule_num = 0 |
|
for rule in orig_conf.get('redistribution_rules', []): |
|
fixed_types = [] |
|
for route_type in rule['route_redistribution_types']: |
|
if not route_type.startswith('TIER1'): |
|
fixed_types.append(route_type) |
|
fixed_conf['redistribution_rules'][rule_num][ |
|
'route_redistribution_types'] = fixed_types |
|
rule_num = rule_num + 1 |
|
# Save the original config so it can be reverted later |
|
orig_conf_map[tier0] = orig_conf |
|
fixed_conf['bgp_enabled'] = False |
|
fixed_conf['ospf_enabled'] = False |
|
nsxpolicy.tier0.update_route_redistribution_config( |
|
tier0, fixed_conf) |
|
LOG.info("Disabled Tier0 %s route redistribution config for " |
|
"Tier1 routes", tier0) |
|
f = open(state_filename, "w") |
|
f.write("%s" % jsonutils.dumps(orig_conf_map)) |
|
f.close() |
|
elif action.lower() == 'restore': |
|
try: |
|
f = open(state_filename, "r") |
|
orig_conf_map = jsonutils.loads(f.read()) |
|
f.close() |
|
except Exception: |
|
LOG.warning("State file %s not found:", state_filename) |
|
sys.exit(1) |
|
for tier0 in tier0s: |
|
if tier0 in orig_conf_map: |
|
# Restore its original config: |
|
try: |
|
nsxpolicy.tier0.update_route_redistribution_config( |
|
tier0, orig_conf_map[tier0]) |
|
LOG.info("Restored Tier0 %s original route redistribution " |
|
"config", tier0) |
|
except Exception: |
|
LOG.error("Failed to update redistribution of Tier0 %s", |
|
tier0) |
|
else: |
|
LOG.info("Tier0 %s route redistribution config was not " |
|
"changed", tier0) |
|
else: |
|
LOG.error("%s", errmsg) |
|
sys.exit(1) |
|
|
|
|
|
def _cidrs_overlap(cidr0, cidr1): |
|
return cidr0.first <= cidr1.last and cidr1.first <= cidr0.last |
|
|
|
|
|
@admin_utils.output_header |
|
def migration_validate_external_cidrs(resource, event, trigger, **kwargs): |
|
"""Before V2T migration, validate that the external subnets cidrs |
|
do not overlap the tier0 uplinks |
|
""" |
|
errmsg = ("Need to specify --property ext-net=<path> --property " |
|
"ext-cidr=<path>") |
|
if not kwargs.get('property'): |
|
LOG.error("%s", errmsg) |
|
return |
|
|
|
properties = admin_utils.parse_multi_keyval_opt(kwargs['property']) |
|
ext_net_file = properties.get('ext-net') |
|
ext_cidr_file = properties.get('ext-cidr') |
|
if not ext_net_file or not ext_cidr_file: |
|
LOG.error("%s", errmsg) |
|
return |
|
|
|
with open(ext_net_file, 'r') as myfile: |
|
# maps external network neutron id to tier0 |
|
data = myfile.read() |
|
external_networks = jsonutils.loads(data) |
|
with open(ext_cidr_file, 'r') as myfile: |
|
# maps external network neutron id to its cidr |
|
data = myfile.read() |
|
external_cidrs = jsonutils.loads(data) |
|
|
|
nsxpolicy = p_utils.get_connected_nsxpolicy() |
|
|
|
for net_id in external_cidrs: |
|
net_cidr = netaddr.IPNetwork(external_cidrs[net_id]).cidr |
|
tier0 = external_networks.get(net_id) |
|
if not tier0: |
|
LOG.error("Could not find network %s in %s. Please ensure " |
|
"external networks are correctly listed in " |
|
"migrator configuration ", net_id, ext_net_file) |
|
sys.exit(1) |
|
else: |
|
tier0_cidrs = nsxpolicy.tier0.get_uplink_cidrs(tier0) |
|
for cidr in tier0_cidrs: |
|
tier0_subnet = netaddr.IPNetwork(cidr).cidr |
|
if _cidrs_overlap(tier0_subnet, net_cidr): |
|
LOG.error("External subnet of network %s cannot overlap " |
|
"with T0 %s uplink cidr %s", net_id, tier0, cidr) |
|
sys.exit(1) |
|
sys.exit(0) |
|
|
|
|
|
registry.subscribe(cleanup_db_mappings, |
|
constants.NSX_MIGRATE_T_P, |
|
shell.Operations.CLEAN_ALL.value) |
|
|
|
registry.subscribe(post_v2t_migration_cleanups, |
|
constants.NSX_MIGRATE_V_T, |
|
shell.Operations.CLEAN_ALL.value) |
|
|
|
registry.subscribe(migration_tier0_redistribute, |
|
constants.NSX_MIGRATE_V_T, |
|
shell.Operations.NSX_REDISTRIBUTE.value) |
|
|
|
registry.subscribe(migration_validate_external_cidrs, |
|
constants.NSX_MIGRATE_V_T, |
|
shell.Operations.VALIDATE.value)
|
|
|