NSX|P Availability zones support
For networks & routers Change-Id: I338147bafdf4e1950db4c2cbb8166c515404d5c1
This commit is contained in:
parent
1d7e552ef5
commit
5b95817834
@ -881,7 +881,7 @@ nsxv_az_opts = [
|
|||||||
# the list of expected zones is under nsx_v3 group: availability_zones
|
# the list of expected zones is under nsx_v3 group: availability_zones
|
||||||
# Note: if any of the optional arguments is missing - the global one will be
|
# Note: if any of the optional arguments is missing - the global one will be
|
||||||
# used instead.
|
# used instead.
|
||||||
nsxv3_az_opts = [
|
nsx_v3_and_p_az_opts = [
|
||||||
cfg.StrOpt('metadata_proxy',
|
cfg.StrOpt('metadata_proxy',
|
||||||
help=_("The name or UUID of the NSX Metadata Proxy "
|
help=_("The name or UUID of the NSX Metadata Proxy "
|
||||||
"that will be used to enable native metadata service. "
|
"that will be used to enable native metadata service. "
|
||||||
@ -913,6 +913,13 @@ nsxv3_az_opts = [
|
|||||||
"transport zone that will be used for bridging between "
|
"transport zone that will be used for bridging between "
|
||||||
"Neutron networks, if no physical network has been "
|
"Neutron networks, if no physical network has been "
|
||||||
"specified")),
|
"specified")),
|
||||||
|
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")),
|
||||||
|
]
|
||||||
|
|
||||||
|
nsxv3_az_opts = nsx_v3_and_p_az_opts + [
|
||||||
cfg.ListOpt('switching_profiles',
|
cfg.ListOpt('switching_profiles',
|
||||||
help=_("(Optional) list switching profiles uuids that will be "
|
help=_("(Optional) list switching profiles uuids that will be "
|
||||||
"attached to all neutron created nsx ports.")),
|
"attached to all neutron created nsx ports.")),
|
||||||
@ -930,6 +937,8 @@ nsxv3_az_opts = [
|
|||||||
" the Tier0 router")),
|
" the Tier0 router")),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
nsxp_az_opts = nsx_v3_and_p_az_opts
|
||||||
|
|
||||||
nsx_tvd_opts = [
|
nsx_tvd_opts = [
|
||||||
cfg.ListOpt('nsx_v_extension_drivers',
|
cfg.ListOpt('nsx_v_extension_drivers',
|
||||||
default=[],
|
default=[],
|
||||||
@ -1009,8 +1018,13 @@ def register_nsxv3_azs(conf, availability_zones):
|
|||||||
_register_nsx_azs(conf, availability_zones, nsxv3_az_opts)
|
_register_nsx_azs(conf, availability_zones, nsxv3_az_opts)
|
||||||
|
|
||||||
|
|
||||||
|
def register_nsxp_azs(conf, availability_zones):
|
||||||
|
_register_nsx_azs(conf, availability_zones, nsxp_az_opts)
|
||||||
|
|
||||||
|
|
||||||
register_nsxv_azs(cfg.CONF, cfg.CONF.nsxv.availability_zones)
|
register_nsxv_azs(cfg.CONF, cfg.CONF.nsxv.availability_zones)
|
||||||
register_nsxv3_azs(cfg.CONF, cfg.CONF.nsx_v3.availability_zones)
|
register_nsxv3_azs(cfg.CONF, cfg.CONF.nsx_v3.availability_zones)
|
||||||
|
register_nsxp_azs(cfg.CONF, cfg.CONF.nsx_p.availability_zones)
|
||||||
|
|
||||||
|
|
||||||
def _get_nsx_az_opts(az, opts):
|
def _get_nsx_az_opts(az, opts):
|
||||||
@ -1034,6 +1048,10 @@ def get_nsxv3_az_opts(az):
|
|||||||
return _get_nsx_az_opts(az, nsxv3_az_opts)
|
return _get_nsx_az_opts(az, nsxv3_az_opts)
|
||||||
|
|
||||||
|
|
||||||
|
def get_nsxp_az_opts(az):
|
||||||
|
return _get_nsx_az_opts(az, nsxp_az_opts)
|
||||||
|
|
||||||
|
|
||||||
def validate_nsxv_config_options():
|
def validate_nsxv_config_options():
|
||||||
if (cfg.CONF.nsxv.manager_uri is None or
|
if (cfg.CONF.nsxv.manager_uri is None or
|
||||||
cfg.CONF.nsxv.user is None or
|
cfg.CONF.nsxv.user is None or
|
||||||
|
@ -15,11 +15,8 @@
|
|||||||
|
|
||||||
from vmware_nsx._i18n import _
|
from vmware_nsx._i18n import _
|
||||||
from vmware_nsx.common import availability_zones as common_az
|
from vmware_nsx.common import availability_zones as common_az
|
||||||
from vmware_nsx.common import config
|
|
||||||
from vmware_nsx.common import exceptions as nsx_exc
|
from vmware_nsx.common import exceptions as nsx_exc
|
||||||
|
|
||||||
DEFAULT_NAME = common_az.DEFAULT_NAME + 'v3'
|
|
||||||
|
|
||||||
|
|
||||||
class NsxV3AvailabilityZone(common_az.ConfiguredAvailabilityZone):
|
class NsxV3AvailabilityZone(common_az.ConfiguredAvailabilityZone):
|
||||||
|
|
||||||
@ -34,8 +31,12 @@ class NsxV3AvailabilityZone(common_az.ConfiguredAvailabilityZone):
|
|||||||
# May be overriden by children
|
# May be overriden by children
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def get_az_opts(self):
|
||||||
|
# Should be implemented by children
|
||||||
|
pass
|
||||||
|
|
||||||
def init_from_config_section(self, az_name):
|
def init_from_config_section(self, az_name):
|
||||||
az_info = config.get_nsxv3_az_opts(self.name)
|
az_info = self.get_az_opts()
|
||||||
|
|
||||||
if self._has_native_dhcp_metadata():
|
if self._has_native_dhcp_metadata():
|
||||||
# The optional parameters will get the global values if not
|
# The optional parameters will get the global values if not
|
||||||
|
@ -23,14 +23,29 @@ from sqlalchemy import exc as sql_exc
|
|||||||
|
|
||||||
from six import moves
|
from six import moves
|
||||||
|
|
||||||
|
from neutron.db import agentschedulers_db
|
||||||
|
from neutron.db import allowedaddresspairs_db as addr_pair_db
|
||||||
|
from neutron.db.availability_zone import router as router_az_db
|
||||||
|
from neutron.db import dns_db
|
||||||
|
from neutron.db import external_net_db
|
||||||
|
from neutron.db import extradhcpopt_db
|
||||||
|
from neutron.db import extraroute_db
|
||||||
|
from neutron.db import l3_attrs_db
|
||||||
from neutron.db import l3_db
|
from neutron.db import l3_db
|
||||||
|
from neutron.db import l3_gwmode_db
|
||||||
|
from neutron.db import portbindings_db
|
||||||
|
from neutron.db import portsecurity_db
|
||||||
|
from neutron.db import securitygroups_db
|
||||||
|
from neutron.db import vlantransparent_db
|
||||||
from neutron.extensions import securitygroup as ext_sg
|
from neutron.extensions import securitygroup as ext_sg
|
||||||
from neutron_lib.api.definitions import allowedaddresspairs as addr_apidef
|
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 external_net as extnet_apidef
|
from neutron_lib.api.definitions import external_net as extnet_apidef
|
||||||
from neutron_lib.api.definitions import port_security as psec
|
from neutron_lib.api.definitions import port_security as psec
|
||||||
from neutron_lib.api.definitions import portbindings as pbin
|
from neutron_lib.api.definitions import portbindings as pbin
|
||||||
from neutron_lib.api.definitions import provider_net as pnet
|
from neutron_lib.api.definitions import provider_net as pnet
|
||||||
from neutron_lib.api import validators
|
from neutron_lib.api import validators
|
||||||
|
from neutron_lib.api.validators import availability_zone as az_validator
|
||||||
from neutron_lib import constants
|
from neutron_lib import constants
|
||||||
from neutron_lib.db import api as db_api
|
from neutron_lib.db import api as db_api
|
||||||
from neutron_lib.db import utils as db_utils
|
from neutron_lib.db import utils as db_utils
|
||||||
@ -42,11 +57,14 @@ from neutron_lib.services.qos import constants as qos_consts
|
|||||||
from neutron_lib.utils import helpers
|
from neutron_lib.utils import helpers
|
||||||
from neutron_lib.utils import net as nl_net_utils
|
from neutron_lib.utils import net as nl_net_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 exceptions as nsx_exc
|
||||||
from vmware_nsx.common import nsx_constants
|
from vmware_nsx.common import nsx_constants
|
||||||
from vmware_nsx.common import utils
|
from vmware_nsx.common import utils
|
||||||
from vmware_nsx.db import db as nsx_db
|
from vmware_nsx.db import db as nsx_db
|
||||||
from vmware_nsx.db import extended_security_group as extended_sec
|
from vmware_nsx.db import extended_security_group as extended_sec
|
||||||
|
from vmware_nsx.db import extended_security_group_rule as extend_sg_rule
|
||||||
|
from vmware_nsx.db import maclearning as mac_db
|
||||||
from vmware_nsx.db import nsx_portbindings_db as pbin_db
|
from vmware_nsx.db import nsx_portbindings_db as pbin_db
|
||||||
from vmware_nsx.extensions import maclearning as mac_ext
|
from vmware_nsx.extensions import maclearning as mac_ext
|
||||||
from vmware_nsx.extensions import providersecuritygroup as provider_sg
|
from vmware_nsx.extensions import providersecuritygroup as provider_sg
|
||||||
@ -61,9 +79,31 @@ from vmware_nsxlib.v3 import nsx_constants as nsxlib_consts
|
|||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class NsxPluginV3Base(plugin.NsxPluginBase,
|
# 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
|
||||||
|
# this needs to be above securitygroups_db.SecurityGroupDbMixin.
|
||||||
|
# FIXME(arosen): we can solve this inheritance order issue by just mixining in
|
||||||
|
# the classes into a new class to handle the order correctly.
|
||||||
|
class NsxPluginV3Base(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
||||||
|
addr_pair_db.AllowedAddressPairsMixin,
|
||||||
|
plugin.NsxPluginBase,
|
||||||
extended_sec.ExtendedSecurityGroupPropertiesMixin,
|
extended_sec.ExtendedSecurityGroupPropertiesMixin,
|
||||||
pbin_db.NsxPortBindingMixin):
|
pbin_db.NsxPortBindingMixin,
|
||||||
|
extend_sg_rule.ExtendedSecurityGroupRuleMixin,
|
||||||
|
securitygroups_db.SecurityGroupDbMixin,
|
||||||
|
external_net_db.External_net_db_mixin,
|
||||||
|
extraroute_db.ExtraRoute_db_mixin,
|
||||||
|
router_az_db.RouterAvailabilityZoneMixin,
|
||||||
|
l3_gwmode_db.L3_NAT_db_mixin,
|
||||||
|
portbindings_db.PortBindingMixin,
|
||||||
|
portsecurity_db.PortSecurityDbMixin,
|
||||||
|
extradhcpopt_db.ExtraDhcpOptMixin,
|
||||||
|
dns_db.DNSDbMixin,
|
||||||
|
vlantransparent_db.Vlantransparent_db_mixin,
|
||||||
|
mac_db.MacLearningDbMixin,
|
||||||
|
l3_attrs_db.ExtraAttributesMixin,
|
||||||
|
nsx_com_az.NSXAvailabilityZonesPluginCommon):
|
||||||
"""Common methods for NSX-V3 plugins (NSX-V3 & Policy)"""
|
"""Common methods for NSX-V3 plugins (NSX-V3 & Policy)"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@ -1194,3 +1234,88 @@ class NsxPluginV3Base(plugin.NsxPluginBase,
|
|||||||
elif not port_security:
|
elif not port_security:
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def _validate_obj_az_on_creation(self, context, obj_data, obj_type):
|
||||||
|
# validate the availability zone, and get the AZ object
|
||||||
|
if az_def.AZ_HINTS in obj_data:
|
||||||
|
self._validate_availability_zones_forced(
|
||||||
|
context, obj_type, obj_data[az_def.AZ_HINTS])
|
||||||
|
return self.get_obj_az_by_hints(obj_data)
|
||||||
|
|
||||||
|
def _add_az_to_net(self, context, net_id, net_data):
|
||||||
|
if az_def.AZ_HINTS in net_data:
|
||||||
|
# Update the AZ hints in the neutron object
|
||||||
|
az_hints = az_validator.convert_az_list_to_string(
|
||||||
|
net_data[az_def.AZ_HINTS])
|
||||||
|
super(NsxPluginV3Base, self).update_network(
|
||||||
|
context, net_id,
|
||||||
|
{'network': {az_def.AZ_HINTS: az_hints}})
|
||||||
|
|
||||||
|
def _add_az_to_router(self, context, router_id, router_data):
|
||||||
|
if az_def.AZ_HINTS in router_data:
|
||||||
|
# Update the AZ hints in the neutron object
|
||||||
|
az_hints = az_validator.convert_az_list_to_string(
|
||||||
|
router_data[az_def.AZ_HINTS])
|
||||||
|
super(NsxPluginV3Base, self).update_router(
|
||||||
|
context, router_id,
|
||||||
|
{'router': {az_def.AZ_HINTS: az_hints}})
|
||||||
|
|
||||||
|
def get_network_availability_zones(self, net_db):
|
||||||
|
if self._has_native_dhcp_metadata():
|
||||||
|
hints = az_validator.convert_az_string_to_list(
|
||||||
|
net_db[az_def.AZ_HINTS])
|
||||||
|
# When using the configured AZs, the az will always be the same
|
||||||
|
# as the hint (or default if none)
|
||||||
|
if hints:
|
||||||
|
az_name = hints[0]
|
||||||
|
else:
|
||||||
|
az_name = self.get_default_az().name
|
||||||
|
return [az_name]
|
||||||
|
else:
|
||||||
|
return []
|
||||||
|
|
||||||
|
def _get_router_az_obj(self, router):
|
||||||
|
l3_attrs_db.ExtraAttributesMixin._extend_extra_router_dict(
|
||||||
|
router, router)
|
||||||
|
return self.get_router_az(router)
|
||||||
|
|
||||||
|
def get_router_availability_zones(self, router):
|
||||||
|
"""Return availability zones which a router belongs to."""
|
||||||
|
return [self._get_router_az_obj(router).name]
|
||||||
|
|
||||||
|
def _validate_availability_zones_forced(self, context, resource_type,
|
||||||
|
availability_zones):
|
||||||
|
return self.validate_availability_zones(context, resource_type,
|
||||||
|
availability_zones,
|
||||||
|
force=True)
|
||||||
|
|
||||||
|
def _list_availability_zones(self, context, filters=None):
|
||||||
|
# If no native_dhcp_metadata - use neutron AZs
|
||||||
|
if not self._has_native_dhcp_metadata():
|
||||||
|
return super(NsxPluginV3Base, self)._list_availability_zones(
|
||||||
|
context, filters=filters)
|
||||||
|
|
||||||
|
result = {}
|
||||||
|
for az in self._availability_zones_data.list_availability_zones():
|
||||||
|
# Add this availability zone as a network & router resource
|
||||||
|
if filters:
|
||||||
|
if 'name' in filters and az not in filters['name']:
|
||||||
|
continue
|
||||||
|
for res in ['network', 'router']:
|
||||||
|
if 'resource' not in filters or res in filters['resource']:
|
||||||
|
result[(az, res)] = True
|
||||||
|
return result
|
||||||
|
|
||||||
|
def validate_availability_zones(self, context, resource_type,
|
||||||
|
availability_zones, force=False):
|
||||||
|
# This method is called directly from this plugin but also from
|
||||||
|
# registered callbacks
|
||||||
|
if self._is_sub_plugin and not force:
|
||||||
|
# validation should be done together for both plugins
|
||||||
|
return
|
||||||
|
# If no native_dhcp_metadata - use neutron AZs
|
||||||
|
if not self._has_native_dhcp_metadata():
|
||||||
|
return super(NsxPluginV3Base, self).validate_availability_zones(
|
||||||
|
context, resource_type, availability_zones)
|
||||||
|
# Validate against the configured AZs
|
||||||
|
return self.validate_obj_azs(availability_zones)
|
||||||
|
@ -14,16 +14,24 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
|
from oslo_log import log
|
||||||
|
|
||||||
from vmware_nsx.common import availability_zones as common_az
|
from vmware_nsx.common import availability_zones as common_az
|
||||||
|
from vmware_nsx.common import config
|
||||||
|
from vmware_nsx.common import exceptions as nsx_exc
|
||||||
from vmware_nsx.plugins.common_v3 import availability_zones as v3_az
|
from vmware_nsx.plugins.common_v3 import availability_zones as v3_az
|
||||||
|
from vmware_nsxlib.v3 import exceptions as nsx_lib_exc
|
||||||
|
|
||||||
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
DEFAULT_NAME = common_az.DEFAULT_NAME + 'v3'
|
DEFAULT_NAME = common_az.DEFAULT_NAME + 'p'
|
||||||
|
|
||||||
|
|
||||||
class NsxPAvailabilityZone(v3_az.NsxV3AvailabilityZone):
|
class NsxPAvailabilityZone(v3_az.NsxV3AvailabilityZone):
|
||||||
|
|
||||||
|
def get_az_opts(self):
|
||||||
|
return config.get_nsxp_az_opts(self.name)
|
||||||
|
|
||||||
def init_defaults(self):
|
def init_defaults(self):
|
||||||
# use the default configuration
|
# use the default configuration
|
||||||
self.metadata_proxy = cfg.CONF.nsx_p.metadata_proxy
|
self.metadata_proxy = cfg.CONF.nsx_p.metadata_proxy
|
||||||
@ -32,6 +40,80 @@ class NsxPAvailabilityZone(v3_az.NsxV3AvailabilityZone):
|
|||||||
self.default_overlay_tz = cfg.CONF.nsx_p.default_overlay_tz
|
self.default_overlay_tz = cfg.CONF.nsx_p.default_overlay_tz
|
||||||
self.default_vlan_tz = cfg.CONF.nsx_p.default_vlan_tz
|
self.default_vlan_tz = cfg.CONF.nsx_p.default_vlan_tz
|
||||||
self.default_tier0_router = cfg.CONF.nsx_p.default_tier0_router
|
self.default_tier0_router = cfg.CONF.nsx_p.default_tier0_router
|
||||||
|
self.dns_domain = cfg.CONF.nsx_p.dns_domain
|
||||||
|
self.nameservers = cfg.CONF.nsx_p.nameservers
|
||||||
|
|
||||||
|
def _init_default_resource(self, resource_api, config_name,
|
||||||
|
filter_list_results=None,
|
||||||
|
auto_config=False,
|
||||||
|
is_mandatory=True):
|
||||||
|
# NOTE(annak): we may need to generalize this for API calls
|
||||||
|
# requiring path ids
|
||||||
|
name_or_id = getattr(self, config_name)
|
||||||
|
if not name_or_id:
|
||||||
|
if auto_config:
|
||||||
|
# If the field not specified, the system will auto-configure
|
||||||
|
# in case only single resource is present
|
||||||
|
resources = resource_api.list()
|
||||||
|
if filter_list_results:
|
||||||
|
resources = filter_list_results(resources)
|
||||||
|
if len(resources) == 1:
|
||||||
|
return resources[0]['id']
|
||||||
|
|
||||||
|
if is_mandatory:
|
||||||
|
if self.is_default():
|
||||||
|
raise cfg.RequiredOptError(config_name,
|
||||||
|
group=cfg.OptGroup('nsx_p'))
|
||||||
|
else:
|
||||||
|
msg = (_("No %(res)s provided for availability "
|
||||||
|
"zone %(az)s") % {
|
||||||
|
'res': config_name,
|
||||||
|
'az': self.name})
|
||||||
|
raise nsx_exc.NsxPluginException(err_msg=msg)
|
||||||
|
return None
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Check if the configured value is the ID
|
||||||
|
resource_api.get(name_or_id, silent=True)
|
||||||
|
return name_or_id
|
||||||
|
except nsx_lib_exc.ResourceNotFound:
|
||||||
|
# Check if the configured value is the name
|
||||||
|
resource = resource_api.get_by_name(name_or_id)
|
||||||
|
if resource:
|
||||||
|
return resource['id']
|
||||||
|
else:
|
||||||
|
if self.is_default():
|
||||||
|
raise cfg.RequiredOptError(config_name,
|
||||||
|
group=cfg.OptGroup('nsx_p'))
|
||||||
|
else:
|
||||||
|
msg = (_("Could not find %(res)s %(id)s for availability "
|
||||||
|
"zone %(az)s") % {
|
||||||
|
'res': config_name,
|
||||||
|
'id': name_or_id,
|
||||||
|
'az': self.name})
|
||||||
|
raise nsx_exc.NsxPluginException(err_msg=msg)
|
||||||
|
|
||||||
|
def translate_configured_names_to_uuids(self, nsxpolicy):
|
||||||
|
super(NsxPAvailabilityZone, self).translate_configured_names_to_uuids(
|
||||||
|
nsxpolicy)
|
||||||
|
|
||||||
|
# TODO(asarfaty): add DHCP/metadata parameters
|
||||||
|
# TODO(asarfaty): add support for init_objects_by_tags
|
||||||
|
self._default_overlay_tz_uuid = self._init_default_resource(
|
||||||
|
nsxpolicy.transport_zone, 'default_overlay_tz',
|
||||||
|
auto_config=True, is_mandatory=True,
|
||||||
|
filter_list_results=lambda tzs: [
|
||||||
|
tz for tz in tzs if tz['tz_type'].startswith('OVERLAY')])
|
||||||
|
|
||||||
|
self._default_vlan_tz_uuid = self._init_default_resource(
|
||||||
|
nsxpolicy.transport_zone, 'default_vlan_tz',
|
||||||
|
auto_config=True, is_mandatory=False,
|
||||||
|
filter_list_results=lambda tzs: [
|
||||||
|
tz for tz in tzs if tz['tz_type'].startswith('VLAN')])
|
||||||
|
|
||||||
|
self._default_tier0_router = self._init_default_resource(
|
||||||
|
nsxpolicy.tier0, 'default_tier0_router',
|
||||||
|
auto_config=True, is_mandatory=True)
|
||||||
|
|
||||||
|
|
||||||
class NsxPAvailabilityZones(common_az.ConfiguredAvailabilityZones):
|
class NsxPAvailabilityZones(common_az.ConfiguredAvailabilityZones):
|
||||||
|
@ -22,22 +22,10 @@ from oslo_utils import excutils
|
|||||||
from oslo_utils import uuidutils
|
from oslo_utils import uuidutils
|
||||||
import webob.exc
|
import webob.exc
|
||||||
|
|
||||||
from neutron.db import agentschedulers_db
|
|
||||||
from neutron.db import allowedaddresspairs_db as addr_pair_db
|
|
||||||
from neutron.db import dns_db
|
|
||||||
from neutron.db import external_net_db
|
|
||||||
from neutron.db import extradhcpopt_db
|
|
||||||
from neutron.db import extraroute_db
|
|
||||||
from neutron.db import l3_attrs_db
|
|
||||||
from neutron.db import l3_db
|
from neutron.db import l3_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
|
||||||
from neutron.db import models_v2
|
from neutron.db import models_v2
|
||||||
from neutron.db import portbindings_db
|
|
||||||
from neutron.db import portsecurity_db
|
|
||||||
from neutron.db import securitygroups_db
|
|
||||||
from neutron.db import vlantransparent_db
|
|
||||||
from neutron.extensions import providernet
|
from neutron.extensions import providernet
|
||||||
from neutron.extensions import securitygroup as ext_sg
|
from neutron.extensions import securitygroup as ext_sg
|
||||||
from neutron.quota import resource_registry
|
from neutron.quota import resource_registry
|
||||||
@ -66,8 +54,6 @@ from vmware_nsx.common import locking
|
|||||||
from vmware_nsx.common import managers
|
from vmware_nsx.common import managers
|
||||||
from vmware_nsx.common import utils
|
from vmware_nsx.common import utils
|
||||||
from vmware_nsx.db import db as nsx_db
|
from vmware_nsx.db import db as nsx_db
|
||||||
from vmware_nsx.db import extended_security_group_rule as extend_sg_rule
|
|
||||||
from vmware_nsx.db import maclearning as mac_db
|
|
||||||
from vmware_nsx.extensions import maclearning as mac_ext
|
from vmware_nsx.extensions import maclearning as mac_ext
|
||||||
from vmware_nsx.extensions import projectpluginmap
|
from vmware_nsx.extensions import projectpluginmap
|
||||||
from vmware_nsx.extensions import providersecuritygroup as provider_sg
|
from vmware_nsx.extensions import providersecuritygroup as provider_sg
|
||||||
@ -105,21 +91,7 @@ SEG_SECURITY_PROFILE_UUID = (
|
|||||||
|
|
||||||
|
|
||||||
@resource_extend.has_resource_extenders
|
@resource_extend.has_resource_extenders
|
||||||
class NsxPolicyPlugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base):
|
||||||
addr_pair_db.AllowedAddressPairsMixin,
|
|
||||||
nsx_plugin_common.NsxPluginV3Base,
|
|
||||||
extend_sg_rule.ExtendedSecurityGroupRuleMixin,
|
|
||||||
securitygroups_db.SecurityGroupDbMixin,
|
|
||||||
external_net_db.External_net_db_mixin,
|
|
||||||
extraroute_db.ExtraRoute_db_mixin,
|
|
||||||
l3_gwmode_db.L3_NAT_db_mixin,
|
|
||||||
portbindings_db.PortBindingMixin,
|
|
||||||
portsecurity_db.PortSecurityDbMixin,
|
|
||||||
extradhcpopt_db.ExtraDhcpOptMixin,
|
|
||||||
dns_db.DNSDbMixin,
|
|
||||||
vlantransparent_db.Vlantransparent_db_mixin,
|
|
||||||
mac_db.MacLearningDbMixin,
|
|
||||||
l3_attrs_db.ExtraAttributesMixin):
|
|
||||||
|
|
||||||
__native_bulk_support = True
|
__native_bulk_support = True
|
||||||
__native_pagination_support = True
|
__native_pagination_support = True
|
||||||
@ -140,6 +112,9 @@ class NsxPolicyPlugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
|||||||
"external-net",
|
"external-net",
|
||||||
"extraroute",
|
"extraroute",
|
||||||
"router",
|
"router",
|
||||||
|
"availability_zone",
|
||||||
|
"network_availability_zone",
|
||||||
|
"router_availability_zone",
|
||||||
"subnet_allocation",
|
"subnet_allocation",
|
||||||
"security-group-logging",
|
"security-group-logging",
|
||||||
"provider-security-group",
|
"provider-security-group",
|
||||||
@ -159,6 +134,7 @@ class NsxPolicyPlugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.fwaas_callbacks = None
|
self.fwaas_callbacks = None
|
||||||
self.init_is_complete = False
|
self.init_is_complete = False
|
||||||
|
self._is_sub_plugin = False
|
||||||
nsxlib_utils.set_is_attr_callback(validators.is_attr_set)
|
nsxlib_utils.set_is_attr_callback(validators.is_attr_set)
|
||||||
self._extend_fault_map()
|
self._extend_fault_map()
|
||||||
extension_drivers = cfg.CONF.nsx_extension_drivers
|
extension_drivers = cfg.CONF.nsx_extension_drivers
|
||||||
@ -189,60 +165,11 @@ 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,
|
|
||||||
filter_list_results=None):
|
|
||||||
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 filter_list_results:
|
|
||||||
resources = filter_list_results(resources)
|
|
||||||
if len(resources) == 1:
|
|
||||||
return resources[0]['id']
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
|
|
||||||
try:
|
|
||||||
resource_api.get(name_or_id, silent=True)
|
|
||||||
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):
|
def _init_default_config(self):
|
||||||
"""Validate the configuration & initialize default values"""
|
# Default tier0/transport zones are initialized via the default AZ
|
||||||
# Default Tier0 router
|
# Init AZ resources
|
||||||
self.default_tier0_router = self._init_default_resource(
|
for az in self.get_azs_list():
|
||||||
self.nsxpolicy.tier0,
|
az.translate_configured_names_to_uuids(self.nsxpolicy)
|
||||||
cfg.CONF.nsx_p.default_tier0_router)
|
|
||||||
|
|
||||||
if not self.default_tier0_router:
|
|
||||||
raise cfg.RequiredOptError("default_tier0_router",
|
|
||||||
group=cfg.OptGroup('nsx_p'))
|
|
||||||
|
|
||||||
# Default overlay transport zone
|
|
||||||
self.default_overlay_tz = self._init_default_resource(
|
|
||||||
self.nsxpolicy.transport_zone,
|
|
||||||
cfg.CONF.nsx_p.default_overlay_tz,
|
|
||||||
filter_list_results=lambda tzs: [
|
|
||||||
tz for tz in tzs if tz['tz_type'].startswith('OVERLAY')])
|
|
||||||
|
|
||||||
if not self.default_overlay_tz:
|
|
||||||
raise cfg.RequiredOptError("default_overlay_tz",
|
|
||||||
group=cfg.OptGroup('nsx_p'))
|
|
||||||
|
|
||||||
# Default VLAN transport zone (not mandatory)
|
|
||||||
self.default_vlan_tz = self._init_default_resource(
|
|
||||||
self.nsxpolicy.transport_zone,
|
|
||||||
cfg.CONF.nsx_p.default_vlan_tz,
|
|
||||||
filter_list_results=lambda tzs: [
|
|
||||||
tz for tz in tzs if tz['tz_type'].startswith('VLAN')])
|
|
||||||
|
|
||||||
def init_availability_zones(self):
|
def init_availability_zones(self):
|
||||||
self._availability_zones_data = nsxp_az.NsxPAvailabilityZones()
|
self._availability_zones_data = nsxp_az.NsxPAvailabilityZones()
|
||||||
@ -419,6 +346,9 @@ class NsxPolicyPlugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
|||||||
is_external_net = validators.is_attr_set(external) and external
|
is_external_net = validators.is_attr_set(external) and external
|
||||||
tenant_id = net_data['tenant_id']
|
tenant_id = net_data['tenant_id']
|
||||||
|
|
||||||
|
# validate the availability zone, and get the AZ object
|
||||||
|
az = self._validate_obj_az_on_creation(context, net_data, 'network')
|
||||||
|
|
||||||
self._ensure_default_security_group(context, tenant_id)
|
self._ensure_default_security_group(context, tenant_id)
|
||||||
vlt = vlan_apidef.get_vlan_transparent(net_data)
|
vlt = vlan_apidef.get_vlan_transparent(net_data)
|
||||||
|
|
||||||
@ -427,7 +357,7 @@ class NsxPolicyPlugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
|||||||
if is_external_net:
|
if is_external_net:
|
||||||
is_provider_net, net_type, physical_net, vlan_id = (
|
is_provider_net, net_type, physical_net, vlan_id = (
|
||||||
self._validate_external_net_create(
|
self._validate_external_net_create(
|
||||||
net_data, self.default_tier0_router,
|
net_data, az._default_tier0_router,
|
||||||
self._tier0_validator))
|
self._tier0_validator))
|
||||||
provider_data = {'is_provider_net': is_provider_net,
|
provider_data = {'is_provider_net': is_provider_net,
|
||||||
'net_type': net_type,
|
'net_type': net_type,
|
||||||
@ -437,8 +367,8 @@ class NsxPolicyPlugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
|||||||
else:
|
else:
|
||||||
provider_data = self._validate_provider_create(
|
provider_data = self._validate_provider_create(
|
||||||
context, net_data,
|
context, net_data,
|
||||||
self.default_vlan_tz,
|
az._default_vlan_tz_uuid,
|
||||||
self.default_overlay_tz,
|
az._default_overlay_tz_uuid,
|
||||||
self.nsxpolicy.transport_zone,
|
self.nsxpolicy.transport_zone,
|
||||||
self.nsxpolicy.segment,
|
self.nsxpolicy.segment,
|
||||||
transparent_vlan=vlt)
|
transparent_vlan=vlt)
|
||||||
@ -464,6 +394,7 @@ class NsxPolicyPlugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
|||||||
self._process_network_port_security_create(
|
self._process_network_port_security_create(
|
||||||
context, net_data, created_net)
|
context, net_data, created_net)
|
||||||
self._process_l3_create(context, created_net, net_data)
|
self._process_l3_create(context, created_net, net_data)
|
||||||
|
self._add_az_to_net(context, created_net['id'], net_data)
|
||||||
|
|
||||||
if provider_data['is_provider_net']:
|
if provider_data['is_provider_net']:
|
||||||
# Save provider network fields, needed by get_network()
|
# Save provider network fields, needed by get_network()
|
||||||
@ -942,7 +873,8 @@ class NsxPolicyPlugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
|||||||
return
|
return
|
||||||
network = self.get_network(context, network_id)
|
network = self.get_network(context, network_id)
|
||||||
if not network.get(pnet.PHYSICAL_NETWORK):
|
if not network.get(pnet.PHYSICAL_NETWORK):
|
||||||
return self.default_tier0_router
|
az = self.get_network_az(network)
|
||||||
|
return az._default_tier0_router
|
||||||
else:
|
else:
|
||||||
return network.get(pnet.PHYSICAL_NETWORK)
|
return network.get(pnet.PHYSICAL_NETWORK)
|
||||||
|
|
||||||
@ -1104,6 +1036,11 @@ class NsxPolicyPlugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
|||||||
def create_router(self, context, router):
|
def create_router(self, context, router):
|
||||||
r = router['router']
|
r = router['router']
|
||||||
gw_info = self._extract_external_gw(context, router, is_extract=True)
|
gw_info = self._extract_external_gw(context, router, is_extract=True)
|
||||||
|
|
||||||
|
# validate the availability zone, and get the AZ object
|
||||||
|
# TODO(asarfaty): router AZ is not used for anything yet
|
||||||
|
self._validate_obj_az_on_creation(context, r, 'router')
|
||||||
|
|
||||||
with db_api.CONTEXT_WRITER.using(context):
|
with db_api.CONTEXT_WRITER.using(context):
|
||||||
router = super(NsxPolicyPlugin, self).create_router(
|
router = super(NsxPolicyPlugin, self).create_router(
|
||||||
context, router)
|
context, router)
|
||||||
@ -1917,9 +1854,6 @@ class NsxPolicyPlugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
|||||||
tz)
|
tz)
|
||||||
return type == nsxlib_consts.TRANSPORT_TYPE_OVERLAY
|
return type == nsxlib_consts.TRANSPORT_TYPE_OVERLAY
|
||||||
|
|
||||||
def _has_native_dhcp_metadata(self):
|
|
||||||
return True
|
|
||||||
|
|
||||||
def _is_ens_tz_net(self, context, net_id):
|
def _is_ens_tz_net(self, context, net_id):
|
||||||
#TODO(annak): handle ENS case
|
#TODO(annak): handle ENS case
|
||||||
return False
|
return False
|
||||||
@ -1927,3 +1861,6 @@ class NsxPolicyPlugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
|||||||
def _is_ens_tz_port(self, context, port_data):
|
def _is_ens_tz_port(self, context, port_data):
|
||||||
#TODO(annak): handle ENS case
|
#TODO(annak): handle ENS case
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def _has_native_dhcp_metadata(self):
|
||||||
|
return True
|
||||||
|
@ -21,16 +21,21 @@ from vmware_nsx.plugins.common_v3 import availability_zones as v3_az
|
|||||||
from vmware_nsxlib.v3 import core_resources
|
from vmware_nsxlib.v3 import core_resources
|
||||||
from vmware_nsxlib.v3 import nsx_constants as nsxlib_consts
|
from vmware_nsxlib.v3 import nsx_constants as nsxlib_consts
|
||||||
|
|
||||||
|
DEFAULT_NAME = common_az.DEFAULT_NAME + 'v3'
|
||||||
|
|
||||||
|
|
||||||
class NsxV3AvailabilityZone(v3_az.NsxV3AvailabilityZone):
|
class NsxV3AvailabilityZone(v3_az.NsxV3AvailabilityZone):
|
||||||
|
|
||||||
|
def get_az_opts(self):
|
||||||
|
return config.get_nsxv3_az_opts(self.name)
|
||||||
|
|
||||||
def _has_native_dhcp_metadata(self):
|
def _has_native_dhcp_metadata(self):
|
||||||
return cfg.CONF.nsx_v3.native_dhcp_metadata
|
return cfg.CONF.nsx_v3.native_dhcp_metadata
|
||||||
|
|
||||||
def init_from_config_section(self, az_name):
|
def init_from_config_section(self, az_name):
|
||||||
super(NsxV3AvailabilityZone, self).init_from_config_section(az_name)
|
super(NsxV3AvailabilityZone, self).init_from_config_section(az_name)
|
||||||
|
|
||||||
az_info = config.get_nsxv3_az_opts(self.name)
|
az_info = self.get_az_opts()
|
||||||
|
|
||||||
switching_profiles = az_info.get('switching_profiles')
|
switching_profiles = az_info.get('switching_profiles')
|
||||||
if switching_profiles:
|
if switching_profiles:
|
||||||
@ -197,7 +202,7 @@ class NsxV3AvailabilityZone(v3_az.NsxV3AvailabilityZone):
|
|||||||
|
|
||||||
class NsxV3AvailabilityZones(common_az.ConfiguredAvailabilityZones):
|
class NsxV3AvailabilityZones(common_az.ConfiguredAvailabilityZones):
|
||||||
|
|
||||||
default_name = v3_az.DEFAULT_NAME
|
default_name = DEFAULT_NAME
|
||||||
|
|
||||||
def __init__(self, use_tvd_config=False):
|
def __init__(self, use_tvd_config=False):
|
||||||
if use_tvd_config:
|
if use_tvd_config:
|
||||||
|
@ -19,13 +19,11 @@ import mock
|
|||||||
import netaddr
|
import netaddr
|
||||||
from neutron_lib.agent import topics
|
from neutron_lib.agent import topics
|
||||||
from neutron_lib.api.definitions import allowedaddresspairs as addr_apidef
|
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 external_net as extnet_apidef
|
from neutron_lib.api.definitions import external_net as extnet_apidef
|
||||||
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
|
||||||
from neutron_lib.api import extensions
|
from neutron_lib.api import extensions
|
||||||
from neutron_lib.api import faults
|
from neutron_lib.api import faults
|
||||||
from neutron_lib.api.validators import availability_zone as az_validator
|
|
||||||
from neutron_lib.db import api as db_api
|
from neutron_lib.db import api as db_api
|
||||||
from neutron_lib.db import resource_extend
|
from neutron_lib.db import resource_extend
|
||||||
from neutron_lib.db import utils as db_utils
|
from neutron_lib.db import utils as db_utils
|
||||||
@ -39,24 +37,11 @@ from neutron.api.rpc.agentnotifiers import dhcp_rpc_agent_api
|
|||||||
from neutron.api.rpc.handlers import dhcp_rpc
|
from neutron.api.rpc.handlers import dhcp_rpc
|
||||||
from neutron.api.rpc.handlers import metadata_rpc
|
from neutron.api.rpc.handlers import metadata_rpc
|
||||||
from neutron.db import agents_db
|
from neutron.db import agents_db
|
||||||
from neutron.db import agentschedulers_db
|
|
||||||
from neutron.db import allowedaddresspairs_db as addr_pair_db
|
|
||||||
from neutron.db.availability_zone import router as router_az_db
|
|
||||||
from neutron.db import db_base_plugin_v2
|
from neutron.db import db_base_plugin_v2
|
||||||
from neutron.db import dns_db
|
|
||||||
from neutron.db import external_net_db
|
|
||||||
from neutron.db import extradhcpopt_db
|
|
||||||
from neutron.db import extraroute_db
|
|
||||||
from neutron.db import l3_attrs_db
|
|
||||||
from neutron.db import l3_db
|
from neutron.db import l3_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
|
||||||
from neutron.db import models_v2
|
from neutron.db import models_v2
|
||||||
from neutron.db import portbindings_db
|
|
||||||
from neutron.db import portsecurity_db
|
|
||||||
from neutron.db import securitygroups_db
|
|
||||||
from neutron.db import vlantransparent_db
|
|
||||||
from neutron.extensions import providernet
|
from neutron.extensions import providernet
|
||||||
from neutron.extensions import securitygroup as ext_sg
|
from neutron.extensions import securitygroup as ext_sg
|
||||||
from neutron.quota import resource_registry
|
from neutron.quota import resource_registry
|
||||||
@ -82,7 +67,6 @@ import webob.exc
|
|||||||
|
|
||||||
from vmware_nsx._i18n import _
|
from vmware_nsx._i18n import _
|
||||||
from vmware_nsx.api_replay import utils as api_replay_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 config # noqa
|
from vmware_nsx.common import config # noqa
|
||||||
from vmware_nsx.common import exceptions as nsx_exc
|
from vmware_nsx.common import exceptions as nsx_exc
|
||||||
from vmware_nsx.common import l3_rpc_agent_api
|
from vmware_nsx.common import l3_rpc_agent_api
|
||||||
@ -91,8 +75,6 @@ from vmware_nsx.common import managers
|
|||||||
from vmware_nsx.common import nsx_constants
|
from vmware_nsx.common import nsx_constants
|
||||||
from vmware_nsx.common import utils
|
from vmware_nsx.common import utils
|
||||||
from vmware_nsx.db import db as nsx_db
|
from vmware_nsx.db import db as nsx_db
|
||||||
from vmware_nsx.db import extended_security_group_rule as extend_sg_rule
|
|
||||||
from vmware_nsx.db import maclearning as mac_db
|
|
||||||
from vmware_nsx.dhcp_meta import rpc as nsx_rpc
|
from vmware_nsx.dhcp_meta import rpc as nsx_rpc
|
||||||
from vmware_nsx.extensions import advancedserviceproviders as as_providers
|
from vmware_nsx.extensions import advancedserviceproviders as as_providers
|
||||||
from vmware_nsx.extensions import housekeeper as hk_ext
|
from vmware_nsx.extensions import housekeeper as hk_ext
|
||||||
@ -145,30 +127,8 @@ NSX_V3_CLIENT_SSL_PROFILE = 'nsx-default-client-ssl-profile'
|
|||||||
NSX_V3_OS_DFW_UUID = '00000000-def0-0000-0fed-000000000000'
|
NSX_V3_OS_DFW_UUID = '00000000-def0-0000-0fed-000000000000'
|
||||||
|
|
||||||
|
|
||||||
# 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
|
|
||||||
# this needs to be above securitygroups_db.SecurityGroupDbMixin.
|
|
||||||
# FIXME(arosen): we can solve this inheritance order issue by just mixining in
|
|
||||||
# the classes into a new class to handle the order correctly.
|
|
||||||
@resource_extend.has_resource_extenders
|
@resource_extend.has_resource_extenders
|
||||||
class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
class NsxV3Plugin(nsx_plugin_common.NsxPluginV3Base,
|
||||||
addr_pair_db.AllowedAddressPairsMixin,
|
|
||||||
nsx_plugin_common.NsxPluginV3Base,
|
|
||||||
extend_sg_rule.ExtendedSecurityGroupRuleMixin,
|
|
||||||
securitygroups_db.SecurityGroupDbMixin,
|
|
||||||
external_net_db.External_net_db_mixin,
|
|
||||||
extraroute_db.ExtraRoute_db_mixin,
|
|
||||||
router_az_db.RouterAvailabilityZoneMixin,
|
|
||||||
l3_gwmode_db.L3_NAT_db_mixin,
|
|
||||||
portbindings_db.PortBindingMixin,
|
|
||||||
portsecurity_db.PortSecurityDbMixin,
|
|
||||||
extradhcpopt_db.ExtraDhcpOptMixin,
|
|
||||||
dns_db.DNSDbMixin,
|
|
||||||
vlantransparent_db.Vlantransparent_db_mixin,
|
|
||||||
mac_db.MacLearningDbMixin,
|
|
||||||
nsx_com_az.NSXAvailabilityZonesPluginCommon,
|
|
||||||
l3_attrs_db.ExtraAttributesMixin,
|
|
||||||
hk_ext.Housekeeper):
|
hk_ext.Housekeeper):
|
||||||
|
|
||||||
__native_bulk_support = True
|
__native_bulk_support = True
|
||||||
@ -879,11 +839,6 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
|||||||
|
|
||||||
return self.conn.consume_in_threads()
|
return self.conn.consume_in_threads()
|
||||||
|
|
||||||
def _get_router_az_obj(self, router):
|
|
||||||
l3_attrs_db.ExtraAttributesMixin._extend_extra_router_dict(
|
|
||||||
router, router)
|
|
||||||
return self.get_router_az(router)
|
|
||||||
|
|
||||||
def _get_edge_cluster(self, tier0_uuid, router):
|
def _get_edge_cluster(self, tier0_uuid, router):
|
||||||
az = self._get_router_az_obj(router)
|
az = self._get_router_az_obj(router)
|
||||||
if az and az._edge_cluster_uuid:
|
if az and az._edge_cluster_uuid:
|
||||||
@ -1046,10 +1001,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
|||||||
tenant_id = net_data['tenant_id']
|
tenant_id = net_data['tenant_id']
|
||||||
|
|
||||||
# validate the availability zone, and get the AZ object
|
# validate the availability zone, and get the AZ object
|
||||||
if az_def.AZ_HINTS in net_data:
|
az = self._validate_obj_az_on_creation(context, net_data, 'network')
|
||||||
self._validate_availability_zones_forced(
|
|
||||||
context, 'network', net_data[az_def.AZ_HINTS])
|
|
||||||
az = self.get_obj_az_by_hints(net_data)
|
|
||||||
|
|
||||||
self._ensure_default_security_group(context, tenant_id)
|
self._ensure_default_security_group(context, tenant_id)
|
||||||
|
|
||||||
@ -1086,15 +1038,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
|||||||
self._process_network_port_security_create(
|
self._process_network_port_security_create(
|
||||||
context, net_data, created_net)
|
context, net_data, created_net)
|
||||||
self._process_l3_create(context, created_net, net_data)
|
self._process_l3_create(context, created_net, net_data)
|
||||||
|
self._add_az_to_net(context, created_net['id'], net_data)
|
||||||
if az_def.AZ_HINTS in net_data:
|
|
||||||
# Update the AZ hints in the neutron object
|
|
||||||
az_hints = az_validator.convert_az_list_to_string(
|
|
||||||
net_data[az_def.AZ_HINTS])
|
|
||||||
super(NsxV3Plugin, self).update_network(
|
|
||||||
context,
|
|
||||||
created_net['id'],
|
|
||||||
{'network': {az_def.AZ_HINTS: az_hints}})
|
|
||||||
|
|
||||||
if is_provider_net:
|
if is_provider_net:
|
||||||
# Save provider network fields, needed by get_network()
|
# Save provider network fields, needed by get_network()
|
||||||
@ -3004,7 +2948,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
|||||||
return
|
return
|
||||||
network = self.get_network(context, network_id)
|
network = self.get_network(context, network_id)
|
||||||
if not network.get(pnet.PHYSICAL_NETWORK):
|
if not network.get(pnet.PHYSICAL_NETWORK):
|
||||||
az = self.get_network_az_by_net_id(context, network_id)
|
az = self.get_network_az(network)
|
||||||
return az._default_tier0_router
|
return az._default_tier0_router
|
||||||
else:
|
else:
|
||||||
return network.get(pnet.PHYSICAL_NETWORK)
|
return network.get(pnet.PHYSICAL_NETWORK)
|
||||||
@ -3221,9 +3165,7 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
|||||||
self.validate_router_dhcp_relay(context)
|
self.validate_router_dhcp_relay(context)
|
||||||
|
|
||||||
# validate the availability zone
|
# validate the availability zone
|
||||||
if az_def.AZ_HINTS in r:
|
self._validate_obj_az_on_creation(context, r, 'router')
|
||||||
self._validate_availability_zones_forced(context, 'router',
|
|
||||||
r[az_def.AZ_HINTS])
|
|
||||||
|
|
||||||
gw_info = self._extract_external_gw(context, router, is_extract=True)
|
gw_info = self._extract_external_gw(context, router, is_extract=True)
|
||||||
r['id'] = (r.get('id') or uuidutils.generate_uuid())
|
r['id'] = (r.get('id') or uuidutils.generate_uuid())
|
||||||
@ -3231,14 +3173,8 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
|||||||
r, resource_type='os-neutron-router-id',
|
r, resource_type='os-neutron-router-id',
|
||||||
project_name=context.tenant_name)
|
project_name=context.tenant_name)
|
||||||
router = super(NsxV3Plugin, self).create_router(context, router)
|
router = super(NsxV3Plugin, self).create_router(context, router)
|
||||||
if az_def.AZ_HINTS in r:
|
self._add_az_to_router(context, router['id'], r)
|
||||||
# Update the AZ hints in the neutron object
|
|
||||||
az_hints = az_validator.convert_az_list_to_string(
|
|
||||||
r[az_def.AZ_HINTS])
|
|
||||||
super(NsxV3Plugin, self).update_router(
|
|
||||||
context,
|
|
||||||
router['id'],
|
|
||||||
{'router': {az_def.AZ_HINTS: az_hints}})
|
|
||||||
router_db = self._get_router(context, r['id'])
|
router_db = self._get_router(context, r['id'])
|
||||||
with db_api.CONTEXT_WRITER.using(context):
|
with db_api.CONTEXT_WRITER.using(context):
|
||||||
self._process_extra_attr_router_create(context, router_db, r)
|
self._process_extra_attr_router_create(context, router_db, r)
|
||||||
@ -3319,10 +3255,6 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
|||||||
|
|
||||||
return ret_val
|
return ret_val
|
||||||
|
|
||||||
def get_router_availability_zones(self, router):
|
|
||||||
"""Return availability zones which a router belongs to."""
|
|
||||||
return [self._get_router_az_obj(router).name]
|
|
||||||
|
|
||||||
def _update_router_wrapper(self, context, router_id, router):
|
def _update_router_wrapper(self, context, router_id, router):
|
||||||
if cfg.CONF.api_replay_mode:
|
if cfg.CONF.api_replay_mode:
|
||||||
# NOTE(arosen): the mock.patch here is needed for api_replay_mode
|
# NOTE(arosen): the mock.patch here is needed for api_replay_mode
|
||||||
@ -4325,57 +4257,6 @@ class NsxV3Plugin(agentschedulers_db.AZDhcpAgentSchedulerDbMixin,
|
|||||||
rules = [(rule['display_name'], rule['id']) for rule in firewall_rules]
|
rules = [(rule['display_name'], rule['id']) for rule in firewall_rules]
|
||||||
nsx_db.save_sg_rule_mappings(context.session, rules)
|
nsx_db.save_sg_rule_mappings(context.session, rules)
|
||||||
|
|
||||||
def _list_availability_zones(self, context, filters=None):
|
|
||||||
# If no native_dhcp_metadata - use neutron AZs
|
|
||||||
if not cfg.CONF.nsx_v3.native_dhcp_metadata:
|
|
||||||
return super(NsxV3Plugin, self)._list_availability_zones(
|
|
||||||
context, filters=filters)
|
|
||||||
|
|
||||||
result = {}
|
|
||||||
for az in self._availability_zones_data.list_availability_zones():
|
|
||||||
# Add this availability zone as a network & router resource
|
|
||||||
if filters:
|
|
||||||
if 'name' in filters and az not in filters['name']:
|
|
||||||
continue
|
|
||||||
for res in ['network', 'router']:
|
|
||||||
if 'resource' not in filters or res in filters['resource']:
|
|
||||||
result[(az, res)] = True
|
|
||||||
return result
|
|
||||||
|
|
||||||
def _validate_availability_zones_forced(self, context, resource_type,
|
|
||||||
availability_zones):
|
|
||||||
return self.validate_availability_zones(context, resource_type,
|
|
||||||
availability_zones,
|
|
||||||
force=True)
|
|
||||||
|
|
||||||
def validate_availability_zones(self, context, resource_type,
|
|
||||||
availability_zones, force=False):
|
|
||||||
# This method is called directly from this plugin but also from
|
|
||||||
# registered callbacks
|
|
||||||
if self._is_sub_plugin and not force:
|
|
||||||
# validation should be done together for both plugins
|
|
||||||
return
|
|
||||||
# If no native_dhcp_metadata - use neutron AZs
|
|
||||||
if not cfg.CONF.nsx_v3.native_dhcp_metadata:
|
|
||||||
return super(NsxV3Plugin, self).validate_availability_zones(
|
|
||||||
context, resource_type, availability_zones)
|
|
||||||
# Validate against the configured AZs
|
|
||||||
return self.validate_obj_azs(availability_zones)
|
|
||||||
|
|
||||||
def get_network_availability_zones(self, net_db):
|
|
||||||
if cfg.CONF.nsx_v3.native_dhcp_metadata:
|
|
||||||
hints = az_validator.convert_az_string_to_list(
|
|
||||||
net_db[az_def.AZ_HINTS])
|
|
||||||
# When using the configured AZs, the az will always be the same
|
|
||||||
# as the hint (or default if none)
|
|
||||||
if hints:
|
|
||||||
az_name = hints[0]
|
|
||||||
else:
|
|
||||||
az_name = self.get_default_az().name
|
|
||||||
return [az_name]
|
|
||||||
else:
|
|
||||||
return []
|
|
||||||
|
|
||||||
def recalculate_snat_rules_for_router(self, context, router, subnets):
|
def recalculate_snat_rules_for_router(self, context, router, subnets):
|
||||||
"""Recalculate router snat rules for specific subnets.
|
"""Recalculate router snat rules for specific subnets.
|
||||||
Invoked when subnetpool address scope changes.
|
Invoked when subnetpool address scope changes.
|
||||||
|
@ -12,12 +12,15 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
from oslo_config import cfg
|
||||||
|
|
||||||
from neutron.db import l3_dvr_db # noqa
|
from neutron.db import l3_dvr_db # noqa
|
||||||
from neutron_lib import context
|
from neutron_lib import context
|
||||||
from neutron_lib.plugins import constants as const
|
from neutron_lib.plugins import constants as const
|
||||||
from neutron_lib.plugins import directory
|
from neutron_lib.plugins import directory
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
|
|
||||||
|
from vmware_nsx.common import config
|
||||||
from vmware_nsx.plugins.nsx_p import plugin
|
from vmware_nsx.plugins.nsx_p import plugin
|
||||||
from vmware_nsx.plugins.nsx_v3 import utils as v3_utils
|
from vmware_nsx.plugins.nsx_v3 import utils as v3_utils
|
||||||
from vmware_nsx.shell.admin.plugins.common import formatters
|
from vmware_nsx.shell.admin.plugins.common import formatters
|
||||||
@ -70,6 +73,8 @@ def get_realization_info(resource, *realization_args):
|
|||||||
|
|
||||||
class NsxPolicyPluginWrapper(plugin.NsxPolicyPlugin):
|
class NsxPolicyPluginWrapper(plugin.NsxPolicyPlugin):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
# initialize the availability zones
|
||||||
|
config.register_nsxp_azs(cfg.CONF, cfg.CONF.nsx_p.availability_zones)
|
||||||
super(NsxPolicyPluginWrapper, self).__init__()
|
super(NsxPolicyPluginWrapper, self).__init__()
|
||||||
self.context = context.get_admin_context()
|
self.context = context.get_admin_context()
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ from oslo_log import log as logging
|
|||||||
from vmware_nsx.common import config # noqa
|
from vmware_nsx.common import config # noqa
|
||||||
from vmware_nsx.common import utils as nsx_utils
|
from vmware_nsx.common import utils as nsx_utils
|
||||||
from vmware_nsx.dhcp_meta import rpc as nsx_rpc
|
from vmware_nsx.dhcp_meta import rpc as nsx_rpc
|
||||||
from vmware_nsx.plugins.common_v3 import availability_zones as nsx_az
|
from vmware_nsx.plugins.nsx_v3 import availability_zones as nsx_az
|
||||||
from vmware_nsx.shell.admin.plugins.common import constants
|
from vmware_nsx.shell.admin.plugins.common import constants
|
||||||
from vmware_nsx.shell.admin.plugins.common import formatters
|
from vmware_nsx.shell.admin.plugins.common import formatters
|
||||||
from vmware_nsx.shell.admin.plugins.common import utils as admin_utils
|
from vmware_nsx.shell.admin.plugins.common import utils as admin_utils
|
||||||
|
129
vmware_nsx/tests/unit/nsx_p/test_availability_zones.py
Normal file
129
vmware_nsx/tests/unit/nsx_p/test_availability_zones.py
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
# Copyright 2018 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.
|
||||||
|
|
||||||
|
from oslo_config import cfg
|
||||||
|
from oslo_utils import uuidutils
|
||||||
|
|
||||||
|
from neutron.tests import base
|
||||||
|
|
||||||
|
from vmware_nsx.common import config
|
||||||
|
from vmware_nsx.common import exceptions as nsx_exc
|
||||||
|
from vmware_nsx.plugins.nsx_p import availability_zones as nsx_az
|
||||||
|
|
||||||
|
|
||||||
|
class NsxPAvailabilityZonesTestCase(base.BaseTestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(NsxPAvailabilityZonesTestCase, self).setUp()
|
||||||
|
self.az_name = "zone1"
|
||||||
|
self.group_name = "az:%s" % self.az_name
|
||||||
|
config.register_nsxv3_azs(cfg.CONF, [self.az_name])
|
||||||
|
self.global_md_proxy = uuidutils.generate_uuid()
|
||||||
|
cfg.CONF.set_override(
|
||||||
|
"metadata_proxy", self.global_md_proxy, group="nsx_p")
|
||||||
|
self.global_dhcp_profile = uuidutils.generate_uuid()
|
||||||
|
cfg.CONF.set_override(
|
||||||
|
"dhcp_profile", self.global_dhcp_profile, group="nsx_p")
|
||||||
|
cfg.CONF.set_override(
|
||||||
|
"native_metadata_route", "1.1.1.1", group="nsx_p")
|
||||||
|
cfg.CONF.set_override("dns_domain", "xxx.com", group="nsx_p")
|
||||||
|
cfg.CONF.set_override("nameservers", ["10.1.1.1"], group="nsx_p")
|
||||||
|
cfg.CONF.set_override(
|
||||||
|
"default_tier0_router", "uuidrtr1", group="nsx_p")
|
||||||
|
|
||||||
|
def _config_az(self,
|
||||||
|
metadata_proxy="metadata_proxy1",
|
||||||
|
dhcp_profile="dhcp_profile1",
|
||||||
|
native_metadata_route="2.2.2.2",
|
||||||
|
dns_domain="aaa.com",
|
||||||
|
nameservers=["20.1.1.1"],
|
||||||
|
default_overlay_tz='otz',
|
||||||
|
default_vlan_tz='vtz',
|
||||||
|
default_tier0_router="uuidrtr2"):
|
||||||
|
if metadata_proxy is not None:
|
||||||
|
cfg.CONF.set_override("metadata_proxy", metadata_proxy,
|
||||||
|
group=self.group_name)
|
||||||
|
if dhcp_profile is not None:
|
||||||
|
cfg.CONF.set_override("dhcp_profile", dhcp_profile,
|
||||||
|
group=self.group_name)
|
||||||
|
if native_metadata_route is not None:
|
||||||
|
cfg.CONF.set_override("native_metadata_route",
|
||||||
|
native_metadata_route,
|
||||||
|
group=self.group_name)
|
||||||
|
if dns_domain is not None:
|
||||||
|
cfg.CONF.set_override("dns_domain", dns_domain,
|
||||||
|
group=self.group_name)
|
||||||
|
if nameservers is not None:
|
||||||
|
cfg.CONF.set_override("nameservers", nameservers,
|
||||||
|
group=self.group_name)
|
||||||
|
if default_overlay_tz is not None:
|
||||||
|
cfg.CONF.set_override("default_overlay_tz", default_overlay_tz,
|
||||||
|
group=self.group_name)
|
||||||
|
if default_vlan_tz is not None:
|
||||||
|
cfg.CONF.set_override("default_vlan_tz", default_vlan_tz,
|
||||||
|
group=self.group_name)
|
||||||
|
if default_tier0_router is not None:
|
||||||
|
cfg.CONF.set_override("default_tier0_router", default_tier0_router,
|
||||||
|
group=self.group_name)
|
||||||
|
|
||||||
|
def test_simple_availability_zone(self):
|
||||||
|
self._config_az()
|
||||||
|
az = nsx_az.NsxPAvailabilityZone(self.az_name)
|
||||||
|
self.assertEqual(self.az_name, az.name)
|
||||||
|
self.assertEqual("metadata_proxy1", az.metadata_proxy)
|
||||||
|
self.assertEqual("dhcp_profile1", az.dhcp_profile)
|
||||||
|
self.assertEqual("2.2.2.2", az.native_metadata_route)
|
||||||
|
self.assertEqual("aaa.com", az.dns_domain)
|
||||||
|
self.assertEqual(["20.1.1.1"], az.nameservers)
|
||||||
|
self.assertEqual("otz", az.default_overlay_tz)
|
||||||
|
self.assertEqual("vtz", az.default_vlan_tz)
|
||||||
|
self.assertEqual("uuidrtr2", az.default_tier0_router)
|
||||||
|
|
||||||
|
def test_missing_group_section(self):
|
||||||
|
self.assertRaises(
|
||||||
|
nsx_exc.NsxInvalidConfiguration,
|
||||||
|
nsx_az.NsxPAvailabilityZone,
|
||||||
|
"doesnt_exist")
|
||||||
|
|
||||||
|
def test_availability_zone_missing_metadata_proxy(self):
|
||||||
|
# Mandatory parameter
|
||||||
|
self._config_az(metadata_proxy=None)
|
||||||
|
self.assertRaises(
|
||||||
|
nsx_exc.NsxInvalidConfiguration,
|
||||||
|
nsx_az.NsxPAvailabilityZone,
|
||||||
|
self.az_name)
|
||||||
|
|
||||||
|
def test_availability_zone_missing_dhcp_profile(self):
|
||||||
|
# Mandatory parameter
|
||||||
|
self._config_az(dhcp_profile=None)
|
||||||
|
self.assertRaises(
|
||||||
|
nsx_exc.NsxInvalidConfiguration,
|
||||||
|
nsx_az.NsxPAvailabilityZone,
|
||||||
|
self.az_name)
|
||||||
|
|
||||||
|
def test_availability_zone_missing_md_route(self):
|
||||||
|
self._config_az(native_metadata_route=None)
|
||||||
|
az = nsx_az.NsxPAvailabilityZone(self.az_name)
|
||||||
|
self.assertEqual("1.1.1.1", az.native_metadata_route)
|
||||||
|
|
||||||
|
def test_availability_zone_missing_dns_domain(self):
|
||||||
|
self._config_az(dns_domain=None)
|
||||||
|
az = nsx_az.NsxPAvailabilityZone(self.az_name)
|
||||||
|
self.assertEqual("xxx.com", az.dns_domain)
|
||||||
|
|
||||||
|
def test_availability_zone_missing_nameservers(self):
|
||||||
|
self._config_az(nameservers=None)
|
||||||
|
az = nsx_az.NsxPAvailabilityZone(self.az_name)
|
||||||
|
self.assertEqual(["10.1.1.1"], az.nameservers)
|
@ -44,6 +44,7 @@ from neutron_lib import exceptions as n_exc
|
|||||||
from neutron_lib.plugins import directory
|
from neutron_lib.plugins import directory
|
||||||
|
|
||||||
from vmware_nsx.common import utils
|
from vmware_nsx.common import utils
|
||||||
|
from vmware_nsx.plugins.nsx_p import plugin as nsx_plugin
|
||||||
from vmware_nsx.tests import unit as vmware
|
from vmware_nsx.tests import unit as vmware
|
||||||
from vmware_nsx.tests.unit.common_plugin import common_v3
|
from vmware_nsx.tests.unit.common_plugin import common_v3
|
||||||
from vmware_nsxlib.v3 import exceptions as nsxlib_exc
|
from vmware_nsxlib.v3 import exceptions as nsxlib_exc
|
||||||
@ -362,6 +363,17 @@ class NsxPTestNetworks(test_db_base_plugin_v2.TestNetworksV2,
|
|||||||
self.assertEqual('InvalidInput',
|
self.assertEqual('InvalidInput',
|
||||||
res['NeutronError']['type'])
|
res['NeutronError']['type'])
|
||||||
|
|
||||||
|
@mock.patch.object(nsx_plugin.NsxPolicyPlugin,
|
||||||
|
'validate_availability_zones')
|
||||||
|
def test_create_network_with_availability_zone(self, mock_validate_az):
|
||||||
|
name = 'net-with-zone'
|
||||||
|
zone = ['zone1']
|
||||||
|
|
||||||
|
mock_validate_az.return_value = None
|
||||||
|
with self.network(name=name, availability_zone_hints=zone) as net:
|
||||||
|
az_hints = net['network']['availability_zone_hints']
|
||||||
|
self.assertListEqual(az_hints, zone)
|
||||||
|
|
||||||
|
|
||||||
class NsxPTestPorts(test_db_base_plugin_v2.TestPortsV2,
|
class NsxPTestPorts(test_db_base_plugin_v2.TestPortsV2,
|
||||||
NsxPPluginTestCaseMixin):
|
NsxPPluginTestCaseMixin):
|
||||||
@ -1140,3 +1152,13 @@ class NsxPTestL3NatTestCase(NsxPTestL3NatTest,
|
|||||||
body = self._show('routers', r['router']['id'])
|
body = self._show('routers', r['router']['id'])
|
||||||
gw_info = body['router']['external_gateway_info']
|
gw_info = body['router']['external_gateway_info']
|
||||||
self.assertIsNone(gw_info)
|
self.assertIsNone(gw_info)
|
||||||
|
|
||||||
|
@mock.patch.object(nsx_plugin.NsxPolicyPlugin,
|
||||||
|
'validate_availability_zones')
|
||||||
|
def test_create_router_with_availability_zone(self, mock_validate_az):
|
||||||
|
name = 'rtr-with-zone'
|
||||||
|
zone = ['zone1']
|
||||||
|
mock_validate_az.return_value = None
|
||||||
|
with self.router(name=name, availability_zone_hints=zone) as rtr:
|
||||||
|
az_hints = rtr['router']['availability_zone_hints']
|
||||||
|
self.assertListEqual(zone, az_hints)
|
||||||
|
@ -31,7 +31,7 @@ from vmware_nsx.common import exceptions as nsx_exc
|
|||||||
from vmware_nsx.common import utils
|
from vmware_nsx.common import utils
|
||||||
from vmware_nsx.db import db as nsx_db
|
from vmware_nsx.db import db as nsx_db
|
||||||
from vmware_nsx.extensions import advancedserviceproviders as as_providers
|
from vmware_nsx.extensions import advancedserviceproviders as as_providers
|
||||||
from vmware_nsx.plugins.common_v3 import availability_zones as nsx_az
|
from vmware_nsx.plugins.nsx_v3 import availability_zones as nsx_az
|
||||||
from vmware_nsx.tests.unit.nsx_v3 import test_plugin
|
from vmware_nsx.tests.unit.nsx_v3 import test_plugin
|
||||||
from vmware_nsxlib.v3 import core_resources
|
from vmware_nsxlib.v3 import core_resources
|
||||||
from vmware_nsxlib.v3 import nsx_constants
|
from vmware_nsxlib.v3 import nsx_constants
|
||||||
|
Loading…
x
Reference in New Issue
Block a user