NSX|P: Initial connectivity support
Not covered yet: DHCP, Switching Profiles, TZs, provider networks, GW, NAT Change-Id: I9f4163d8a233b0d3914363556ddf6ec0f375f99a
This commit is contained in:
parent
30e1395302
commit
4f6730911c
@ -482,7 +482,15 @@ nsx_v3_opts = nsx_v3_and_p + [
|
|||||||
|
|
||||||
]
|
]
|
||||||
|
|
||||||
nsx_p_opts = nsx_v3_and_p + []
|
nsx_p_opts = nsx_v3_and_p + [
|
||||||
|
cfg.StrOpt('default_tier0_router',
|
||||||
|
help=_("Name or UUID of the default tier0 router that will be "
|
||||||
|
"used for connecting to tier1 logical routers and "
|
||||||
|
"configuring external networks. If only one tier0 "
|
||||||
|
" router is present on backend, it will be assumed "
|
||||||
|
"as default unless this value is provided")),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
DEFAULT_STATUS_CHECK_INTERVAL = 2000
|
DEFAULT_STATUS_CHECK_INTERVAL = 2000
|
||||||
DEFAULT_MINIMUM_POOLED_EDGES = 1
|
DEFAULT_MINIMUM_POOLED_EDGES = 1
|
||||||
|
@ -24,6 +24,7 @@ from neutron.db import l3_attrs_db
|
|||||||
from neutron.db import l3_db
|
from neutron.db import l3_db
|
||||||
from neutron.db import models_v2
|
from neutron.db import models_v2
|
||||||
from neutron_lib.api.definitions import address_scope as ext_address_scope
|
from neutron_lib.api.definitions import address_scope as ext_address_scope
|
||||||
|
from neutron_lib.api.definitions import allowedaddresspairs as addr_apidef
|
||||||
from neutron_lib.api.definitions import availability_zone as az_def
|
from neutron_lib.api.definitions import availability_zone as az_def
|
||||||
from neutron_lib.api.definitions import external_net as extnet_apidef
|
from neutron_lib.api.definitions import external_net as extnet_apidef
|
||||||
from neutron_lib.api.definitions import network as net_def
|
from neutron_lib.api.definitions import network as net_def
|
||||||
@ -38,12 +39,14 @@ from neutron_lib.callbacks import resources
|
|||||||
from neutron_lib import constants
|
from neutron_lib import constants
|
||||||
from neutron_lib import context as n_context
|
from neutron_lib import context as n_context
|
||||||
from neutron_lib import exceptions as n_exc
|
from neutron_lib import exceptions as n_exc
|
||||||
|
from neutron_lib.exceptions import allowedaddresspairs as addr_exc
|
||||||
from neutron_lib.plugins import directory
|
from neutron_lib.plugins import directory
|
||||||
from neutron_lib.services.qos import constants as qos_consts
|
from neutron_lib.services.qos import constants as qos_consts
|
||||||
from neutron_lib.utils import net
|
from neutron_lib.utils import net
|
||||||
|
|
||||||
from vmware_nsx._i18n import _
|
from vmware_nsx._i18n import _
|
||||||
from vmware_nsx.common import exceptions as nsx_exc
|
from vmware_nsx.common import exceptions as nsx_exc
|
||||||
|
from vmware_nsx.common import utils
|
||||||
from vmware_nsx.extensions import maclearning as mac_ext
|
from vmware_nsx.extensions import maclearning as mac_ext
|
||||||
from vmware_nsx.extensions import secgroup_rule_local_ip_prefix as sg_prefix
|
from vmware_nsx.extensions import secgroup_rule_local_ip_prefix as sg_prefix
|
||||||
from vmware_nsx.services.qos.common import utils as qos_com_utils
|
from vmware_nsx.services.qos.common import utils as qos_com_utils
|
||||||
@ -567,6 +570,24 @@ class NsxPluginBase(db_base_plugin_v2.NeutronDbPluginV2,
|
|||||||
self._assert_on_vpn_port_change(original_port)
|
self._assert_on_vpn_port_change(original_port)
|
||||||
self._assert_on_lb_port_fixed_ip_change(port_data, orig_dev_owner)
|
self._assert_on_lb_port_fixed_ip_change(port_data, orig_dev_owner)
|
||||||
|
|
||||||
|
def _build_port_name(self, context, port_data):
|
||||||
|
device_owner = port_data.get('device_owner')
|
||||||
|
device_id = port_data.get('device_id')
|
||||||
|
if device_owner == l3_db.DEVICE_OWNER_ROUTER_INTF and device_id:
|
||||||
|
router = self._get_router(context, device_id)
|
||||||
|
name = utils.get_name_and_uuid(
|
||||||
|
router['name'] or 'router', port_data['id'], tag='port')
|
||||||
|
elif device_owner == constants.DEVICE_OWNER_DHCP:
|
||||||
|
network = self.get_network(context, port_data['network_id'])
|
||||||
|
name = self._get_dhcp_port_name(network['name'],
|
||||||
|
network['id'])
|
||||||
|
elif device_owner.startswith(constants.DEVICE_OWNER_COMPUTE_PREFIX):
|
||||||
|
name = utils.get_name_and_uuid(
|
||||||
|
port_data['name'] or 'instance-port', port_data['id'])
|
||||||
|
else:
|
||||||
|
name = port_data['name']
|
||||||
|
return name
|
||||||
|
|
||||||
def _process_extra_attr_router_create(self, context, router_db, r):
|
def _process_extra_attr_router_create(self, context, router_db, r):
|
||||||
for extra_attr in l3_attrs_db.get_attr_info().keys():
|
for extra_attr in l3_attrs_db.get_attr_info().keys():
|
||||||
if (extra_attr in r and
|
if (extra_attr in r and
|
||||||
@ -595,6 +616,38 @@ class NsxPluginBase(db_base_plugin_v2.NeutronDbPluginV2,
|
|||||||
sg_rule[sg_prefix.LOCAL_IP_PREFIX].startswith('0.0.0.0/')):
|
sg_rule[sg_prefix.LOCAL_IP_PREFIX].startswith('0.0.0.0/')):
|
||||||
sg_rule[sg_prefix.LOCAL_IP_PREFIX] = None
|
sg_rule[sg_prefix.LOCAL_IP_PREFIX] = None
|
||||||
|
|
||||||
|
def _validate_interface_address_scope(self, context,
|
||||||
|
router_db, interface_info):
|
||||||
|
gw_network_id = (router_db.gw_port.network_id if router_db.gw_port
|
||||||
|
else None)
|
||||||
|
|
||||||
|
subnet = self.get_subnet(context, interface_info['subnet_ids'][0])
|
||||||
|
if not router_db.enable_snat and gw_network_id:
|
||||||
|
self._validate_address_scope_for_router_interface(
|
||||||
|
context.elevated(), router_db.id, gw_network_id, subnet['id'])
|
||||||
|
|
||||||
|
def _validate_ipv4_address_pairs(self, address_pairs):
|
||||||
|
for pair in address_pairs:
|
||||||
|
ip = pair.get('ip_address')
|
||||||
|
if not utils.is_ipv4_ip_address(ip):
|
||||||
|
raise nsx_exc.InvalidIPAddress(ip_address=ip)
|
||||||
|
|
||||||
|
# NSXv3 and Policy only
|
||||||
|
def _create_port_address_pairs(self, context, port_data):
|
||||||
|
(port_security, has_ip) = self._determine_port_security_and_has_ip(
|
||||||
|
context, port_data)
|
||||||
|
|
||||||
|
address_pairs = port_data.get(addr_apidef.ADDRESS_PAIRS)
|
||||||
|
if validators.is_attr_set(address_pairs):
|
||||||
|
if not port_security:
|
||||||
|
raise addr_exc.AddressPairAndPortSecurityRequired()
|
||||||
|
else:
|
||||||
|
self._validate_ipv4_address_pairs(address_pairs)
|
||||||
|
self._process_create_allowed_address_pairs(context, port_data,
|
||||||
|
address_pairs)
|
||||||
|
else:
|
||||||
|
port_data[addr_apidef.ADDRESS_PAIRS] = []
|
||||||
|
|
||||||
def get_housekeeper(self, context, name, fields=None):
|
def get_housekeeper(self, context, name, fields=None):
|
||||||
# run the job in readonly mode and get the results
|
# run the job in readonly mode and get the results
|
||||||
self.housekeeper.run(context, name, readonly=True)
|
self.housekeeper.run(context, name, readonly=True)
|
||||||
|
@ -15,6 +15,8 @@
|
|||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
import netaddr
|
||||||
|
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_log import log
|
from oslo_log import log
|
||||||
from oslo_utils import excutils
|
from oslo_utils import excutils
|
||||||
@ -30,6 +32,7 @@ from neutron.db import external_net_db
|
|||||||
from neutron.db import extradhcpopt_db
|
from neutron.db import extradhcpopt_db
|
||||||
from neutron.db import extraroute_db
|
from neutron.db import extraroute_db
|
||||||
from neutron.db import l3_attrs_db
|
from neutron.db import l3_attrs_db
|
||||||
|
from neutron.db import l3_db
|
||||||
from neutron.db import l3_gwmode_db
|
from neutron.db import l3_gwmode_db
|
||||||
from neutron.db.models import l3 as l3_db_models
|
from neutron.db.models import l3 as l3_db_models
|
||||||
from neutron.db.models import securitygroup as securitygroup_model # noqa
|
from neutron.db.models import securitygroup as securitygroup_model # noqa
|
||||||
@ -40,6 +43,7 @@ from neutron.db import securitygroups_db
|
|||||||
from neutron.db import vlantransparent_db
|
from neutron.db import vlantransparent_db
|
||||||
from neutron.extensions import providernet
|
from neutron.extensions import providernet
|
||||||
from neutron.quota import resource_registry
|
from neutron.quota import resource_registry
|
||||||
|
from neutron_lib.api.definitions import allowedaddresspairs as addr_apidef
|
||||||
from neutron_lib.api.definitions import external_net
|
from neutron_lib.api.definitions import external_net
|
||||||
from neutron_lib.api.definitions import l3 as l3_apidef
|
from neutron_lib.api.definitions import l3 as l3_apidef
|
||||||
from neutron_lib.api.definitions import port_security as psec
|
from neutron_lib.api.definitions import port_security as psec
|
||||||
@ -161,6 +165,7 @@ class NsxPolicyPlugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
|||||||
|
|
||||||
self.cfg_group = 'nsx_p' # group name for nsx_p section in nsx.ini
|
self.cfg_group = 'nsx_p' # group name for nsx_p section in nsx.ini
|
||||||
|
|
||||||
|
self._init_default_config()
|
||||||
self._prepare_default_rules()
|
self._prepare_default_rules()
|
||||||
|
|
||||||
# subscribe the init complete method last, so it will be called only
|
# subscribe the init complete method last, so it will be called only
|
||||||
@ -169,6 +174,38 @@ class NsxPolicyPlugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
|||||||
resources.PROCESS,
|
resources.PROCESS,
|
||||||
events.AFTER_INIT)
|
events.AFTER_INIT)
|
||||||
|
|
||||||
|
# NOTE(annak): we may need to generalize this for API calls
|
||||||
|
# requiring path ids
|
||||||
|
def _init_default_resource(self, resource_api, name_or_id):
|
||||||
|
if not name_or_id:
|
||||||
|
# If not specified, the system will auto-configure
|
||||||
|
# in case only single resource is present
|
||||||
|
resources = resource_api.list()
|
||||||
|
if len(resources) == 1:
|
||||||
|
return resources[0]['id']
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
try:
|
||||||
|
resource_api.get(name_or_id)
|
||||||
|
return name_or_id
|
||||||
|
except nsx_lib_exc.ResourceNotFound:
|
||||||
|
try:
|
||||||
|
resource = resource_api.get_by_name(name_or_id)
|
||||||
|
if resource:
|
||||||
|
return resource['id']
|
||||||
|
except nsx_lib_exc.ResourceNotFound:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _init_default_config(self):
|
||||||
|
self.default_tier0_router = self._init_default_resource(
|
||||||
|
self.nsxpolicy.tier0,
|
||||||
|
cfg.CONF.nsx_p.default_tier0_router)
|
||||||
|
|
||||||
|
if not self.default_tier0_router:
|
||||||
|
raise cfg.RequiredOptError("default_tier0_router",
|
||||||
|
group=cfg.OptGroup('nsx_p'))
|
||||||
|
|
||||||
def _validate_nsx_policy_version(self):
|
def _validate_nsx_policy_version(self):
|
||||||
self._nsx_version = self.nsxpolicy.get_version()
|
self._nsx_version = self.nsxpolicy.get_version()
|
||||||
LOG.info("NSX Version: %s", self._nsx_version)
|
LOG.info("NSX Version: %s", self._nsx_version)
|
||||||
@ -219,8 +256,25 @@ class NsxPolicyPlugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
|||||||
})
|
})
|
||||||
|
|
||||||
def _create_network_at_the_backend(self, context, net_data):
|
def _create_network_at_the_backend(self, context, net_data):
|
||||||
#TODO(asarfaty): implement, using nsx-id the same as the neutron id
|
# TODO(annak): provider network
|
||||||
pass
|
net_data['id'] = net_data.get('id') or uuidutils.generate_uuid()
|
||||||
|
|
||||||
|
net_name = utils.get_name_and_uuid(net_data['name'] or 'network',
|
||||||
|
net_data['id'])
|
||||||
|
tags = self.nsxpolicy.build_v3_tags_payload(
|
||||||
|
net_data, resource_type='os-neutron-net-id',
|
||||||
|
project_name=context.tenant_name)
|
||||||
|
|
||||||
|
# TODO(annak): admin state config is missing on policy
|
||||||
|
# should we not create networks that are down?
|
||||||
|
# alternative - configure status on manager for time being
|
||||||
|
# admin_state = net_data.get('admin_state_up', True)
|
||||||
|
|
||||||
|
self.nsxpolicy.segment.create_or_overwrite(
|
||||||
|
net_name,
|
||||||
|
segment_id=net_data['id'],
|
||||||
|
description=net_data.get('description'),
|
||||||
|
tags=tags)
|
||||||
|
|
||||||
def _validate_external_net_create(self, net_data):
|
def _validate_external_net_create(self, net_data):
|
||||||
#TODO(asarfaty): implement
|
#TODO(asarfaty): implement
|
||||||
@ -255,7 +309,7 @@ class NsxPolicyPlugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
|||||||
# Create the backend NSX network
|
# Create the backend NSX network
|
||||||
if not is_external_net:
|
if not is_external_net:
|
||||||
try:
|
try:
|
||||||
self._create_network_at_the_backend(context, net_data)
|
self._create_network_at_the_backend(context, created_net)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
LOG.exception("Failed to create NSX network network: %s", e)
|
LOG.exception("Failed to create NSX network network: %s", e)
|
||||||
with excutils.save_and_reraise_exception():
|
with excutils.save_and_reraise_exception():
|
||||||
@ -272,11 +326,10 @@ class NsxPolicyPlugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
|||||||
def delete_network(self, context, network_id):
|
def delete_network(self, context, network_id):
|
||||||
with db_api.context_manager.writer.using(context):
|
with db_api.context_manager.writer.using(context):
|
||||||
self._process_l3_delete(context, network_id)
|
self._process_l3_delete(context, network_id)
|
||||||
return super(NsxPolicyPlugin, self).delete_network(
|
super(NsxPolicyPlugin, self).delete_network(
|
||||||
context, network_id)
|
context, network_id)
|
||||||
if not self._network_is_external(context, network_id):
|
if not self._network_is_external(context, network_id):
|
||||||
# TODO(asarfaty) delete the NSX logical network
|
self.nsxpolicy.segment.delete(network_id)
|
||||||
pass
|
|
||||||
|
|
||||||
def update_network(self, context, id, network):
|
def update_network(self, context, id, network):
|
||||||
original_net = super(NsxPolicyPlugin, self).get_network(context, id)
|
original_net = super(NsxPolicyPlugin, self).get_network(context, id)
|
||||||
@ -352,13 +405,51 @@ class NsxPolicyPlugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
|||||||
|
|
||||||
return updated_subnet
|
return updated_subnet
|
||||||
|
|
||||||
|
def _build_address_bindings(self, port):
|
||||||
|
address_bindings = []
|
||||||
|
for fixed_ip in port['fixed_ips']:
|
||||||
|
if netaddr.IPNetwork(fixed_ip['ip_address']).version != 4:
|
||||||
|
#TODO(annak): enable when IPv6 is supported
|
||||||
|
continue
|
||||||
|
binding = self.nsxpolicy.segment_port.build_address_binding(
|
||||||
|
fixed_ip['ip_address'], port['mac_address'])
|
||||||
|
address_bindings.append(binding)
|
||||||
|
|
||||||
|
for pair in port.get(addr_apidef.ADDRESS_PAIRS):
|
||||||
|
binding = self.nsxpolicy.segment_port.build_address_binding(
|
||||||
|
pair['ip_address'], pair['mac_address'])
|
||||||
|
address_bindings.append(binding)
|
||||||
|
|
||||||
|
return address_bindings
|
||||||
|
|
||||||
def _create_port_at_the_backend(self, context, port_data):
|
def _create_port_at_the_backend(self, context, port_data):
|
||||||
#TODO(asarfaty): implement
|
# TODO(annak): admin_state not supported by policy
|
||||||
pass
|
# TODO(annak): handle exclude list
|
||||||
|
# TODO(annak): switching profiles when supported
|
||||||
|
name = self._build_port_name(context, port_data)
|
||||||
|
psec, has_ip = self._determine_port_security_and_has_ip(context,
|
||||||
|
port_data)
|
||||||
|
address_bindings = (self._build_address_bindings(port_data)
|
||||||
|
if psec else None)
|
||||||
|
device_owner = port_data.get('device_owner')
|
||||||
|
vif_id = None
|
||||||
|
if device_owner and device_owner != l3_db.DEVICE_OWNER_ROUTER_INTF:
|
||||||
|
vif_id = port_data['id']
|
||||||
|
|
||||||
|
self.nsxpolicy.segment_port.create_or_overwrite(
|
||||||
|
port_data['network_id'],
|
||||||
|
port_data['id'],
|
||||||
|
name,
|
||||||
|
description=port_data.get('description'),
|
||||||
|
address_bindings=address_bindings,
|
||||||
|
vif_id=vif_id)
|
||||||
|
|
||||||
def _cleanup_port(self, context, port_id, lport_id):
|
def _cleanup_port(self, context, port_id, lport_id):
|
||||||
super(NsxPolicyPlugin, self).delete_port(context, port_id)
|
super(NsxPolicyPlugin, self).delete_port(context, port_id)
|
||||||
#TODO(asarfaty): Delete the NSX logical port
|
|
||||||
|
port_data = self.get_port(context, port_id)
|
||||||
|
self.nsxpolicy.segment_port.delete(
|
||||||
|
port_data['network_id'], port_data['id'])
|
||||||
|
|
||||||
def base_create_port(self, context, port):
|
def base_create_port(self, context, port):
|
||||||
neutron_db = super(NsxPolicyPlugin, self).create_port(context, port)
|
neutron_db = super(NsxPolicyPlugin, self).create_port(context, port)
|
||||||
@ -380,6 +471,8 @@ class NsxPolicyPlugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
|||||||
neutron_db = self.base_create_port(context, port)
|
neutron_db = self.base_create_port(context, port)
|
||||||
port["port"].update(neutron_db)
|
port["port"].update(neutron_db)
|
||||||
|
|
||||||
|
self._create_port_address_pairs(context, port_data)
|
||||||
|
|
||||||
if not is_external_net:
|
if not is_external_net:
|
||||||
try:
|
try:
|
||||||
self._create_port_at_the_backend(context, port_data)
|
self._create_port_at_the_backend(context, port_data)
|
||||||
@ -403,10 +496,15 @@ class NsxPolicyPlugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
|||||||
l3_port_check=True, l2gw_port_check=True,
|
l3_port_check=True, l2gw_port_check=True,
|
||||||
force_delete_dhcp=False,
|
force_delete_dhcp=False,
|
||||||
force_delete_vpn=False):
|
force_delete_vpn=False):
|
||||||
port = self.get_port(context, port_id)
|
port_data = self.get_port(context, port_id)
|
||||||
if not self._network_is_external(context, port['network_id']):
|
if not self._network_is_external(context, port_data['network_id']):
|
||||||
#TODO(asarfaty): Delete the NSX logical port
|
try:
|
||||||
pass
|
self.nsxpolicy.segment_port.delete(
|
||||||
|
port_data['network_id'], port_data['id'])
|
||||||
|
except Exception as ex:
|
||||||
|
LOG.error("Failed to delete port %(id)s on NSX backend "
|
||||||
|
"due to %(e)s",
|
||||||
|
{'id': port_data['id'], 'e': ex})
|
||||||
|
|
||||||
self.disassociate_floatingips(context, port_id)
|
self.disassociate_floatingips(context, port_id)
|
||||||
|
|
||||||
@ -510,7 +608,22 @@ class NsxPolicyPlugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
|||||||
context, router)
|
context, router)
|
||||||
router_db = self._get_router(context, router['id'])
|
router_db = self._get_router(context, router['id'])
|
||||||
self._process_extra_attr_router_create(context, router_db, r)
|
self._process_extra_attr_router_create(context, router_db, r)
|
||||||
#TODO(asarfaty): Create the NSX logical router and add DB mapping
|
|
||||||
|
router_name = utils.get_name_and_uuid(router['name'] or 'router',
|
||||||
|
router['id'])
|
||||||
|
#TODO(annak): handle GW
|
||||||
|
try:
|
||||||
|
self.nsxpolicy.tier1.create_or_overwrite(
|
||||||
|
router_name, router['id'],
|
||||||
|
tier0=self.default_tier0_router)
|
||||||
|
#TODO(annak): narrow down the exception
|
||||||
|
except Exception as ex:
|
||||||
|
with excutils.save_and_reraise_exception():
|
||||||
|
LOG.error('Failed to create router %(id)s '
|
||||||
|
'on NSX backend. Exception: %(e)s',
|
||||||
|
{'id': router['id'], 'e': ex})
|
||||||
|
self.delete_router(context, router['id'])
|
||||||
|
|
||||||
LOG.debug("Created router %s: %s. GW info %s",
|
LOG.debug("Created router %s: %s. GW info %s",
|
||||||
router['id'], r, gw_info)
|
router['id'], r, gw_info)
|
||||||
return self.get_router(context, router['id'])
|
return self.get_router(context, router['id'])
|
||||||
@ -519,13 +632,14 @@ class NsxPolicyPlugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
|||||||
router = self.get_router(context, router_id)
|
router = self.get_router(context, router_id)
|
||||||
if router.get(l3_apidef.EXTERNAL_GW_INFO):
|
if router.get(l3_apidef.EXTERNAL_GW_INFO):
|
||||||
self._update_router_gw_info(context, router_id, {})
|
self._update_router_gw_info(context, router_id, {})
|
||||||
nsx_router_id = nsx_db.get_nsx_router_id(
|
|
||||||
context.session, router_id)
|
|
||||||
ret_val = super(NsxPolicyPlugin, self).delete_router(
|
ret_val = super(NsxPolicyPlugin, self).delete_router(
|
||||||
context, router_id)
|
context, router_id)
|
||||||
if nsx_router_id:
|
|
||||||
#TODO(asarfaty): delete the NSX logical router
|
try:
|
||||||
pass
|
self.nsxpolicy.tier1.delete(router_id)
|
||||||
|
except Exception as ex:
|
||||||
|
LOG.error("Failed to delete NSX T1 router %(id)s: %(e)s", {
|
||||||
|
'e': ex, 'id': router_id})
|
||||||
|
|
||||||
return ret_val
|
return ret_val
|
||||||
|
|
||||||
@ -557,7 +671,23 @@ class NsxPolicyPlugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
|||||||
info = super(NsxPolicyPlugin, self).add_router_interface(
|
info = super(NsxPolicyPlugin, self).add_router_interface(
|
||||||
context, router_id, interface_info)
|
context, router_id, interface_info)
|
||||||
|
|
||||||
#TODO(asarfaty) Update the NSX logical router ports
|
self._validate_interface_address_scope(context, router_db, info)
|
||||||
|
subnet = self.get_subnet(context, info['subnet_ids'][0])
|
||||||
|
|
||||||
|
# TODO(annak): Validate TZ
|
||||||
|
try:
|
||||||
|
# This is always an overwrite call
|
||||||
|
# NOTE: Connecting network to multiple routers is not supported
|
||||||
|
self.nsxpolicy.segment.create_or_overwrite(network_id,
|
||||||
|
tier1_id=router_id)
|
||||||
|
except Exception as ex:
|
||||||
|
with excutils.save_and_reraise_exception():
|
||||||
|
LOG.error('Failed to create router interface for subnet '
|
||||||
|
'%(id)s on NSX backend. Exception: %(e)s',
|
||||||
|
{'id': subnet['id'], 'e': ex})
|
||||||
|
self.remove_router_interface(
|
||||||
|
context, router_id, interface_info)
|
||||||
|
|
||||||
return info
|
return info
|
||||||
|
|
||||||
def remove_router_interface(self, context, router_id, interface_info):
|
def remove_router_interface(self, context, router_id, interface_info):
|
||||||
|
@ -1727,7 +1727,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
|||||||
LOG.debug("Created logical DHCP server %(server)s for network "
|
LOG.debug("Created logical DHCP server %(server)s for network "
|
||||||
"%(network)s",
|
"%(network)s",
|
||||||
{'server': dhcp_server['id'], 'network': network['id']})
|
{'server': dhcp_server['id'], 'network': network['id']})
|
||||||
name = self._get_port_name(context, port_data)
|
name = self._build_port_name(context, port_data)
|
||||||
nsx_port = self.nsxlib.logical_port.create(
|
nsx_port = self.nsxlib.logical_port.create(
|
||||||
nsx_net_id, dhcp_server['id'], tags=port_tags, name=name,
|
nsx_net_id, dhcp_server['id'], tags=port_tags, name=name,
|
||||||
attachment_type=nsxlib_consts.ATTACHMENT_DHCP,
|
attachment_type=nsxlib_consts.ATTACHMENT_DHCP,
|
||||||
@ -2226,24 +2226,6 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
|||||||
net_name or 'network'),
|
net_name or 'network'),
|
||||||
net_id)
|
net_id)
|
||||||
|
|
||||||
def _get_port_name(self, context, port_data):
|
|
||||||
device_owner = port_data.get('device_owner')
|
|
||||||
device_id = port_data.get('device_id')
|
|
||||||
if device_owner == l3_db.DEVICE_OWNER_ROUTER_INTF and device_id:
|
|
||||||
router = self._get_router(context, device_id)
|
|
||||||
name = utils.get_name_and_uuid(
|
|
||||||
router['name'] or 'router', port_data['id'], tag='port')
|
|
||||||
elif device_owner == const.DEVICE_OWNER_DHCP:
|
|
||||||
network = self.get_network(context, port_data['network_id'])
|
|
||||||
name = self._get_dhcp_port_name(network['name'],
|
|
||||||
network['id'])
|
|
||||||
elif device_owner.startswith(const.DEVICE_OWNER_COMPUTE_PREFIX):
|
|
||||||
name = utils.get_name_and_uuid(
|
|
||||||
port_data['name'] or 'instance-port', port_data['id'])
|
|
||||||
else:
|
|
||||||
name = port_data['name']
|
|
||||||
return name
|
|
||||||
|
|
||||||
def _get_qos_profile_id(self, context, policy_id):
|
def _get_qos_profile_id(self, context, policy_id):
|
||||||
switch_profile_id = nsx_db.get_switch_profile_by_qos_policy(
|
switch_profile_id = nsx_db.get_switch_profile_by_qos_policy(
|
||||||
context.session, policy_id)
|
context.session, policy_id)
|
||||||
@ -2378,7 +2360,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
|||||||
profiles.append(self._mac_learning_profile)
|
profiles.append(self._mac_learning_profile)
|
||||||
profiles.append(self._no_switch_security)
|
profiles.append(self._no_switch_security)
|
||||||
|
|
||||||
name = self._get_port_name(context, port_data)
|
name = self._build_port_name(context, port_data)
|
||||||
nsx_net_id = self._get_network_nsx_id(context, port_data['network_id'])
|
nsx_net_id = self._get_network_nsx_id(context, port_data['network_id'])
|
||||||
try:
|
try:
|
||||||
result = self.nsxlib.logical_port.create(
|
result = self.nsxlib.logical_port.create(
|
||||||
@ -2412,12 +2394,6 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
|||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def _validate_address_pairs(self, address_pairs):
|
|
||||||
for pair in address_pairs:
|
|
||||||
ip = pair.get('ip_address')
|
|
||||||
if not utils.is_ipv4_ip_address(ip):
|
|
||||||
raise nsx_exc.InvalidIPAddress(ip_address=ip)
|
|
||||||
|
|
||||||
def _provider_sgs_specified(self, port_data):
|
def _provider_sgs_specified(self, port_data):
|
||||||
# checks if security groups were updated adding/modifying
|
# checks if security groups were updated adding/modifying
|
||||||
# security groups, port security is set and port has ip
|
# security groups, port security is set and port has ip
|
||||||
@ -2462,18 +2438,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
|||||||
context, port_data, neutron_db)
|
context, port_data, neutron_db)
|
||||||
|
|
||||||
# allowed address pair checks
|
# allowed address pair checks
|
||||||
address_pairs = port_data.get(addr_apidef.ADDRESS_PAIRS)
|
self._create_port_address_pairs(context, port_data)
|
||||||
if validators.is_attr_set(address_pairs):
|
|
||||||
if not port_security:
|
|
||||||
raise addr_exc.AddressPairAndPortSecurityRequired()
|
|
||||||
else:
|
|
||||||
self._validate_address_pairs(address_pairs)
|
|
||||||
self._process_create_allowed_address_pairs(
|
|
||||||
context, neutron_db,
|
|
||||||
address_pairs)
|
|
||||||
else:
|
|
||||||
# remove ATTR_NOT_SPECIFIED
|
|
||||||
port_data[addr_apidef.ADDRESS_PAIRS] = []
|
|
||||||
|
|
||||||
if port_security and has_ip:
|
if port_security and has_ip:
|
||||||
self._ensure_default_security_group_on_port(context, port)
|
self._ensure_default_security_group_on_port(context, port)
|
||||||
@ -3147,7 +3112,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
|||||||
raise addr_exc.AddressPairAndPortSecurityRequired()
|
raise addr_exc.AddressPairAndPortSecurityRequired()
|
||||||
|
|
||||||
if delete_addr_pairs or has_addr_pairs:
|
if delete_addr_pairs or has_addr_pairs:
|
||||||
self._validate_address_pairs(
|
self._validate_ipv4_address_pairs(
|
||||||
updated_port[addr_apidef.ADDRESS_PAIRS])
|
updated_port[addr_apidef.ADDRESS_PAIRS])
|
||||||
# delete address pairs and read them in
|
# delete address pairs and read them in
|
||||||
self._delete_allowed_address_pairs(context, id)
|
self._delete_allowed_address_pairs(context, id)
|
||||||
@ -3245,7 +3210,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
|||||||
attachment_type = None
|
attachment_type = None
|
||||||
vif_uuid = None
|
vif_uuid = None
|
||||||
|
|
||||||
name = self._get_port_name(context, updated_port)
|
name = self._build_port_name(context, updated_port)
|
||||||
|
|
||||||
# Update exclude list if necessary
|
# Update exclude list if necessary
|
||||||
updated_ps = updated_port.get('port_security_enabled')
|
updated_ps = updated_port.get('port_security_enabled')
|
||||||
@ -4333,9 +4298,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
|||||||
|
|
||||||
# If it is a no-snat router, interface address scope must be the
|
# If it is a no-snat router, interface address scope must be the
|
||||||
# same as the gateways
|
# same as the gateways
|
||||||
if not router_db.enable_snat and gw_network_id:
|
self._validate_interface_address_scope(context, router_db, info)
|
||||||
self._validate_address_scope_for_router_interface(
|
|
||||||
context.elevated(), router_id, gw_network_id, subnet['id'])
|
|
||||||
|
|
||||||
nsx_router_id = nsx_db.get_nsx_router_id(context.session,
|
nsx_router_id = nsx_db.get_nsx_router_id(context.session,
|
||||||
router_id)
|
router_id)
|
||||||
|
@ -37,11 +37,16 @@ class NsxPPluginTestCaseMixin(
|
|||||||
ext_mgr=ext_mgr)
|
ext_mgr=ext_mgr)
|
||||||
|
|
||||||
def _mock_nsx_policy_backend_calls(self):
|
def _mock_nsx_policy_backend_calls(self):
|
||||||
|
resource_list_result = {'results': [{'id': 'test',
|
||||||
|
'display_name': 'test'}]}
|
||||||
mock.patch(
|
mock.patch(
|
||||||
"vmware_nsxlib.v3.NsxPolicyLib.get_version",
|
"vmware_nsxlib.v3.NsxPolicyLib.get_version",
|
||||||
return_value=nsx_constants.NSX_VERSION_2_4_0).start()
|
return_value=nsx_constants.NSX_VERSION_2_4_0).start()
|
||||||
mock.patch(
|
mock.patch(
|
||||||
"vmware_nsxlib.v3.client.RESTClient.get").start()
|
"vmware_nsxlib.v3.client.RESTClient.get").start()
|
||||||
|
mock.patch(
|
||||||
|
"vmware_nsxlib.v3.client.RESTClient.list",
|
||||||
|
return_value=resource_list_result).start()
|
||||||
mock.patch(
|
mock.patch(
|
||||||
"vmware_nsxlib.v3.client.RESTClient.patch").start()
|
"vmware_nsxlib.v3.client.RESTClient.patch").start()
|
||||||
mock.patch(
|
mock.patch(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user