api_replay for migration into the policy plugin
- Add api reply support in the policy plugin - Move some api_replay common code to the common_v3 plugin - Add support for avaiablity zones in the api_replay Change-Id: Idb376e2d8c0b24f2fea5f051af2191f77831803c
This commit is contained in:
parent
5216a35ffd
commit
905310e2fc
@ -35,6 +35,7 @@ class ApiReplayCli(object):
|
||||
dest_os_user_domain_id=args.dest_os_user_domain_id,
|
||||
dest_os_password=args.dest_os_password,
|
||||
dest_os_auth_url=args.dest_os_auth_url,
|
||||
dest_plugin=args.dest_plugin,
|
||||
use_old_keystone=args.use_old_keystone,
|
||||
logfile=args.logfile)
|
||||
|
||||
@ -101,7 +102,11 @@ class ApiReplayCli(object):
|
||||
parser.add_argument(
|
||||
"--dest-os-auth-url",
|
||||
required=True,
|
||||
help="They keystone api endpoint for this user.")
|
||||
help="The keystone api endpoint for this user.")
|
||||
parser.add_argument(
|
||||
"--dest-plugin",
|
||||
default='nsx-p',
|
||||
help="The core plugin of the destination nsx-t/nsx-p.")
|
||||
|
||||
parser.add_argument(
|
||||
"--use-old-keystone",
|
||||
|
@ -38,7 +38,7 @@ class ApiReplayClient(utils.PrepareObjectForMigration):
|
||||
source_os_password, source_os_auth_url,
|
||||
dest_os_username, dest_os_user_domain_id,
|
||||
dest_os_tenant_name, dest_os_tenant_domain_id,
|
||||
dest_os_password, dest_os_auth_url,
|
||||
dest_os_password, dest_os_auth_url, dest_plugin,
|
||||
use_old_keystone, logfile):
|
||||
|
||||
if logfile:
|
||||
@ -80,8 +80,9 @@ class ApiReplayClient(utils.PrepareObjectForMigration):
|
||||
tenant_domain_id=dest_os_tenant_domain_id,
|
||||
password=dest_os_password,
|
||||
auth_url=dest_os_auth_url)
|
||||
self.dest_plugin = dest_plugin
|
||||
|
||||
LOG.info("Starting NSX migration.")
|
||||
LOG.info("Starting NSX migration to %s.", self.dest_plugin)
|
||||
# Migrate all the objects
|
||||
self.migrate_security_groups()
|
||||
self.migrate_qos_policies()
|
||||
@ -269,6 +270,11 @@ class ApiReplayClient(utils.PrepareObjectForMigration):
|
||||
# is raised here but that's okay.
|
||||
pass
|
||||
|
||||
def get_dest_availablity_zones(self, resource):
|
||||
azs = self.dest_neutron.list_availability_zones()['availability_zones']
|
||||
az_names = [az['name'] for az in azs if az['resource'] == resource]
|
||||
return az_names
|
||||
|
||||
def migrate_routers(self):
|
||||
"""Migrates routers from source to dest neutron.
|
||||
|
||||
@ -284,6 +290,7 @@ class ApiReplayClient(utils.PrepareObjectForMigration):
|
||||
source_routers = []
|
||||
|
||||
dest_routers = self.dest_neutron.list_routers()['routers']
|
||||
dest_azs = self.get_dest_availablity_zones('router')
|
||||
update_routes = {}
|
||||
gw_info = {}
|
||||
|
||||
@ -304,7 +311,7 @@ class ApiReplayClient(utils.PrepareObjectForMigration):
|
||||
|
||||
dest_router = self.have_id(router['id'], dest_routers)
|
||||
if dest_router is False:
|
||||
body = self.prepare_router(router)
|
||||
body = self.prepare_router(router, dest_azs=dest_azs)
|
||||
try:
|
||||
new_router = (self.dest_neutron.create_router(
|
||||
{'router': body}))
|
||||
@ -390,6 +397,7 @@ class ApiReplayClient(utils.PrepareObjectForMigration):
|
||||
dest_default_public_net = True
|
||||
|
||||
subnetpools_map = self.migrate_subnetpools()
|
||||
dest_azs = self.get_dest_availablity_zones('network')
|
||||
|
||||
total_num = len(source_networks)
|
||||
LOG.info("Migrating %(nets)s networks, %(subnets)s subnets and "
|
||||
@ -400,7 +408,8 @@ class ApiReplayClient(utils.PrepareObjectForMigration):
|
||||
external_net = network.get('router:external')
|
||||
body = self.prepare_network(
|
||||
network, remove_qos=remove_qos,
|
||||
dest_default_public_net=dest_default_public_net)
|
||||
dest_default_public_net=dest_default_public_net,
|
||||
dest_azs=dest_azs)
|
||||
|
||||
# only create network if the dest server doesn't have it
|
||||
if self.have_id(network['id'], dest_networks):
|
||||
@ -450,7 +459,7 @@ class ApiReplayClient(utils.PrepareObjectForMigration):
|
||||
body['enable_dhcp'] = False
|
||||
if count_dhcp_subnet > 1:
|
||||
# Do not allow dhcp on the subnet if there is already
|
||||
# another subnet with DHCP as the v3 plugin supports
|
||||
# another subnet with DHCP as the v3 plugins supports
|
||||
# only one
|
||||
LOG.warning("Disabling DHCP for subnet on net %s: "
|
||||
"The plugin doesn't support multiple "
|
||||
@ -561,7 +570,7 @@ class ApiReplayClient(utils.PrepareObjectForMigration):
|
||||
# script multiple times as we don't track this.
|
||||
# Note(asarfaty): also if the same network in
|
||||
# source is attached to 2 routers, which the v3
|
||||
# plugin does not support.
|
||||
# plugins does not support.
|
||||
LOG.error("Failed to add router interface port"
|
||||
"(%(port)s): %(e)s",
|
||||
{'port': port, 'e': e})
|
||||
|
@ -46,10 +46,10 @@ def _fixup_res_dict(context, attr_name, res_dict, check_allow_post=True):
|
||||
|
||||
|
||||
class PrepareObjectForMigration(object):
|
||||
"""Helper class to modify V objects before creating them in T"""
|
||||
"""Helper class to modify source objects before creating them in dest"""
|
||||
# Remove some fields before creating the new object.
|
||||
# Some fields are not supported for a new object, and some are not
|
||||
# supported by the nsx-v3 plugin
|
||||
# supported by the destination plugin
|
||||
basic_ignore_fields = ['updated_at',
|
||||
'created_at',
|
||||
'tags',
|
||||
@ -64,7 +64,6 @@ class PrepareObjectForMigration(object):
|
||||
'ha',
|
||||
'external_gateway_info',
|
||||
'router_type',
|
||||
'availability_zone_hints',
|
||||
'availability_zones',
|
||||
'distributed',
|
||||
'flavor_id']
|
||||
@ -89,7 +88,6 @@ class PrepareObjectForMigration(object):
|
||||
'status',
|
||||
'subnets',
|
||||
'availability_zones',
|
||||
'availability_zone_hints',
|
||||
'ipv4_address_scope',
|
||||
'ipv6_address_scope',
|
||||
'mtu']
|
||||
@ -124,10 +122,18 @@ class PrepareObjectForMigration(object):
|
||||
self.fix_description(sg)
|
||||
return self.drop_fields(sg, self.drop_sg_fields)
|
||||
|
||||
def prepare_router(self, rtr, direct_call=False):
|
||||
def prepare_router(self, rtr, dest_azs=None, direct_call=False):
|
||||
self.fix_description(rtr)
|
||||
body = self.drop_fields(rtr, self.drop_router_fields)
|
||||
if direct_call:
|
||||
if dest_azs:
|
||||
if body.get('availability_zone_hints'):
|
||||
az = body['availability_zone_hints'][0]
|
||||
if az not in dest_azs:
|
||||
if az != 'default':
|
||||
LOG.warning("Ignoring AZ %s in router %s as it is not "
|
||||
"defined in destination", az, rtr['id'])
|
||||
body['availability_zone_hints'] = []
|
||||
elif direct_call:
|
||||
body['availability_zone_hints'] = []
|
||||
return body
|
||||
|
||||
@ -136,7 +142,7 @@ class PrepareObjectForMigration(object):
|
||||
return self.drop_fields(pool, self.drop_subnetpool_fields)
|
||||
|
||||
def prepare_network(self, net, dest_default_public_net=True,
|
||||
remove_qos=False, direct_call=False):
|
||||
remove_qos=False, dest_azs=None, direct_call=False):
|
||||
self.fix_description(net)
|
||||
body = self.drop_fields(net, self.drop_network_fields)
|
||||
|
||||
@ -151,13 +157,13 @@ class PrepareObjectForMigration(object):
|
||||
del body[field]
|
||||
|
||||
# vxlan network with segmentation id should be translated to a regular
|
||||
# network in nsx-v3.
|
||||
# network in nsx-v3/P.
|
||||
if (body.get('provider:network_type') == 'vxlan' and
|
||||
body.get('provider:segmentation_id') is not None):
|
||||
del body['provider:network_type']
|
||||
del body['provider:segmentation_id']
|
||||
|
||||
# flat network should be translated to a regular network in nsx-v3.
|
||||
# flat network should be translated to a regular network in nsx-v3/P.
|
||||
if (body.get('provider:network_type') == 'flat'):
|
||||
del body['provider:network_type']
|
||||
if 'provider:physical_network' in body:
|
||||
@ -179,7 +185,15 @@ class PrepareObjectForMigration(object):
|
||||
body['is_default'] = False
|
||||
LOG.warning("Public network %s was set to non default network",
|
||||
body['id'])
|
||||
if direct_call:
|
||||
if dest_azs:
|
||||
if body.get('availability_zone_hints'):
|
||||
az = body['availability_zone_hints'][0]
|
||||
if az not in dest_azs:
|
||||
if az != 'default':
|
||||
LOG.warning("Ignoring AZ %s in net %s as it is not "
|
||||
"defined in destination", az, body['id'])
|
||||
body['availability_zone_hints'] = []
|
||||
elif direct_call:
|
||||
body['availability_zone_hints'] = []
|
||||
return body
|
||||
|
||||
|
@ -246,7 +246,7 @@ nsx_common_opts = [
|
||||
help=_("If true, the server then allows the caller to "
|
||||
"specify the id of resources. This should only "
|
||||
"be enabled in order to allow one to migrate an "
|
||||
"existing install of neutron to the NSX-T plugin.")),
|
||||
"existing install of neutron to a new VMWare plugin.")),
|
||||
cfg.ListOpt('nsx_extension_drivers',
|
||||
default=[],
|
||||
help=_("An ordered list of extension driver "
|
||||
|
@ -13,7 +13,8 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
|
||||
import decorator
|
||||
import mock
|
||||
import netaddr
|
||||
from oslo_config import cfg
|
||||
from oslo_db import exception as db_exc
|
||||
@ -38,6 +39,7 @@ from neutron.db import extraroute_db
|
||||
from neutron.db import l3_attrs_db
|
||||
from neutron.db import l3_db
|
||||
from neutron.db import l3_gwmode_db
|
||||
from neutron.db.models import securitygroup as securitygroup_model
|
||||
from neutron.db import models_v2
|
||||
from neutron.db import portbindings_db
|
||||
from neutron.db import portsecurity_db
|
||||
@ -70,6 +72,7 @@ from neutron_lib.services.qos import constants as qos_consts
|
||||
from neutron_lib.utils import helpers
|
||||
from neutron_lib.utils import net as nl_net_utils
|
||||
|
||||
from vmware_nsx.api_replay import utils as api_replay_utils
|
||||
from vmware_nsx.common import availability_zones as nsx_com_az
|
||||
from vmware_nsx.common import exceptions as nsx_exc
|
||||
from vmware_nsx.common import locking
|
||||
@ -95,6 +98,17 @@ from vmware_nsxlib.v3 import utils as nsxlib_utils
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@decorator.decorator
|
||||
def api_replay_mode_wrapper(f, *args, **kwargs):
|
||||
if cfg.CONF.api_replay_mode:
|
||||
# NOTE(arosen): the mock.patch here is needed for api_replay_mode
|
||||
with mock.patch("neutron_lib.plugins.utils._fixup_res_dict",
|
||||
side_effect=api_replay_utils._fixup_res_dict):
|
||||
return f(*args, **kwargs)
|
||||
else:
|
||||
return f(*args, **kwargs)
|
||||
|
||||
|
||||
# NOTE(asarfaty): the order of inheritance here is important. in order for the
|
||||
# QoS notification to work, the AgentScheduler init must be called first
|
||||
# NOTE(arosen): same is true with the ExtendedSecurityGroupPropertiesMixin
|
||||
@ -2761,6 +2775,38 @@ class NsxPluginV3Base(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
||||
|
||||
return restricted_vlans
|
||||
|
||||
@api_replay_mode_wrapper
|
||||
def _create_floating_ip_wrapper(self, context, floatingip):
|
||||
initial_status = (constants.FLOATINGIP_STATUS_ACTIVE
|
||||
if floatingip['floatingip']['port_id']
|
||||
else constants.FLOATINGIP_STATUS_DOWN)
|
||||
return super(NsxPluginV3Base, self).create_floatingip(
|
||||
context, floatingip, initial_status=initial_status)
|
||||
|
||||
def _ensure_default_security_group(self, context, tenant_id):
|
||||
# NOTE(arosen): if in replay mode we'll create all the default
|
||||
# security groups for the user with their data so we don't
|
||||
# want this to be called.
|
||||
if not cfg.CONF.api_replay_mode:
|
||||
return super(NsxPluginV3Base, self)._ensure_default_security_group(
|
||||
context, tenant_id)
|
||||
|
||||
def _handle_api_replay_default_sg(self, context, secgroup_db):
|
||||
"""Set default api-replay migrated SG as default manually"""
|
||||
if (secgroup_db['name'] == 'default'):
|
||||
# this is a default security group copied from another cloud
|
||||
# Ugly patch! mark it as default manually
|
||||
with context.session.begin(subtransactions=True):
|
||||
try:
|
||||
default_entry = securitygroup_model.DefaultSecurityGroup(
|
||||
security_group_id=secgroup_db['id'],
|
||||
project_id=secgroup_db['project_id'])
|
||||
context.session.add(default_entry)
|
||||
except Exception as e:
|
||||
LOG.error("Failed to mark migrated security group %(id)s "
|
||||
"as default %(e)s",
|
||||
{'id': secgroup_db['id'], 'e': e})
|
||||
|
||||
|
||||
class TagsCallbacks(object):
|
||||
|
||||
|
@ -68,6 +68,7 @@ from vmware_nsx.common import locking
|
||||
from vmware_nsx.common import managers
|
||||
from vmware_nsx.common import utils
|
||||
from vmware_nsx.db import db as nsx_db
|
||||
from vmware_nsx.extensions import api_replay
|
||||
from vmware_nsx.extensions import maclearning as mac_ext
|
||||
from vmware_nsx.extensions import projectpluginmap
|
||||
from vmware_nsx.extensions import providersecuritygroup as provider_sg
|
||||
@ -214,6 +215,10 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base):
|
||||
if cfg.CONF.vlan_transparent:
|
||||
self.supported_extension_aliases.append(vlan_apidef.ALIAS)
|
||||
|
||||
# Support api-reply for migration environments to the policy plugin
|
||||
if cfg.CONF.api_replay_mode:
|
||||
self.supported_extension_aliases.append(api_replay.ALIAS)
|
||||
|
||||
nsxlib_utils.set_inject_headers_callback(v3_utils.inject_headers)
|
||||
self._validate_nsx_policy_version()
|
||||
self._validate_config()
|
||||
@ -1787,6 +1792,7 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base):
|
||||
router_id,
|
||||
static_route_id=self._get_static_route_id(route))
|
||||
|
||||
@nsx_plugin_common.api_replay_mode_wrapper
|
||||
def update_router(self, context, router_id, router):
|
||||
gw_info = self._extract_external_gw(context, router, is_extract=False)
|
||||
router_data = router['router']
|
||||
@ -1857,6 +1863,7 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base):
|
||||
cidr_prefix = int(subnet['cidr'].split('/')[1])
|
||||
return "%s/%s" % (subnet['gateway_ip'], cidr_prefix)
|
||||
|
||||
@nsx_plugin_common.api_replay_mode_wrapper
|
||||
def add_router_interface(self, context, router_id, interface_info):
|
||||
network_id = self._get_interface_network(context, interface_info)
|
||||
extern_net = self._network_is_external(context, network_id)
|
||||
@ -2131,10 +2138,7 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base):
|
||||
self._assert_on_assoc_floatingip_to_special_ports(
|
||||
fip_data, port_data)
|
||||
|
||||
new_fip = super(NsxPolicyPlugin, self).create_floatingip(
|
||||
context, floatingip, initial_status=(
|
||||
const.FLOATINGIP_STATUS_ACTIVE
|
||||
if port_id else const.FLOATINGIP_STATUS_DOWN))
|
||||
new_fip = self._create_floating_ip_wrapper(context, floatingip)
|
||||
router_id = new_fip['router_id']
|
||||
if not router_id:
|
||||
return new_fip
|
||||
@ -2639,6 +2643,9 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base):
|
||||
secgroup,
|
||||
default_sg)
|
||||
|
||||
if cfg.CONF.api_replay_mode:
|
||||
self._handle_api_replay_default_sg(context, secgroup_db)
|
||||
|
||||
try:
|
||||
# Create Group & communication map on the NSX
|
||||
self._create_security_group_backend_resources(
|
||||
|
@ -69,7 +69,6 @@ from oslo_utils import importutils
|
||||
from oslo_utils import uuidutils
|
||||
|
||||
from vmware_nsx._i18n import _
|
||||
from vmware_nsx.api_replay import utils as api_replay_utils
|
||||
from vmware_nsx.common import config # noqa
|
||||
from vmware_nsx.common import exceptions as nsx_exc
|
||||
from vmware_nsx.common import l3_rpc_agent_api
|
||||
@ -2383,17 +2382,7 @@ class NsxV3Plugin(nsx_plugin_common.NsxPluginV3Base,
|
||||
|
||||
return ret_val
|
||||
|
||||
def _update_router_wrapper(self, context, router_id, router):
|
||||
if cfg.CONF.api_replay_mode:
|
||||
# NOTE(arosen): the mock.patch here is needed for api_replay_mode
|
||||
with mock.patch("neutron_lib.plugins.utils._fixup_res_dict",
|
||||
side_effect=api_replay_utils._fixup_res_dict):
|
||||
return super(NsxV3Plugin, self).update_router(
|
||||
context, router_id, router)
|
||||
else:
|
||||
return super(NsxV3Plugin, self).update_router(
|
||||
context, router_id, router)
|
||||
|
||||
@nsx_plugin_common.api_replay_mode_wrapper
|
||||
def update_router(self, context, router_id, router):
|
||||
gw_info = self._extract_external_gw(context, router, is_extract=False)
|
||||
router_data = router['router']
|
||||
@ -2473,7 +2462,8 @@ class NsxV3Plugin(nsx_plugin_common.NsxPluginV3Base,
|
||||
nsx_router_id,
|
||||
description=router_data['description'])
|
||||
|
||||
return self._update_router_wrapper(context, router_id, router)
|
||||
return super(NsxV3Plugin, self).update_router(
|
||||
context, router_id, router)
|
||||
except nsx_lib_exc.ResourceNotFound:
|
||||
with db_api.CONTEXT_WRITER.using(context):
|
||||
router_db = self._get_router(context, router_id)
|
||||
@ -2670,18 +2660,7 @@ class NsxV3Plugin(nsx_plugin_common.NsxPluginV3Base,
|
||||
|
||||
return (ports, address_groups)
|
||||
|
||||
def _add_router_interface_wrapper(self, context, router_id,
|
||||
interface_info):
|
||||
if cfg.CONF.api_replay_mode:
|
||||
# NOTE(arosen): the mock.patch here is needed for api_replay_mode
|
||||
with mock.patch("neutron_lib.plugins.utils._fixup_res_dict",
|
||||
side_effect=api_replay_utils._fixup_res_dict):
|
||||
return super(NsxV3Plugin, self).add_router_interface(
|
||||
context, router_id, interface_info)
|
||||
else:
|
||||
return super(NsxV3Plugin, self).add_router_interface(
|
||||
context, router_id, interface_info)
|
||||
|
||||
@nsx_plugin_common.api_replay_mode_wrapper
|
||||
def add_router_interface(self, context, router_id, interface_info):
|
||||
network_id = self._get_interface_network(context, interface_info)
|
||||
extern_net = self._network_is_external(context, network_id)
|
||||
@ -2717,8 +2696,8 @@ class NsxV3Plugin(nsx_plugin_common.NsxPluginV3Base,
|
||||
[network_id])
|
||||
|
||||
# Update the interface of the neutron router
|
||||
info = self._add_router_interface_wrapper(context, router_id,
|
||||
interface_info)
|
||||
info = super(NsxV3Plugin, self).add_router_interface(
|
||||
context, router_id, interface_info)
|
||||
try:
|
||||
subnet = self.get_subnet(context, info['subnet_ids'][0])
|
||||
port = self.get_port(context, info['port_id'])
|
||||
@ -2919,23 +2898,6 @@ class NsxV3Plugin(nsx_plugin_common.NsxPluginV3Base,
|
||||
vs_client.update_virtual_server_with_vip(vs['id'],
|
||||
vip_address)
|
||||
|
||||
def _create_floating_ip_wrapper(self, context, floatingip):
|
||||
if cfg.CONF.api_replay_mode:
|
||||
# NOTE(arosen): the mock.patch here is needed for api_replay_mode
|
||||
with mock.patch("neutron_lib.plugins.utils._fixup_res_dict",
|
||||
side_effect=api_replay_utils._fixup_res_dict):
|
||||
return super(NsxV3Plugin, self).create_floatingip(
|
||||
context, floatingip, initial_status=(
|
||||
const.FLOATINGIP_STATUS_ACTIVE
|
||||
if floatingip['floatingip']['port_id']
|
||||
else const.FLOATINGIP_STATUS_DOWN))
|
||||
else:
|
||||
return super(NsxV3Plugin, self).create_floatingip(
|
||||
context, floatingip, initial_status=(
|
||||
const.FLOATINGIP_STATUS_ACTIVE
|
||||
if floatingip['floatingip']['port_id']
|
||||
else const.FLOATINGIP_STATUS_DOWN))
|
||||
|
||||
def create_floatingip(self, context, floatingip):
|
||||
# First do some validations
|
||||
fip_data = floatingip['floatingip']
|
||||
@ -3122,14 +3084,6 @@ class NsxV3Plugin(nsx_plugin_common.NsxPluginV3Base,
|
||||
super(NsxV3Plugin, self).disassociate_floatingips(
|
||||
context, port_id, do_notify=False)
|
||||
|
||||
def _ensure_default_security_group(self, context, tenant_id):
|
||||
# NOTE(arosen): if in replay mode we'll create all the default
|
||||
# security groups for the user with their data so we don't
|
||||
# want this to be called.
|
||||
if (cfg.CONF.api_replay_mode is False):
|
||||
return super(NsxV3Plugin, self)._ensure_default_security_group(
|
||||
context, tenant_id)
|
||||
|
||||
def _create_fw_section_for_secgroup(self, nsgroup, is_provider):
|
||||
# NOTE(arosen): if a security group is provider we want to
|
||||
# insert our rules at the top.
|
||||
@ -3190,22 +3144,6 @@ class NsxV3Plugin(nsx_plugin_common.NsxPluginV3Base,
|
||||
logging_enabled, action, _sg_rules,
|
||||
ruleid_2_remote_nsgroup_map)
|
||||
|
||||
def _handle_api_replay_default_sg(self, context, secgroup_db):
|
||||
"""Set default api-replay migrated SG as default manually"""
|
||||
if (secgroup_db['name'] == 'default'):
|
||||
# this is a default security group copied from another cloud
|
||||
# Ugly patch! mark it as default manually
|
||||
with context.session.begin(subtransactions=True):
|
||||
try:
|
||||
default_entry = securitygroup_model.DefaultSecurityGroup(
|
||||
security_group_id=secgroup_db['id'],
|
||||
project_id=secgroup_db['project_id'])
|
||||
context.session.add(default_entry)
|
||||
except Exception as e:
|
||||
LOG.error("Failed to mark migrated security group %(id)s "
|
||||
"as default %(e)s",
|
||||
{'id': secgroup_db['id'], 'e': e})
|
||||
|
||||
def create_security_group(self, context, security_group, default_sg=False):
|
||||
secgroup = security_group['security_group']
|
||||
secgroup['id'] = secgroup.get('id') or uuidutils.generate_uuid()
|
||||
|
@ -206,6 +206,7 @@ def create_t_resources(context, objects, ext_net):
|
||||
# fix object before creation using the api replay code
|
||||
orig_id = obj['id']
|
||||
prepare_object = getattr(prepare, "prepare_%s" % resource)
|
||||
# TODO(asarfaty): Add availability zones support too
|
||||
obj_data = prepare_object(obj, direct_call=True)
|
||||
enable_dhcp = False
|
||||
# special cases for different objects before create:
|
||||
|
94
vmware_nsx/tests/unit/nsx_p/test_api_replay.py
Normal file
94
vmware_nsx/tests/unit/nsx_p/test_api_replay.py
Normal file
@ -0,0 +1,94 @@
|
||||
# Copyright (c) 2019 OpenStack Foundation.
|
||||
#
|
||||
# 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.
|
||||
|
||||
from vmware_nsx.extensions import api_replay
|
||||
from vmware_nsx.tests.unit.nsx_p import test_plugin
|
||||
|
||||
from neutron_lib.api import attributes
|
||||
from neutron_lib.plugins import directory
|
||||
from oslo_config import cfg
|
||||
|
||||
|
||||
class TestApiReplay(test_plugin.NsxPTestL3NatTest):
|
||||
|
||||
def setUp(self, plugin=None, ext_mgr=None, service_plugins=None):
|
||||
# enables api_replay_mode for these tests
|
||||
cfg.CONF.set_override('api_replay_mode', True)
|
||||
|
||||
super(TestApiReplay, self).setUp()
|
||||
|
||||
def tearDown(self):
|
||||
# disables api_replay_mode for these tests
|
||||
cfg.CONF.set_override('api_replay_mode', False)
|
||||
|
||||
# remove the extension from the plugin
|
||||
directory.get_plugin().supported_extension_aliases.remove(
|
||||
api_replay.ALIAS)
|
||||
|
||||
# Revert the attributes map back to normal
|
||||
for attr_name in ('ports', 'networks', 'security_groups',
|
||||
'security_group_rules', 'routers', 'policies'):
|
||||
attr_info = attributes.RESOURCES[attr_name]
|
||||
attr_info['id']['allow_post'] = False
|
||||
|
||||
super(TestApiReplay, self).tearDown()
|
||||
|
||||
def test_create_port_specify_id(self):
|
||||
specified_network_id = '555e762b-d7a1-4b44-b09b-2a34ada56c9f'
|
||||
specified_port_id = 'e55e762b-d7a1-4b44-b09b-2a34ada56c9f'
|
||||
network_res = self._create_network(self.fmt,
|
||||
'test-network',
|
||||
True,
|
||||
arg_list=('id',),
|
||||
id=specified_network_id)
|
||||
network = self.deserialize(self.fmt, network_res)
|
||||
self.assertEqual(specified_network_id, network['network']['id'])
|
||||
port_res = self._create_port(self.fmt,
|
||||
network['network']['id'],
|
||||
arg_list=('id',),
|
||||
id=specified_port_id)
|
||||
port = self.deserialize(self.fmt, port_res)
|
||||
self.assertEqual(specified_port_id, port['port']['id'])
|
||||
|
||||
def _create_router(self, fmt, tenant_id, name=None,
|
||||
admin_state_up=None,
|
||||
arg_list=None, **kwargs):
|
||||
data = {'router': {'tenant_id': tenant_id}}
|
||||
if name:
|
||||
data['router']['name'] = name
|
||||
if admin_state_up:
|
||||
data['router']['admin_state_up'] = admin_state_up
|
||||
for arg in (('admin_state_up', 'tenant_id') + (arg_list or ())):
|
||||
# Arg must be present and not empty
|
||||
if kwargs.get(arg):
|
||||
data['router'][arg] = kwargs[arg]
|
||||
router_req = self.new_create_request('routers', data, fmt)
|
||||
return router_req.get_response(self.ext_api)
|
||||
|
||||
def test_create_update_router(self):
|
||||
specified_router_id = '555e762b-d7a1-4b44-b09b-2a34ada56c9f'
|
||||
router_res = self._create_router(self.fmt,
|
||||
'test-tenant',
|
||||
'test-rtr',
|
||||
arg_list=('id',),
|
||||
id=specified_router_id)
|
||||
router = self.deserialize(self.fmt, router_res)
|
||||
self.assertEqual(specified_router_id, router['router']['id'])
|
||||
|
||||
# This part tests _fixup_res_dict as well
|
||||
body = self._update('routers', specified_router_id,
|
||||
{'router': {'name': 'new_name'}})
|
||||
body = self._show('routers', specified_router_id)
|
||||
self.assertEqual(body['router']['name'], 'new_name')
|
Loading…
Reference in New Issue
Block a user