diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/AUTHORS vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/AUTHORS --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/AUTHORS 2019-01-31 14:40:20.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/AUTHORS 2019-03-14 02:01:09.000000000 +0000 @@ -529,6 +529,7 @@ gessau ghanshyam ghanshyam +ghanshyam gongysh gongysh gordon chung diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/ChangeLog vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/ChangeLog --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/ChangeLog 2019-01-31 14:40:19.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/ChangeLog 2019-03-14 02:01:09.000000000 +0000 @@ -1,8 +1,74 @@ CHANGES ======= +* NSX|P: Fix groups scope&tag condition +* Add tarballs to install on RHOSP director for NSX integration +* remove use of quota\_db +* NSX|V3: Simplify LBaaS implementation +* NSX|V+V3: Refresh octavia driver DB session +* Remove usage of tempest test\_l3\_agent\_scheduler +* Octavia: Add logging on driver exceptions +* NSX|P: Add scope to security group rules +* NSX|V: enable allow\_address\_pairs upon request +* bump neutron-lib to 1.25.0 +* remove external\_network\_bridge option +* NSX|V3: Fix octavia pool update operation +* Revert "NSX|V: Add lock before spoofguard IPs operations" +* NSX|V3: Change status code of SG failure +* NSX|V3+P: Respect default keyword for physical\_net +* NSX|P: Fix nsxlib api call +* NSX|P: Add TZ configs to devstack code +* skip DVR specific dynamic routing tests +* NSX|V admin utils: Find and fix spoofguard policies mismatches +* NSX|V: Add lock before spoofguard IPs operations +* NSX|V3+V: Fix octavia completor func +* NSX|P: Use the correct domain ID in SG rule creation +* NSX|P: Support vlan router interfaces +* NSX|V3: Add unit tests mocks to avoid loggin errors +* NSX|V3+V: Handle fwaas policy modification +* NSX|V3: FWaaS v2 without GW +* NSX|P: Add mocks to nsxlib in unit tests +* Upgrade appdirs lower constraints +* normalize and use ALIAS in supported\_extension\_aliases +* NSX|V+V3: Fix FWaaS RPC bindings +* use api def ALIAS in supported\_extension\_aliases +* Fix provider security group exception call +* NSX|V3: prevent user from changing the NSX internal SG +* NSX|V3+P: allow removing qos policy from a port +* NSX|V3+P: Fix subnet creation with dns domain +* NSX|V3+V: Handle fwaas policy removal +* NSX|V3: Fix LB advertisment to use admin context +* NSX|V+V3: Fix Octavia statuses update +* NSX|P: Handle ipv4 and ipv6 traffic in SG +* use neutron-lib trunk resource names +* NSX|V+V3: support octavia delete cascade +* NSX|P: Temporary worakround for delete SG rule +* NSX|V3+P: Create port bindings for dhcp ports +* NSX|V+V3: Use the right port device id for octavia vip +* [NSX|V3] Listener data might not have loadbalancer name +* NSX|V+V3: relax FWaaS validation +* NSXT LBaaS: Fail HM delete operation on exception +* bump neutron-lib to 1.23.0 +* NSX|P: Fix vlan transparent configuration +* NSX|V: FWaaS-V2 driver +* Octavia driver: various fixes +* DVS: Prevent from creating a vlan network with same tag and dvs +* Octavia error handling +* NSX|P: Enable mac change in switching profiles +* DVS: Disable port security and security group +* [NSX-V] Ensure binding exists before assigning lswitch\_id +* Remove FWaaS V1 code +* NSX|P: disable tier1 firewall before removing the service router +* NSX|V: Fix update section header +* NSX|V3: Validate FWaaS cidrs +* NSX|P: Add neutron object ID to NSX tags +* use payloads for PORT BEFORE\_DELETE callbacks * use payloads for all SUBNETPOOL\_ADDRESS\_SCOPE events +* Devstack: Delete old project before deciding how to get the new code +* NSX|P: Forbid cert operations without passthrough +* NSX|P: Allow only 1 router interface per network * stop using register\_dict\_extend\_funcs +* use payloads for SECURITY\_GROUP BEFORE\_CREATE events * NSX|V3: Init FWaaS before spawn * NSX|V3+P: reuse common devstack code * Remove ryu from requirements @@ -24,6 +90,7 @@ * Revert "NSX|P: No need to add resource name on update" * NSX|P network & port admin state support * NSX|P dns integration support +* use payloads for all SUBNETPOOL\_ADDRESS\_SCOPE events * NSXT: Remove redundant code, add logging * NSX|V3 Support expected codes for LB HM * NSX|P: No need to add resource name on update diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/debian/changelog vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/debian/changelog --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/debian/changelog 2019-02-04 20:13:38.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/debian/changelog 2019-03-14 03:22:06.000000000 +0000 @@ -1,8 +1,15 @@ -vmware-nsx (14.0.0~b1~git2019013109.17b5ad567-0ubuntu1~cloud0) bionic-stein; urgency=medium +vmware-nsx (14.0.0~b1~git2019031322.8426b63a4-0ubuntu1~cloud0) bionic-stein; urgency=medium - * New upstream release for the Ubuntu Cloud Archive. + * New update for the Ubuntu Cloud Archive. - -- Openstack Ubuntu Testing Bot Mon, 04 Feb 2019 20:13:38 +0000 + -- Openstack Ubuntu Testing Bot Thu, 14 Mar 2019 03:22:06 +0000 + +vmware-nsx (14.0.0~b1~git2019031322.8426b63a4-0ubuntu1) disco; urgency=medium + + * New upstream snapshot for OpenStack Stein. + * d/control: Align (Build-)Depends with upstream. + + -- Corey Bryant Wed, 13 Mar 2019 22:01:48 -0400 vmware-nsx (14.0.0~b1~git2019013109.17b5ad567-0ubuntu1) disco; urgency=medium diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/debian/control vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/debian/control --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/debian/control 2019-01-31 22:15:19.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/debian/control 2019-03-14 02:01:48.000000000 +0000 @@ -31,7 +31,7 @@ python3-neutron-dynamic-routing (>= 2:12.0.0), python3-neutron-fwaas (>= 1:13.0.0~b2-0ubuntu3~), python3-neutron-lbaas (>= 2:12.0.0), - python3-neutron-lib (>= 1.22.0), + python3-neutron-lib (>= 1.25.0), python3-neutron-vpnaas (>= 2:12.0.0), python3-openstackclient (>= 3.16.0), python3-os-testr, @@ -39,7 +39,7 @@ python3-oslo.concurrency (>= 3.26.0), python3-oslo.config (>= 1:5.2.0), python3-oslo.context (>= 1:2.19.2), - python3-oslo.db (>= 4.27.0), + python3-oslo.db (>= 4.37.0), python3-oslo.i18n (>= 3.15.3), python3-oslo.log (>= 3.36.0), python3-oslo.privsep (>= 1.29.0), @@ -91,14 +91,14 @@ python3-neutron-dynamic-routing (>= 2:12.0.0), python3-neutron-fwaas (>= 1:13.0.0~b2-0ubuntu3~), python3-neutron-lbaas (>= 2:12.0.0), - python3-neutron-lib (>= 1.22.0), + python3-neutron-lib (>= 1.25.0), python3-neutron-vpnaas (>= 2:12.0.0), python3-openstackclient (>= 3.16.0), python3-osc-lib (>= 1.10.0), python3-oslo.concurrency (>= 3.26.0), python3-oslo.config (>= 1:5.2.0), python3-oslo.context (>= 1:2.19.2), - python3-oslo.db (>= 4.27.0), + python3-oslo.db (>= 4.37.0), python3-oslo.i18n (>= 3.15.3), python3-oslo.log (>= 3.36.0), python3-oslo.serialization (>= 2.18.0), diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/devstack/lib/nsx_common vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/devstack/lib/nsx_common --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/devstack/lib/nsx_common 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/devstack/lib/nsx_common 2019-03-14 02:01:03.000000000 +0000 @@ -34,26 +34,26 @@ pkg_list="networking-l2gw networking-sfc neutron-lbaas neutron-fwaas neutron-dynamic-routing neutron-vpnaas octavia vmware-nsxlib" for pkg in `echo $pkg_list` do + pkg_renamed=`echo $pkg | sed 's/-/_/g'` + sudo rm -rf /usr/local/lib/python2.7/dist-packages/${pkg_renamed}* + sudo rm -rf /usr/local/lib/python3.5/dist-packages/${pkg_renamed}* + sudo rm -rf ./src/${pkg_renamed}* if is_plugin_enabled $pkg; then echo "Plugin $pkg enabled explicitly with enable_plugin" elif use_library_from_git $pkg; then echo "Project $pkg enabled explicitly from LIBS_FROM_GIT" else - pkg_renamed=`echo $pkg | sed 's/-/_/g'` - sudo rm -rf /usr/local/lib/python2.7/dist-packages/${pkg_renamed}* - sudo rm -rf /usr/local/lib/python3.5/dist-packages/${pkg_renamed}* - sudo rm -rf ./src/${pkg_renamed}* sudo pip install -e "git+https://git.openstack.org/openstack/${pkg}#egg=${pkg_renamed}" sudo chown -R ${USER}:${USER} src/${pkg} fi done + sudo rm -rf /usr/local/lib/python2.7/dist-packages/neutron + sudo rm -rf /usr/local/lib/python2.7/dist-packages/neutron.egg* + sudo rm -rf /usr/local/lib/python3.5/dist-packages/neutron + sudo rm -rf /usr/local/lib/python3.5/dist-packages/neutron.egg* if is_service_enabled neutron; then echo "service Neutron is enabled explicitly by devstack" else - sudo rm -rf /usr/local/lib/python2.7/dist-packages/neutron - sudo rm -rf /usr/local/lib/python2.7/dist-packages/neutron.egg* - sudo rm -rf /usr/local/lib/python3.5/dist-packages/neutron - sudo rm -rf /usr/local/lib/python3.5/dist-packages/neutron.egg* sudo pip install -e "git+https://git.openstack.org/openstack/neutron#egg=neutron" sudo chown -R ${USER}:${USER} src/neutron fi diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/devstack/lib/nsx_v3_p_common vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/devstack/lib/nsx_v3_p_common --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/devstack/lib/nsx_v3_p_common 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/devstack/lib/nsx_v3_p_common 2019-03-14 02:01:03.000000000 +0000 @@ -164,7 +164,6 @@ function neutron_plugin_configure_debug_command { sudo ovs-vsctl --no-wait -- --may-exist add-br $PUBLIC_BRIDGE - iniset $NEUTRON_TEST_CONFIG_FILE DEFAULT external_network_bridge "$PUBLIC_BRIDGE" } function neutron_plugin_configure_dhcp_agent { diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/devstack/lib/vmware_nsx vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/devstack/lib/vmware_nsx --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/devstack/lib/vmware_nsx 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/devstack/lib/vmware_nsx 2019-03-14 02:01:03.000000000 +0000 @@ -76,7 +76,6 @@ function neutron_plugin_configure_debug_command { sudo ovs-vsctl --no-wait -- --may-exist add-br $PUBLIC_BRIDGE - iniset $NEUTRON_TEST_CONFIG_FILE DEFAULT external_network_bridge "$PUBLIC_BRIDGE" } function neutron_plugin_configure_dhcp_agent { diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/devstack/lib/vmware_nsx_p vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/devstack/lib/vmware_nsx_p --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/devstack/lib/vmware_nsx_p 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/devstack/lib/vmware_nsx_p 2019-03-14 02:01:03.000000000 +0000 @@ -49,6 +49,8 @@ function nsxp_configure_service { install_neutron_projects + _nsxp_ini_set default_overlay_tz $DEFAULT_OVERLAY_TZ_UUID + _nsxp_ini_set default_vlan_tz $DEFAULT_VLAN_TZ_UUID if [[ "$DEFAULT_TIER0_ROUTER_UUID" != "" ]]; then _nsxp_ini_set default_tier0_router $DEFAULT_TIER0_ROUTER_UUID Q_L3_ENABLED=True @@ -71,7 +73,6 @@ _nsxp_ini_set native_metadata_route $NATIVE_METADATA_ROUTE _nsxp_ini_set dhcp_profile $DHCP_PROFILE_UUID _nsxp_ini_set metadata_proxy $METADATA_PROXY_UUID - _nsxp_ini_set dhcp_relay_service $DHCP_RELAY_SERVICE iniset $NEUTRON_CONF DEFAULT dhcp_agent_notification False _nsxp_ini_set nsx_api_user $NSX_USER diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/devstack/lib/vmware_nsx_tvd vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/devstack/lib/vmware_nsx_tvd --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/devstack/lib/vmware_nsx_tvd 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/devstack/lib/vmware_nsx_tvd 2019-03-14 02:01:03.000000000 +0000 @@ -131,7 +131,6 @@ function neutron_plugin_configure_debug_command { sudo ovs-vsctl --no-wait -- --may-exist add-br $PUBLIC_BRIDGE - iniset $NEUTRON_TEST_CONFIG_FILE DEFAULT external_network_bridge "$PUBLIC_BRIDGE" } function neutron_plugin_configure_dhcp_agent { diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/devstack/nsx_v/tvd_devstackgaterc vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/devstack/nsx_v/tvd_devstackgaterc --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/devstack/nsx_v/tvd_devstackgaterc 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/devstack/nsx_v/tvd_devstackgaterc 2019-03-14 02:01:03.000000000 +0000 @@ -34,7 +34,6 @@ r="$r|(?:tempest\.api\.network\.test_extensions\.ExtensionsTestJSON\..*)" r="$r|(?:tempest\.api\.network\.test_allowed_address_pair\.AllowedAddressPairTestJSON\.test_update.*)" r="$r|(?:tempest\.api\.network\.admin\.test_routers_dvr\.RoutersTestDVR\..*)" -r="$r|(?:tempest\.api\.network\.admin\.test_l3_agent_scheduler\.L3AgentSchedulerTestJSON\..*)" r="$r|(?:tempest\.api\.network\.admin.\test_metering_extensions.*)" # End list of exclusions. diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/doc/source/admin_util.rst vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/doc/source/admin_util.rst --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/doc/source/admin_util.rst 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/doc/source/admin_util.rst 2019-03-14 02:01:03.000000000 +0000 @@ -279,9 +279,10 @@ - Spoofguard support:: - nsxadmin -r spoofguard-policy -o list-mismatches nsxadmin -r spoofguard-policy -o clean --property policy-id=spoofguardpolicy-10 nsxadmin -r spoofguard-policy -o list --property reverse (entries defined on NSXv and not in Neutron) + nsxadmin -r spoofguard-policy -o list-mismatches (--property network=) - List spoofguard policies with mismatching ips or mac, globally or for a specific network + nsxadmin -r spoofguard-policy -o fix-mismatch --property port= - Fix the spoofgurad ips of a neutron port Metadata ~~~~~~~~ diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/doc/source/devstack.rst vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/doc/source/devstack.rst --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/doc/source/devstack.rst 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/doc/source/devstack.rst 2019-03-14 02:01:03.000000000 +0000 @@ -41,6 +41,25 @@ [NSX] qos_peak_bw_multiplier = +FWaaS (V2) Driver +~~~~~~~~~~~~~~~~~ + +Add neutron-fwaas repo as an external repository and configure following flags in ``local.conf``:: + + [[local|localrc]] + enable_service q-fwaas-v2 + Q_SERVICE_PLUGIN_CLASSES+=,firewall_v2 + + [[post-config|$NEUTRON_CONF]] + [fwaas] + enabled = True + driver = vmware_nsxv_edge_v2 + + [service_providers] + service_provider = FIREWALL_V2:fwaas_db:neutron_fwaas.services.firewall.service_drivers.agents.agents.FirewallAgentDriver:default + +Note - if devstack fails due to ml2_conf.ini being missing, please copy neutron/plugins/ml2/ml2_conf.ini.sample to /etc/neutron/plugins/ml2/ml2_conf.ini and stack again. + L2GW Driver ~~~~~~~~~~~ @@ -84,21 +103,6 @@ "delete_flow_classifier": "rule:admin_only", "get_flow_classifier": "rule:admin_only" -FWaaS (V1) Driver -~~~~~~~~~~~~~~~~~ - -Add neutron-fwaas repo as an external repository and configure following flags in ``local.conf``:: - - [[local|localrc]] - enable_plugin neutron-fwaas https://git.openstack.org/openstack/neutron-fwaas - ENABLED_SERVICES+=,q-fwaas-v1 - Q_SERVICE_PLUGIN_CLASSES=neutron_fwaas.services.firewall.fwaas_plugin.FirewallPlugin - - [[post-config|$NEUTRON_CONF]] - [fwaas] - enabled = True - driver = vmware_nsxv_edge - Neutron dynamic routing plugin (bgp) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -125,11 +129,12 @@ Octavia ~~~~~~~ -Add octavia repo as an external repository and configure following flags in ``local.conf``:: +Add octavia and python-octaviaclient repos as external repositories and configure following flags in ``local.conf``:: [[local|localrc]] OCTAVIA_NODE=api DISABLE_AMP_IMAGE_BUILD=True + LIBS_FROM_GIT=python-openstackclient,python-octaviaclient enable_plugin octavia https://git.openstack.org/openstack/octavia.git enable_plugin octavia-dashboard https://git.openstack.org/openstack/octavia-dashboard enable_service octavia @@ -197,30 +202,14 @@ ENABLED_SERVICES+=,q-trunk Q_SERVICE_PLUGIN_CLASSES+=,trunk -FWaaS (V1) Driver -~~~~~~~~~~~~~~~~~ - -Add neutron-fwaas repo as an external repository and configure following flags in ``local.conf``:: - - [[local|localrc]] - enable_plugin neutron-fwaas https://git.openstack.org/openstack/neutron-fwaas - ENABLED_SERVICES+=,q-fwaas - Q_SERVICE_PLUGIN_CLASSES+=,neutron_fwaas.services.firewall.fwaas_plugin.FirewallPlugin - - [[post-config|$NEUTRON_CONF]] - [fwaas] - enabled = True - driver = vmware_nsxv3_edge_v1 - - FWaaS (V2) Driver ~~~~~~~~~~~~~~~~~ Add neutron-fwaas repo as an external repository and configure following flags in ``local.conf``:: [[local|localrc]] - ENABLED_SERVICES+=,q-fwaas-v2 - Q_SERVICE_PLUGIN_CLASSES+=,neutron_fwaas.services.firewall.fwaas_plugin_v2.FirewallPluginV2 + enable_service q-fwaas-v2 + Q_SERVICE_PLUGIN_CLASSES+=,firewall_v2 [[post-config|$NEUTRON_CONF]] [fwaas] @@ -230,6 +219,8 @@ [service_providers] service_provider = FIREWALL_V2:fwaas_db:neutron_fwaas.services.firewall.service_drivers.agents.agents.FirewallAgentDriver:default +Note - if devstack fails due to ml2_conf.ini being missing, please copy neutron/plugins/ml2/ml2_conf.ini.sample to /etc/neutron/plugins/ml2/ml2_conf.ini and stack again. + LBaaS v2 Driver ~~~~~~~~~~~~~~~ @@ -263,11 +254,12 @@ Octavia ~~~~~~~ -Add octavia repo as an external repository and configure following flags in ``local.conf``:: +Add octavia and python-octaviaclient repos as external repositories and configure following flags in ``local.conf``:: [[local|localrc]] OCTAVIA_NODE=api DISABLE_AMP_IMAGE_BUILD=True + LIBS_FROM_GIT=python-openstackclient,python-octaviaclient enable_plugin octavia https://git.openstack.org/openstack/octavia.git enable_plugin octavia-dashboard https://git.openstack.org/openstack/octavia-dashboard enable_service octavia @@ -328,31 +320,13 @@ [DEFAULT] api_extensions_path = $DEST/neutron-lbaas/neutron_lbaas/extensions -FWaaS (V1) Driver -~~~~~~~~~~~~~~~~~ - -Add neutron-fwaas repo as an external repository and configure following flags in ``local.conf``:: - - [[local|localrc]] - enable_plugin neutron-fwaas https://git.openstack.org/openstack/neutron-fwaas - ENABLED_SERVICES+=,q-fwaas - Q_SERVICE_PLUGIN_CLASSES=vmware_nsxtvd_fwaasv1 - - [[post-config|$NEUTRON_CONF]] - [fwaas] - enabled = True - driver = vmware_nsxtvd_edge_v1 - [DEFAULT] - api_extensions_path = $DEST/neutron-fwaas/neutron_fwaas/extensions - - FWaaS (V2) Driver ~~~~~~~~~~~~~~~~~ Add neutron-fwaas repo as an external repository and configure following flags in ``local.conf``:: [[local|localrc]] - ENABLED_SERVICES+=,q-fwaas-v2 + enable_service q-fwaas-v2 Q_SERVICE_PLUGIN_CLASSES+=,vmware_nsxtvd_fwaasv2 [[post-config|$NEUTRON_CONF]] @@ -365,6 +339,8 @@ [service_providers] service_provider = FIREWALL_V2:fwaas_db:neutron_fwaas.services.firewall.service_drivers.agents.agents.FirewallAgentDriver:default +Note - if devstack fails due to ml2_conf.ini being missing, please copy neutron/plugins/ml2/ml2_conf.ini.sample to /etc/neutron/plugins/ml2/ml2_conf.ini and stack again. + L2GW Driver ~~~~~~~~~~~ diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/lower-constraints.txt vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/lower-constraints.txt --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/lower-constraints.txt 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/lower-constraints.txt 2019-03-14 02:01:03.000000000 +0000 @@ -1,7 +1,7 @@ alabaster==0.7.10 alembic==0.8.10 amqp==2.1.1 -appdirs==1.3.0 +appdirs==1.4.3 asn1crypto==0.23.0 Babel==2.3.4 beautifulsoup4==4.6.0 @@ -50,7 +50,7 @@ munch==2.1.0 netaddr==0.7.18 netifaces==0.10.4 -neutron-lib==1.22.0 +neutron-lib==1.25.0 octavia==3.0.0 openstackdocstheme==1.18.1 os-client-config==1.28.0 @@ -61,7 +61,7 @@ oslo.concurrency==3.26.0 oslo.config==5.2.0 oslo.context==2.19.2 -oslo.db==4.27.0 +oslo.db==4.37.0 oslo.i18n==3.15.3 oslo.log==3.36.0 oslo.messaging==5.29.0 diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/PKG-INFO vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/PKG-INFO --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/PKG-INFO 2019-01-31 14:40:20.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/PKG-INFO 2019-03-14 02:01:10.000000000 +0000 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: vmware-nsx -Version: 13.0.1.dev386 +Version: 13.0.1.dev506 Summary: VMware NSX library for OpenStack projects Home-page: https://launchpad.net/vmware-nsx Author: OpenStack diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/releasenotes/notes/nsxv3-lbaasv2-error-no-member-635ffc6308289aca.yaml vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/releasenotes/notes/nsxv3-lbaasv2-error-no-member-635ffc6308289aca.yaml --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/releasenotes/notes/nsxv3-lbaasv2-error-no-member-635ffc6308289aca.yaml 1970-01-01 00:00:00.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/releasenotes/notes/nsxv3-lbaasv2-error-no-member-635ffc6308289aca.yaml 2019-03-14 02:01:03.000000000 +0000 @@ -0,0 +1,7 @@ +--- +prelude: > + NSXv3 plugin will mark unused loadbalancers in ERROR state. +features: + - | + Upon upgrade to Stein, unused LBaaS-v2 loadbalancers, which have no members + will be marked in ERROR state, and cannot be used. diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/releasenotes/notes/nsxv-fwaas-v2-driver-0b78d5e2c4034b21.yaml vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/releasenotes/notes/nsxv-fwaas-v2-driver-0b78d5e2c4034b21.yaml --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/releasenotes/notes/nsxv-fwaas-v2-driver-0b78d5e2c4034b21.yaml 1970-01-01 00:00:00.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/releasenotes/notes/nsxv-fwaas-v2-driver-0b78d5e2c4034b21.yaml 2019-03-14 02:01:03.000000000 +0000 @@ -0,0 +1,6 @@ +--- +prelude: > + The NSX-V plugin can suppport FWaaS-V2 for setting router edges firewall rules. +features: + - | + The NSX-V plugin can suppport FWaaS-V2 for setting router edges firewall rules. diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/requirements.txt vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/requirements.txt --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/requirements.txt 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/requirements.txt 2019-03-14 02:01:03.000000000 +0000 @@ -10,13 +10,13 @@ SQLAlchemy!=1.1.5,!=1.1.6,!=1.1.7,!=1.1.8,>=1.2.0 # MIT six>=1.10.0 # MIT stevedore>=1.20.0 # Apache-2.0 -neutron-lib>=1.22.0 # Apache-2.0 +neutron-lib>=1.25.0 # Apache-2.0 osc-lib>=1.10.0 # Apache-2.0 python-openstackclient>=3.16.0 # Apache-2.0 oslo.concurrency>=3.26.0 # Apache-2.0 oslo.context>=2.19.2 # Apache-2.0 oslo.config>=5.2.0 # Apache-2.0 -oslo.db>=4.27.0 # Apache-2.0 +oslo.db>=4.37.0 # Apache-2.0 oslo.i18n>=3.15.3 # Apache-2.0 oslo.log>=3.36.0 # Apache-2.0 oslo.serialization!=2.19.1,>=2.18.0 # Apache-2.0 diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/rhosp13/instructions.rst vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/rhosp13/instructions.rst --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/rhosp13/instructions.rst 1970-01-01 00:00:00.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/rhosp13/instructions.rst 2019-03-14 02:01:03.000000000 +0000 @@ -0,0 +1,28 @@ +================================================== +Setting up RHOSP13 director for NSX-T integration +================================================== + +This guide provides instruction for updating the following components +on RHOSP director: + +- openstack-puppet +- openstack-tripleo-heat-templates + +The tarballs nsx-rhosp-openstack-puppet.tar.gz and +nsx-rhosp-openstack-tripleo-heat-templates.tar.gz contain updated versions +for these components. + +The following instructions provide detailed information regarding upgrading +software on the RHOSP director using these tarballs: + +1. Download tarball in RHOSP director’s home directory +2. Verify if an upgrade is needed: +$ test -e /usr/share/openstack-heat-tripleo-templates/docker/services/neutron-plugin-nsx.yaml && echo “OK” || echo “PATCH ME” + +3. Copy both tarballs in /usr/share/openstack +$ sudo cp ~/nsx-rhosp-*.tar.gz /usr/share/openstack + +4. Expand the archives +# cd /usr/share/openstack +# tar xzf nsx-rhosp-*.tar.gz + Binary files /tmp/tmpyKX0lt/ksYCwAnXuy/vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/rhosp13/nsx-openstack-puppet.tar.gz and /tmp/tmpyKX0lt/PPekBL9LK5/vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/rhosp13/nsx-openstack-puppet.tar.gz differ Binary files /tmp/tmpyKX0lt/ksYCwAnXuy/vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/rhosp13/nsx-openstack-tripleo-heat-templates.tar.gz and /tmp/tmpyKX0lt/PPekBL9LK5/vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/rhosp13/nsx-openstack-tripleo-heat-templates.tar.gz differ diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/setup.cfg vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/setup.cfg --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/setup.cfg 2019-01-31 14:40:20.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/setup.cfg 2019-03-14 02:01:10.000000000 +0000 @@ -37,17 +37,13 @@ vmware_dvs = vmware_nsx.plugin:NsxDvsPlugin vmware_nsxtvd = vmware_nsx.plugin:NsxTVDPlugin firewall_drivers = - vmware_nsxv_edge = vmware_nsx.services.fwaas.nsx_v.edge_fwaas_driver:EdgeFwaasDriver - vmware_nsxv3_edge = vmware_nsx.services.fwaas.nsx_v3.edge_fwaas_driver_v1:EdgeFwaasV3DriverV1 - vmware_nsxv3_edge_v1 = vmware_nsx.services.fwaas.nsx_v3.edge_fwaas_driver_v1:EdgeFwaasV3DriverV1 + vmware_nsxv_edge_v2 = vmware_nsx.services.fwaas.nsx_v.edge_fwaas_driver_v2:EdgeFwaasVDriverV2 vmware_nsxv3_edge_v2 = vmware_nsx.services.fwaas.nsx_v3.edge_fwaas_driver_v2:EdgeFwaasV3DriverV2 - vmware_nsxtvd_edge_v1 = vmware_nsx.services.fwaas.nsx_tv.edge_fwaas_driver_v1:EdgeFwaasTVDriverV1 vmware_nsxtvd_edge_v2 = vmware_nsx.services.fwaas.nsx_tv.edge_fwaas_driver_v2:EdgeFwaasTVDriverV2 neutron.service_plugins = vmware_nsxv_qos = vmware_nsx.services.qos.nsx_v.plugin:NsxVQosPlugin vmware_nsx_lbaasv2 = vmware_nsx.services.lbaas.nsx_plugin:LoadBalancerNSXPluginV2 vmware_nsxtvd_lbaasv2 = vmware_nsx.services.lbaas.nsx.plugin:LoadBalancerTVPluginV2 - vmware_nsxtvd_fwaasv1 = vmware_nsx.services.fwaas.nsx_tv.plugin_v1:FwaasTVPluginV1 vmware_nsxtvd_fwaasv2 = vmware_nsx.services.fwaas.nsx_tv.plugin_v2:FwaasTVPluginV2 vmware_nsxtvd_l2gw = vmware_nsx.services.l2gateway.nsx_tvd.plugin:L2GatewayPlugin vmware_nsxtvd_qos = vmware_nsx.services.qos.nsx_tvd.plugin:QoSPlugin diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/common/config.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/common/config.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/common/config.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/common/config.py 2019-03-14 02:01:03.000000000 +0000 @@ -808,6 +808,10 @@ default=False, help=_("Use subnet's exclusive router as a platform for " "LBaaS")), + cfg.BoolOpt('allow_multiple_ip_addresses', + default=False, + help=_("Allow associating multiple IPs to VMs " + "without spoofguard limitations")), ] # define the configuration of each NSX-V availability zone. diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/common/exceptions.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/common/exceptions.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/common/exceptions.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/common/exceptions.py 2019-03-14 02:01:03.000000000 +0000 @@ -23,6 +23,11 @@ message = _("An unexpected error occurred in the NSX Plugin: %(err_msg)s") +class NsxPluginTemporaryError(n_exc.ServiceUnavailable): + message = _("Temporary error occurred in the NSX Plugin: %(err_msg)s." + " Please try again later") + + class ClientCertificateException(NsxPluginException): message = _("Client certificate error: %(err_msg)s") diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/db/extended_security_group.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/db/extended_security_group.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/db/extended_security_group.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/db/extended_security_group.py 2019-03-14 02:01:03.000000000 +0000 @@ -91,7 +91,12 @@ } self._registry_notify(resources.SECURITY_GROUP, events.BEFORE_CREATE, - exc_cls=ext_sg.SecurityGroupConflict, **kwargs) + exc_cls=ext_sg.SecurityGroupConflict, + payload=events.DBEventPayload( + context, metadata={'is_default': default_sg}, + request_body=security_group, + desired_state=s)) + tenant_id = s['tenant_id'] if not default_sg: @@ -188,7 +193,7 @@ # security-group belongs to the same tenant this request is made for. sg = self.get_security_group(context, security_group_id) if not sg[provider_sg.PROVIDER]: - raise provider_sg.SecurityGroupNotProvider(id=sg) + raise provider_sg.SecurityGroupNotProvider(id=security_group_id) def _check_invalid_security_groups_specified(self, context, port, only_warn=False): diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/db/migration/alembic_migrations/versions/EXPAND_HEAD vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/db/migration/alembic_migrations/versions/EXPAND_HEAD --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/db/migration/alembic_migrations/versions/EXPAND_HEAD 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/db/migration/alembic_migrations/versions/EXPAND_HEAD 2019-03-14 02:01:03.000000000 +0000 @@ -1 +1 @@ -fc6308289aca +99bfcb6003c6 diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/db/migration/alembic_migrations/versions/stein/expand/99bfcb6003c6_lbaas_error_no_member.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/db/migration/alembic_migrations/versions/stein/expand/99bfcb6003c6_lbaas_error_no_member.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/db/migration/alembic_migrations/versions/stein/expand/99bfcb6003c6_lbaas_error_no_member.py 1970-01-01 00:00:00.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/db/migration/alembic_migrations/versions/stein/expand/99bfcb6003c6_lbaas_error_no_member.py 2019-03-14 02:01:03.000000000 +0000 @@ -0,0 +1,38 @@ +# Copyright 2019 VMware, Inc. +# +# 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. + +"""lbaas_error_no_member + +Revision ID: 99bfcb6003c6 +Revises: fc6308289aca +Create Date: 2019-03-07 11:27:00.000000 +""" + +from alembic import op + +from neutron.db import migration + +# revision identifiers, used by Alembic. +revision = '99bfcb6003c6' +down_revision = 'fc6308289aca' + + +def upgrade(): + if (migration.schema_has_table('nsxv3_lbaas_loadbalancers') and + migration.schema_has_table('lbaas_loadbalancers')): + # Mark as ERROR loadbalancers without nsx mapping + op.execute("UPDATE lbaas_loadbalancers " + "SET provisioning_status='ERROR' " + "where id not in (select loadbalancer_id from " + "nsxv3_lbaas_loadbalancers)") diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/db/nsxv_db.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/db/nsxv_db.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/db/nsxv_db.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/db/nsxv_db.py 2019-03-14 02:01:03.000000000 +0000 @@ -663,6 +663,17 @@ network_id) +def get_spoofguard_policy_network_id(session, policy_id): + try: + mapping = (session.query( + nsxv_models.NsxvSpoofGuardPolicyNetworkMapping). + filter_by(policy_id=policy_id).one()) + return mapping['network_id'] + except exc.NoResultFound: + LOG.debug("SpoofGuard Policy %s was not found in Neutron DB", + policy_id) + + def get_nsxv_spoofguard_policy_network_mappings(session, filters=None, like_filters=None): session = db_api.get_reader_session() diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/dhcp_meta/modes.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/dhcp_meta/modes.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/dhcp_meta/modes.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/dhcp_meta/modes.py 2019-03-14 02:01:03.000000000 +0000 @@ -18,6 +18,8 @@ import weakref from neutron_lib.agent import topics +from neutron_lib.api.definitions import agent as agent_apidef +from neutron_lib.api.definitions import dhcpagentscheduler from neutron_lib import constants as const from neutron_lib import rpc as n_rpc from oslo_concurrency import lockutils @@ -101,7 +103,7 @@ cfg.CONF.network_scheduler_driver ) self.supported_extension_aliases.extend( - ['agent', 'dhcp_agent_scheduler']) + [agent_apidef.ALIAS, dhcpagentscheduler.ALIAS]) def _setup_nsx_dhcp_metadata(self): self._check_services_requirements() @@ -126,7 +128,7 @@ LOG.warning('network_auto_schedule has been disabled') notifier = combined.DhcpAgentNotifyAPI(weakref.proxy(self), lsn_manager) - self.supported_extension_aliases.append(lsn.EXT_ALIAS) + self.supported_extension_aliases.append(lsn.ALIAS) # Add the capability to migrate dhcp and metadata services over self.migration_manager = ( migration.MigrationManager( @@ -134,7 +136,8 @@ return notifier def _init_extensions(self): - extensions = (lsn.EXT_ALIAS, 'agent', 'dhcp_agent_scheduler') + extensions = (lsn.ALIAS, agent_apidef.ALIAS, + dhcpagentscheduler.ALIAS) for ext in extensions: if ext in self.supported_extension_aliases: self.supported_extension_aliases.remove(ext) diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/extension_drivers/dns_integration.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/extension_drivers/dns_integration.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/extension_drivers/dns_integration.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/extension_drivers/dns_integration.py 2019-03-14 02:01:03.000000000 +0000 @@ -44,7 +44,7 @@ # TODO(asarfaty) use dns-domain/nameserver from network az instead of global class DNSExtensionDriver(driver_api.ExtensionDriver): - _supported_extension_alias = 'dns-integration' + _supported_extension_alias = dns.ALIAS @property def extension_alias(self): @@ -496,12 +496,13 @@ updated_ips) -def _delete_port_in_external_dns_service(resource, event, trigger, **kwargs): +def _delete_port_in_external_dns_service(resource, event, + trigger, payload=None): dns_driver = _get_dns_driver() if not dns_driver: return - context = kwargs['context'] - port_id = kwargs['port_id'] + context = payload.context + port_id = payload.resource_id dns_data_db = obj_reg.load_class('PortDNS').get_object( context, port_id=port_id) if not dns_data_db: diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/extensions/advancedserviceproviders.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/extensions/advancedserviceproviders.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/extensions/advancedserviceproviders.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/extensions/advancedserviceproviders.py 2019-03-14 02:01:03.000000000 +0000 @@ -16,7 +16,7 @@ # Attribute Map ADV_SERVICE_PROVIDERS = 'advanced_service_providers' - +ALIAS = 'advanced-service-providers' EXTENDED_ATTRIBUTES_2_0 = { 'subnets': { @@ -34,7 +34,7 @@ @classmethod def get_alias(cls): - return "advanced-service-providers" + return ALIAS @classmethod def get_description(cls): diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/extensions/api_replay.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/extensions/api_replay.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/extensions/api_replay.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/extensions/api_replay.py 2019-03-14 02:01:03.000000000 +0000 @@ -18,6 +18,9 @@ from neutron_lib.api import extensions from neutron_lib.db import constants as db_const + +ALIAS = 'api-replay' + # The attributes map is here for 2 reasons: # 1) allow posting id for the different objects we are importing # 2) make sure security-group named 'default' is also copied @@ -61,7 +64,7 @@ @classmethod def get_alias(cls): - return 'api-replay' + return ALIAS @classmethod def get_description(cls): diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/extensions/dhcp_mtu.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/extensions/dhcp_mtu.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/extensions/dhcp_mtu.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/extensions/dhcp_mtu.py 2019-03-14 02:01:03.000000000 +0000 @@ -16,6 +16,7 @@ from neutron_lib import constants DHCP_MTU = 'dhcp_mtu' +ALIAS = 'dhcp-mtu' EXTENDED_ATTRIBUTES_2_0 = { 'subnets': { DHCP_MTU: { @@ -37,7 +38,7 @@ @classmethod def get_alias(cls): - return "dhcp-mtu" + return ALIAS @classmethod def get_description(cls): diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/extensions/dns_search_domain.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/extensions/dns_search_domain.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/extensions/dns_search_domain.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/extensions/dns_search_domain.py 2019-03-14 02:01:03.000000000 +0000 @@ -66,6 +66,7 @@ validators.add_validator('dns_search_domain', _validate_dns_search_domain) +ALIAS = 'dns-search-domain' DNS_SEARCH_DOMAIN = 'dns_search_domain' EXTENDED_ATTRIBUTES_2_0 = { 'subnets': { @@ -87,7 +88,7 @@ @classmethod def get_alias(cls): - return "dns-search-domain" + return ALIAS @classmethod def get_description(cls): diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/extensions/edge_service_gateway_bgp_peer.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/extensions/edge_service_gateway_bgp_peer.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/extensions/edge_service_gateway_bgp_peer.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/extensions/edge_service_gateway_bgp_peer.py 2019-03-14 02:01:03.000000000 +0000 @@ -22,7 +22,7 @@ EDGE_SERVICE_GW = 'esg_id' EDGE_ID_MAX_LEN = 15 -ESG_BGP_PEER_EXT_ALIAS = 'edge-service-gateway-bgp-peer' +ALIAS = 'edge-service-gateway-bgp-peer' def _validate_edge_service_gw_id(esg_id, valid_values=None): @@ -87,7 +87,7 @@ @classmethod def get_alias(cls): - return ESG_BGP_PEER_EXT_ALIAS + return ALIAS @classmethod def get_description(cls): diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/extensions/housekeeper.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/extensions/housekeeper.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/extensions/housekeeper.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/extensions/housekeeper.py 2019-03-14 02:01:03.000000000 +0000 @@ -24,6 +24,7 @@ HOUSEKEEPER_RESOURCE_NAME = "housekeeper" HOUSEKEEPERS = "housekeepers" +ALIAS = 'housekeeper' # The housekeeper tasks table is read only RESOURCE_ATTRIBUTE_MAP = { @@ -53,7 +54,7 @@ @classmethod def get_alias(cls): - return HOUSEKEEPER_RESOURCE_NAME + return ALIAS @classmethod def get_description(cls): diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/extensions/lsn.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/extensions/lsn.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/extensions/lsn.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/extensions/lsn.py 2019-03-14 02:01:03.000000000 +0000 @@ -21,8 +21,8 @@ from neutron_lib.plugins import directory -EXT_ALIAS = 'lsn' -COLLECTION_NAME = "%ss" % EXT_ALIAS +ALIAS = 'lsn' +COLLECTION_NAME = "%ss" % ALIAS RESOURCE_ATTRIBUTE_MAP = { COLLECTION_NAME: { @@ -47,7 +47,7 @@ @classmethod def get_alias(cls): - return EXT_ALIAS + return ALIAS @classmethod def get_description(cls): @@ -62,7 +62,7 @@ """Returns Ext Resources.""" exts = [] plugin = directory.get_plugin() - resource_name = EXT_ALIAS + resource_name = ALIAS collection_name = resource_name.replace('_', '-') + "s" params = RESOURCE_ATTRIBUTE_MAP.get(COLLECTION_NAME, dict()) controller = base.create_resource(collection_name, diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/extensions/maclearning.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/extensions/maclearning.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/extensions/maclearning.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/extensions/maclearning.py 2019-03-14 02:01:03.000000000 +0000 @@ -17,6 +17,7 @@ from neutron_lib import constants +ALIAS = 'mac-learning' MAC_LEARNING = 'mac_learning_enabled' EXTENDED_ATTRIBUTES_2_0 = { 'ports': { @@ -37,7 +38,7 @@ @classmethod def get_alias(cls): - return "mac-learning" + return ALIAS @classmethod def get_description(cls): diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/extensions/networkgw.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/extensions/networkgw.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/extensions/networkgw.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/extensions/networkgw.py 2019-03-14 02:01:03.000000000 +0000 @@ -29,8 +29,8 @@ GATEWAY_RESOURCE_NAME = "network_gateway" DEVICE_RESOURCE_NAME = "gateway_device" # Use dash for alias and collection name -EXT_ALIAS = GATEWAY_RESOURCE_NAME.replace('_', '-') -NETWORK_GATEWAYS = "%ss" % EXT_ALIAS +ALIAS = GATEWAY_RESOURCE_NAME.replace('_', '-') +NETWORK_GATEWAYS = "%ss" % ALIAS GATEWAY_DEVICES = "%ss" % DEVICE_RESOURCE_NAME.replace('_', '-') DEVICE_ID_ATTR = 'id' IFACE_NAME_ATTR = 'interface_name' @@ -173,7 +173,7 @@ @classmethod def get_alias(cls): - return EXT_ALIAS + return ALIAS @classmethod def get_description(cls): diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/extensions/nsxpolicy.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/extensions/nsxpolicy.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/extensions/nsxpolicy.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/extensions/nsxpolicy.py 2019-03-14 02:01:03.000000000 +0000 @@ -23,7 +23,7 @@ POLICY_RESOURCE_NAME = "nsx_policy" # Use dash for alias and collection name -EXT_ALIAS = POLICY_RESOURCE_NAME.replace('_', '-') +ALIAS = POLICY_RESOURCE_NAME.replace('_', '-') NSX_POLICIES = "nsx_policies" # The nsx-policies table is read only @@ -48,7 +48,7 @@ @classmethod def get_alias(cls): - return EXT_ALIAS + return ALIAS @classmethod def get_description(cls): diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/extensions/projectpluginmap.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/extensions/projectpluginmap.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/extensions/projectpluginmap.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/extensions/projectpluginmap.py 2019-03-14 02:01:03.000000000 +0000 @@ -24,7 +24,7 @@ PROJECT_PLUGIN_RESOURCE_NAME = "project_plugin_map" # Use dash for alias and collection name -EXT_ALIAS = PROJECT_PLUGIN_RESOURCE_NAME.replace('_', '-') +ALIAS = PROJECT_PLUGIN_RESOURCE_NAME.replace('_', '-') PROJECT_PLUGINS = "project_plugin_maps" @@ -69,7 +69,7 @@ @classmethod def get_alias(cls): - return EXT_ALIAS + return ALIAS @classmethod def get_description(cls): diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/extensions/providersecuritygroup.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/extensions/providersecuritygroup.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/extensions/providersecuritygroup.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/extensions/providersecuritygroup.py 2019-03-14 02:01:03.000000000 +0000 @@ -20,6 +20,7 @@ from vmware_nsx._i18n import _ +ALIAS = 'provider-security-group' PROVIDER = 'provider' PROVIDER_SECURITYGROUPS = 'provider_security_groups' @@ -75,7 +76,7 @@ @classmethod def get_alias(cls): - return "provider-security-group" + return ALIAS @classmethod def get_description(cls): diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/extensions/qos_queue.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/extensions/qos_queue.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/extensions/qos_queue.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/extensions/qos_queue.py 2019-03-14 02:01:03.000000000 +0000 @@ -27,6 +27,7 @@ from vmware_nsx._i18n import _ +ALIAS = 'qos-queue' # For policy.json/Auth qos_queue_create = "create_qos_queue" qos_queue_delete = "delete_qos_queue" @@ -176,7 +177,7 @@ @classmethod def get_alias(cls): - return "qos-queue" + return ALIAS @classmethod def get_description(cls): diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/extensions/routersize.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/extensions/routersize.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/extensions/routersize.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/extensions/routersize.py 2019-03-14 02:01:03.000000000 +0000 @@ -16,6 +16,7 @@ from neutron_lib import constants +ALIAS = 'nsxv-router-size' ROUTER_SIZE = 'router_size' VALID_EDGE_SIZES = ['compact', 'large', 'xlarge', 'quadlarge'] EXTENDED_ATTRIBUTES_2_0 = { @@ -37,7 +38,7 @@ @classmethod def get_alias(cls): - return "nsxv-router-size" + return ALIAS @classmethod def get_description(cls): diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/extensions/routertype.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/extensions/routertype.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/extensions/routertype.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/extensions/routertype.py 2019-03-14 02:01:03.000000000 +0000 @@ -16,6 +16,7 @@ from neutron_lib import constants +ALIAS = 'nsxv-router-type' ROUTER_TYPE = 'router_type' VALID_TYPES = ['shared', 'exclusive'] EXTENDED_ATTRIBUTES_2_0 = { @@ -37,7 +38,7 @@ @classmethod def get_alias(cls): - return "nsxv-router-type" + return ALIAS @classmethod def get_description(cls): diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/extensions/secgroup_rule_local_ip_prefix.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/extensions/secgroup_rule_local_ip_prefix.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/extensions/secgroup_rule_local_ip_prefix.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/extensions/secgroup_rule_local_ip_prefix.py 2019-03-14 02:01:03.000000000 +0000 @@ -17,6 +17,8 @@ from neutron_lib.api import extensions from neutron_lib import constants + +ALIAS = 'secgroup-rule-local-ip-prefix' LOCAL_IP_PREFIX = 'local_ip_prefix' RESOURCE_ATTRIBUTE_MAP = { @@ -43,7 +45,7 @@ @classmethod def get_alias(cls): - return "secgroup-rule-local-ip-prefix" + return ALIAS @classmethod def get_description(cls): diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/extensions/securitygrouplogging.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/extensions/securitygrouplogging.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/extensions/securitygrouplogging.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/extensions/securitygrouplogging.py 2019-03-14 02:01:03.000000000 +0000 @@ -15,6 +15,7 @@ from neutron_lib.api import converters from neutron_lib.api import extensions +ALIAS = 'security-group-logging' LOGGING = 'logging' RESOURCE_ATTRIBUTE_MAP = { @@ -39,7 +40,7 @@ @classmethod def get_alias(cls): - return "security-group-logging" + return ALIAS @classmethod def get_description(cls): diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/extensions/securitygrouppolicy.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/extensions/securitygrouppolicy.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/extensions/securitygrouppolicy.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/extensions/securitygrouppolicy.py 2019-03-14 02:01:03.000000000 +0000 @@ -17,6 +17,8 @@ from vmware_nsx._i18n import _ + +ALIAS = 'security-group-policy' POLICY = 'policy' RESOURCE_ATTRIBUTE_MAP = { @@ -45,7 +47,7 @@ @classmethod def get_alias(cls): - return "security-group-policy" + return ALIAS @classmethod def get_description(cls): diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/extensions/vnicindex.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/extensions/vnicindex.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/extensions/vnicindex.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/extensions/vnicindex.py 2019-03-14 02:01:03.000000000 +0000 @@ -17,7 +17,7 @@ # Attribute Map VNIC_INDEX = 'vnic_index' - +ALIAS = 'vnic-index' EXTENDED_ATTRIBUTES_2_0 = { 'ports': { @@ -36,7 +36,7 @@ @classmethod def get_alias(cls): - return "vnic-index" + return ALIAS @classmethod def get_description(cls): diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/plugins/common_v3/plugin.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/plugins/common_v3/plugin.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/plugins/common_v3/plugin.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/plugins/common_v3/plugin.py 2019-03-14 02:01:03.000000000 +0000 @@ -23,6 +23,7 @@ import webob.exc from six import moves +from six import string_types from neutron.db import agentschedulers_db from neutron.db import allowedaddresspairs_db as addr_pair_db @@ -56,6 +57,7 @@ from neutron_lib.db import utils as db_utils from neutron_lib import exceptions as n_exc from neutron_lib.exceptions import allowedaddresspairs as addr_exc +from neutron_lib.exceptions import l3 as l3_exc from neutron_lib.exceptions import port_security as psec_exc from neutron_lib.plugins import utils as plugin_utils from neutron_lib.services.qos import constants as qos_consts @@ -164,6 +166,8 @@ webob.exc.HTTPBadRequest, nsx_exc.NsxENSPortSecurity: webob.exc.HTTPBadRequest, + nsx_exc.NsxPluginTemporaryError: + webob.exc.HTTPServiceUnavailable }) def _get_conf_attr(self, attr): @@ -682,7 +686,7 @@ is_new_compute = updated_compute and not orig_compute qos_policy_id = None - if validators.is_attr_set(updated_port.get(qos_consts.QOS_POLICY_ID)): + if qos_consts.QOS_POLICY_ID in updated_port: qos_policy_id = updated_port[qos_consts.QOS_POLICY_ID] elif original_port: # Look for the original QoS policy of this port @@ -761,6 +765,9 @@ net_data[pnet.SEGMENTATION_ID] = free_ids[0] return net_data[pnet.SEGMENTATION_ID] + def _default_physical_net(self, physical_net): + return physical_net is None or physical_net == 'default' + def _validate_provider_create(self, context, network_data, default_vlan_tz_uuid, default_overlay_tz_uuid, @@ -809,11 +816,11 @@ if not transparent_vlan: # Set VLAN id to 0 for flat networks vlan_id = '0' - if physical_net is None: + if self._default_physical_net(physical_net): physical_net = default_vlan_tz_uuid elif net_type == utils.NsxV3NetworkTypes.VLAN: # Use default VLAN transport zone if physical network not given - if physical_net is None: + if self._default_physical_net(physical_net): physical_net = default_vlan_tz_uuid if not transparent_vlan: @@ -1065,7 +1072,8 @@ def _get_update_router_gw_actions( self, org_tier0_uuid, orgaddr, org_enable_snat, - new_tier0_uuid, newaddr, new_enable_snat, lb_exist, fw_exist): + new_tier0_uuid, newaddr, new_enable_snat, + lb_exist, fw_exist, sr_currently_exists): """Return a dictionary of flags indicating which actions should be performed on this router GW update. """ @@ -1124,21 +1132,34 @@ actions['advertise_route_connected_flag'] = ( True if not new_enable_snat else False) - # the purpose of the two vars is to be able to differ between + # the purpose of this var is to be able to differ between # adding a gateway w/o snat and adding snat (when adding/removing gw - # the snat option is on by default. - - real_new_enable_snat = new_enable_snat and newaddr - real_org_enable_snat = org_enable_snat and orgaddr - - actions['add_service_router'] = ((real_new_enable_snat and - not real_org_enable_snat) or - (real_new_enable_snat and not - orgaddr and newaddr) - ) and not (fw_exist or lb_exist) - actions['remove_service_router'] = ((not real_new_enable_snat and - real_org_enable_snat) or ( - orgaddr and not newaddr)) and not (fw_exist or lb_exist) + # the snat option is on by default). + new_with_snat = True if (new_enable_snat and newaddr) else False + has_gw = True if newaddr else False + + if sr_currently_exists: + # currently there is a service router on the backend + actions['add_service_router'] = False + # Should remove the service router if the GW was removed, + # or no service needs it: SNAT, LBaaS or FWaaS + actions['remove_service_router'] = ( + not has_gw or not (fw_exist or lb_exist or new_with_snat)) + if actions['remove_service_router']: + LOG.info("Removing service router [has GW: %s, FW %s, LB %s, " + "SNAT %s]", + has_gw, fw_exist, lb_exist, new_with_snat) + else: + # currently there is no service router on the backend + actions['remove_service_router'] = False + # Should add service router if there is a GW + # and there is a service that needs it: SNAT, LB or FWaaS + actions['add_service_router'] = ( + has_gw is not None and (new_with_snat or fw_exist or lb_exist)) + if actions['add_service_router']: + LOG.info("Adding service router [has GW: %s, FW %s, LB %s, " + "SNAT %s]", + has_gw, fw_exist, lb_exist, new_with_snat) return actions @@ -1211,7 +1232,13 @@ network, resource_type='os-neutron-net-id', project_name=context.tenant_name) - dns_domain = network.get('dns_domain') + dns_domain = None + if network.get('dns_domain'): + net_dns = network['dns_domain'] + if isinstance(net_dns, string_types): + dns_domain = net_dns + elif hasattr(net_dns, "dns_domain"): + dns_domain = net_dns.dns_domain if not dns_domain or not validators.is_attr_set(dns_domain): dns_domain = az.dns_domain @@ -1277,6 +1304,8 @@ is_ens_tz_port = self._is_ens_tz_port(context, port_data) self._create_port_preprocess_security(context, port, port_data, neutron_port, is_ens_tz_port) + self._process_portbindings_create_and_update( + context, port_data, neutron_port) server_data = self._build_dhcp_server_config( context, network, subnet, neutron_port, az) @@ -2352,3 +2381,44 @@ 'os-neutron-net-id', network_id) if port_id: self.nsxlib.logical_port.delete(port_id) + + def _support_vlan_router_interfaces(self): + """Should be implemented by each plugin""" + pass + + def _validate_multiple_subnets_routers(self, context, router_id, net_id): + network = self.get_network(context, net_id) + net_type = network.get(pnet.NETWORK_TYPE) + if (net_type and + not self._support_vlan_router_interfaces() and + not self._is_overlay_network(context, net_id)): + err_msg = (_("Only overlay networks can be attached to a logical " + "router. Network %(net_id)s is a %(net_type)s based " + "network") % {'net_id': net_id, 'net_type': net_type}) + LOG.error(err_msg) + raise n_exc.InvalidInput(error_message=err_msg) + # Unable to attach a trunked network to a router interface + if cfg.CONF.vlan_transparent: + if network.get('vlan_transparent') is True: + err_msg = (_("Transparent VLAN networks cannot be attached to " + "a logical router.")) + LOG.error(err_msg) + raise n_exc.InvalidInput(error_message=err_msg) + port_filters = {'device_owner': [l3_db.DEVICE_OWNER_ROUTER_INTF], + 'network_id': [net_id]} + intf_ports = self.get_ports(context.elevated(), filters=port_filters) + router_ids = [port['device_id'] + for port in intf_ports if port['device_id']] + if len(router_ids) > 0: + err_msg = _("Only one subnet of network %(net_id)s can be " + "attached to router, one subnet is already attached " + "to router %(router_id)s") % { + 'net_id': net_id, + 'router_id': router_ids[0]} + LOG.error(err_msg) + if router_id in router_ids: + # attach to the same router again + raise n_exc.InvalidInput(error_message=err_msg) + else: + # attach to multiple routers + raise l3_exc.RouterInterfaceAttachmentConflict(reason=err_msg) diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/plugins/dvs/plugin.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/plugins/dvs/plugin.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/plugins/dvs/plugin.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/plugins/dvs/plugin.py 2019-03-14 02:01:03.000000000 +0000 @@ -14,10 +14,22 @@ # under the License. from neutron_lib.api.definitions import allowedaddresspairs as addr_apidef +from neutron_lib.api.definitions import external_net as enet_apidef +from neutron_lib.api.definitions import l3 as l3_apidef +from neutron_lib.api.definitions import multiprovidernet as mpnet_apidef 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 provider_net as pnet +from neutron_lib.api.definitions import vlantransparent as vlan_apidef +from neutron_lib.api import validators +from neutron_lib import constants +from neutron_lib.db import api as db_api +from neutron_lib.db import resource_extend from neutron_lib.db import utils as db_utils +from neutron_lib import exceptions as n_exc from neutron_lib.exceptions import allowedaddresspairs as addr_exc from neutron_lib.exceptions import port_security as psec_exc +from neutron_lib.plugins import utils from oslo_config import cfg from oslo_log import log as logging from oslo_utils import excutils @@ -38,16 +50,7 @@ from neutron.extensions import providernet from neutron.extensions import securitygroup as ext_sg from neutron.quota import resource_registry -from neutron_lib.api.definitions import multiprovidernet as mpnet_apidef -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 vlantransparent as vlan_apidef -from neutron_lib.api import validators -from neutron_lib import constants -from neutron_lib.db import api as db_api -from neutron_lib.db import resource_extend -from neutron_lib import exceptions as n_exc -from neutron_lib.plugins import utils + import vmware_nsx from vmware_nsx._i18n import _ @@ -80,16 +83,16 @@ dns_db.DNSDbMixin, vlan_ext_db.Vlantransparent_db_mixin): - supported_extension_aliases = ["allowed-address-pairs", - "binding", - "external-net", - "multi-provider", - "port-security", - "provider", + supported_extension_aliases = [addr_apidef.ALIAS, + pbin.ALIAS, + enet_apidef.ALIAS, + mpnet_apidef.ALIAS, + psec.ALIAS, + pnet.ALIAS, "quotas", - "router", + l3_apidef.ALIAS, "security-group", - "vlan-transparent"] + vlan_apidef.ALIAS] __native_bulk_support = True __native_pagination_support = True @@ -272,6 +275,14 @@ network_type_set = validators.is_attr_set(network_type) segmentation_id = net_data.get(pnet.SEGMENTATION_ID) segmentation_id_set = validators.is_attr_set(segmentation_id) + physical_network = net_data.get(pnet.PHYSICAL_NETWORK) + if network_type == 'vlan': + bindings = nsx_db.get_network_bindings_by_vlanid_and_physical_net( + context.session, segmentation_id, physical_network) + if bindings: + err_msg = _("Network with that dvs-id and vlan tag already " + "exists") + raise n_exc.InvalidInput(error_message=err_msg) if not context.is_admin: err_msg = _("Only an admin can create a DVS provider " "network") @@ -401,15 +412,19 @@ # ATTR_NOT_SPECIFIED is for the case where a port is created on a # shared network that is not owned by the tenant. port_data = port['port'] - + network_type = self._dvs_get_network(context, port['port'][ + 'network_id'])['provider:network_type'] with db_api.CONTEXT_WRITER.using(context): # First we allocate port in neutron database neutron_db = super(NsxDvsV2, self).create_port(context, port) self._extension_manager.process_create_port( context, port_data, neutron_db) - port_security = self._get_network_security_binding( - context, neutron_db['network_id']) - port_data[psec.PORTSECURITY] = port_security + if network_type and network_type == 'vlan': + port_data[psec.PORTSECURITY] = False + else: + port_security = self._get_network_security_binding( + context, neutron_db['network_id']) + port_data[psec.PORTSECURITY] = port_security self._process_port_port_security_create( context, port_data, neutron_db) # Update fields obtained from neutron db (eg: MAC address) @@ -417,12 +432,17 @@ has_ip = self._ip_on_port(neutron_db) # security group extension checks - if has_ip: - self._ensure_default_security_group_on_port(context, port) - elif validators.is_attr_set(port_data.get(ext_sg.SECURITYGROUPS)): - raise psec_exc.PortSecurityAndIPRequiredForSecurityGroups() - port_data[ext_sg.SECURITYGROUPS] = ( - self._get_security_groups_on_port(context, port)) + if network_type and network_type != 'vlan': + if has_ip: + self._ensure_default_security_group_on_port(context, port) + elif validators.is_attr_set(port_data.get( + ext_sg.SECURITYGROUPS)): + raise psec_exc.PortSecurityAndIPRequiredForSecurityGroups() + if network_type and network_type == 'vlan': + port_data[ext_sg.SECURITYGROUPS] = [] + else: + port_data[ext_sg.SECURITYGROUPS] = ( + self._get_security_groups_on_port(context, port)) self._process_port_create_security_group( context, port_data, port_data[ext_sg.SECURITYGROUPS]) self._process_portbindings_create_and_update(context, @@ -466,7 +486,6 @@ delete_addr_pairs = self._check_update_deletes_allowed_address_pairs( port) has_addr_pairs = self._check_update_has_allowed_address_pairs(port) - with db_api.CONTEXT_WRITER.using(context): ret_port = super(NsxDvsV2, self).update_port( context, id, port) @@ -477,8 +496,12 @@ port['port'].pop('fixed_ips', None) ret_port.update(port['port']) - # populate port_security setting - if psec.PORTSECURITY not in port['port']: + # populate port_security setting, ignoring vlan network ports. + network_type = self._dvs_get_network(context, + ret_port['network_id'])[ + 'provider:network_type'] + if (psec.PORTSECURITY not in port['port'] and network_type != + 'vlan'): ret_port[psec.PORTSECURITY] = self._get_port_security_binding( context, id) # validate port security and allowed address pairs @@ -500,8 +523,11 @@ context, ret_port, ret_port[addr_apidef.ADDRESS_PAIRS]) if psec.PORTSECURITY in port['port']: - self._process_port_port_security_update( - context, port['port'], ret_port) + if network_type != 'vlan': + self._process_port_port_security_update( + context, port['port'], ret_port) + else: + ret_port[psec.PORTSECURITY] = False self._process_vnic_type(context, port['port'], id) LOG.debug("Updating port: %s", port) self._extension_manager.process_update_port( diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/plugins/nsx/plugin.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/plugins/nsx/plugin.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/plugins/nsx/plugin.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/plugins/nsx/plugin.py 2019-03-14 02:01:03.000000000 +0000 @@ -43,7 +43,6 @@ from neutron.db.models import securitygroup as securitygroup_model # noqa from neutron.db import models_v2 from neutron.db import portsecurity_db -from neutron.db import quota_db # noqa from neutron.db import securitygroups_db from neutron.quota import resource_registry from neutron_lib.api import validators @@ -89,7 +88,7 @@ nsx_com_az.NSXAvailabilityZonesPluginCommon, projectpluginmap.ProjectPluginMapPluginBase): - supported_extension_aliases = ['project-plugin-map'] + supported_extension_aliases = [projectpluginmap.ALIAS] __native_bulk_support = True __native_pagination_support = True @@ -173,7 +172,7 @@ raise nsx_exc.NsxPluginException(err_msg=msg) for k, val in self.plugins.items(): - if "advanced-service-providers" in val.supported_extension_aliases: + if as_providers.ALIAS in val.supported_extension_aliases: self.as_providers[k] = val LOG.info("NSX-TVD plugin will use %s as the default plugin", self.default_plugin) @@ -297,15 +296,16 @@ resources.PORT, events.BEFORE_DELETE) @staticmethod - def _prevent_l3_port_delete_callback(resource, event, trigger, **kwargs): + def _prevent_l3_port_delete_callback(resource, event, + trigger, payload=None): """Register a callback to replace the default one This callback will prevent port deleting only if the port plugin is not NSX-T (in NSX-T plugin it was already handled) """ - context = kwargs['context'] - port_id = kwargs['port_id'] - port_check = kwargs['port_check'] + context = payload.context + port_id = payload.resource_id + port_check = payload.metadata['port_check'] l3plugin = directory.get_plugin(plugin_constants.L3) if l3plugin and port_check: # if not nsx-t - call super code diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/plugins/nsx_mh/plugin.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/plugins/nsx_mh/plugin.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/plugins/nsx_mh/plugin.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/plugins/nsx_mh/plugin.py 2019-03-14 02:01:03.000000000 +0000 @@ -16,17 +16,30 @@ import weakref from neutron_lib.api.definitions import allowedaddresspairs as addr_apidef +from neutron_lib.api.definitions import dvr as dvr_apidef from neutron_lib.api.definitions import external_net as extnet_apidef +from neutron_lib.api.definitions import extra_dhcp_opt as edo_ext +from neutron_lib.api.definitions import extraroute as xroute_apidef +from neutron_lib.api.definitions import l3 as l3_apidef +from neutron_lib.api.definitions import multiprovidernet as mpnet_apidef 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 provider_net as pnet from neutron_lib.api import faults from neutron_lib.api import validators from neutron_lib import constants from neutron_lib import context as q_context +from neutron_lib.db import api as db_api +from neutron_lib.db import model_query +from neutron_lib.db import resource_extend from neutron_lib.db import utils as db_utils from neutron_lib import exceptions as n_exc from neutron_lib.exceptions import allowedaddresspairs as addr_exc +from neutron_lib.exceptions import extraroute as xroute_exc from neutron_lib.exceptions import l3 as l3_exc +from neutron_lib.exceptions import multiprovidernet as mpnet_exc from neutron_lib.exceptions import port_security as psec_exc +from neutron_lib.plugins import utils from oslo_concurrency import lockutils from oslo_config import cfg from oslo_db import exception as db_exc @@ -55,22 +68,10 @@ from neutron.db import models_v2 from neutron.db import portbindings_db from neutron.db import portsecurity_db -from neutron.db import quota_db # noqa from neutron.db import securitygroups_db from neutron.extensions import providernet from neutron.extensions import securitygroup as ext_sg from neutron.quota import resource_registry -from neutron_lib.api.definitions import extra_dhcp_opt as edo_ext -from neutron_lib.api.definitions import extraroute as xroute_apidef -from neutron_lib.api.definitions import multiprovidernet as mpnet_apidef -from neutron_lib.api.definitions import portbindings as pbin -from neutron_lib.api.definitions import provider_net as pnet -from neutron_lib.db import api as db_api -from neutron_lib.db import model_query -from neutron_lib.db import resource_extend -from neutron_lib.exceptions import extraroute as xroute_exc -from neutron_lib.exceptions import multiprovidernet as mpnet_exc -from neutron_lib.plugins import utils import vmware_nsx from vmware_nsx._i18n import _ @@ -121,21 +122,21 @@ securitygroups_db.SecurityGroupDbMixin, dns_db.DNSDbMixin): - supported_extension_aliases = ["allowed-address-pairs", - "binding", - "dvr", + supported_extension_aliases = [addr_apidef.ALIAS, + pbin.ALIAS, + dvr_apidef.ALIAS, "ext-gw-mode", xroute_apidef.ALIAS, - "mac-learning", - "multi-provider", - "network-gateway", - "port-security", - "provider", - "qos-queue", + mac_ext.ALIAS, + mpnet_apidef.ALIAS, + networkgw.ALIAS, + psec.ALIAS, + pnet.ALIAS, + qos.ALIAS, "quotas", - "external-net", - "extra_dhcp_opt", - "router", + extnet_apidef.ALIAS, + edo_ext.ALIAS, + l3_apidef.ALIAS, "security-group", constants.SUBNET_ALLOCATION_EXT_ALIAS] diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/plugins/nsx_p/plugin.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/plugins/nsx_p/plugin.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/plugins/nsx_p/plugin.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/plugins/nsx_p/plugin.py 2019-03-14 02:01:03.000000000 +0000 @@ -13,6 +13,8 @@ # License for the specific language governing permissions and limitations # under the License. +import time + import netaddr from oslo_config import cfg @@ -28,12 +30,22 @@ from neutron.extensions import providernet from neutron.extensions import securitygroup as ext_sg from neutron.quota import resource_registry +from neutron_lib.api.definitions import address_scope +from neutron_lib.api.definitions import agent as agent_apidef from neutron_lib.api.definitions import allowedaddresspairs as addr_apidef +from neutron_lib.api.definitions import availability_zone as az_apidef +from neutron_lib.api.definitions import dhcpagentscheduler from neutron_lib.api.definitions import external_net from neutron_lib.api.definitions import extra_dhcp_opt as ext_edo +from neutron_lib.api.definitions import extraroute from neutron_lib.api.definitions import l3 as l3_apidef +from neutron_lib.api.definitions import network_availability_zone from neutron_lib.api.definitions import port_security as psec +from neutron_lib.api.definitions import portbindings as pbin_apidef +from neutron_lib.api.definitions import provider_net as pnet_apidef +from neutron_lib.api.definitions import router_availability_zone from neutron_lib.api.definitions import vlantransparent as vlan_apidef +from neutron_lib.api import extensions from neutron_lib.api import validators from neutron_lib.callbacks import events from neutron_lib.callbacks import registry @@ -87,6 +99,9 @@ NSX_P_REGULAR_SECTION_CATEGORY = policy_constants.CATEGORY_ENVIRONMENT NSX_P_PROVIDER_SECTION_CATEGORY = policy_constants.CATEGORY_INFRASTRUCTURE +NSX_P_IPV4_SERVICE_ID = 'os-ipv4-all' +NSX_P_IPV6_SERVICE_ID = 'os-ipv6-all' + SPOOFGUARD_PROFILE_UUID = 'neutron-spoofguard-profile' NO_SPOOFGUARD_PROFILE_UUID = policy_defs.SpoofguardProfileDef.DEFAULT_PROFILE MAC_DISCOVERY_PROFILE_UUID = 'neutron-mac-discovery-profile' @@ -106,30 +121,29 @@ __native_pagination_support = True __native_sorting_support = True - supported_extension_aliases = ["allowed-address-pairs", - "address-scope", + supported_extension_aliases = [addr_apidef.ALIAS, + address_scope.ALIAS, "quotas", - "binding", - "extra_dhcp_opt", - "agent", - "dhcp_agent_scheduler", + pbin_apidef.ALIAS, + ext_edo.ALIAS, + agent_apidef.ALIAS, + dhcpagentscheduler.ALIAS, "ext-gw-mode", "security-group", - "secgroup-rule-local-ip-prefix", - "port-security", - "provider", - "external-net", - "extraroute", - "router", - "availability_zone", - "network_availability_zone", - "router_availability_zone", + sg_prefix.ALIAS, + psec.ALIAS, + pnet_apidef.ALIAS, + external_net.ALIAS, + extraroute.ALIAS, + l3_apidef.ALIAS, + az_apidef.ALIAS, + network_availability_zone.ALIAS, + router_availability_zone.ALIAS, "subnet_allocation", - "security-group-logging", - "provider-security-group", + sg_logging.ALIAS, + provider_sg.ALIAS, "port-security-groups-filtering", - "vlan-transparent", - 'mac-learning'] + mac_ext.ALIAS] @resource_registry.tracked_resources( network=models_v2.Network, @@ -170,10 +184,16 @@ self.supported_extension_aliases.extend( self._extension_manager.extension_aliases()) + # Support transparent VLANS only if the global configuration flag + # vlan_transparent is True + if cfg.CONF.vlan_transparent: + self.supported_extension_aliases.append(vlan_apidef.ALIAS) + nsxlib_utils.set_inject_headers_callback(v3_utils.inject_headers) self._validate_nsx_policy_version() self._init_default_config() + self._prepare_common_services() self._prepare_default_rules() self._init_segment_profiles() self._init_dhcp_metadata() @@ -263,6 +283,7 @@ self.nsxpolicy.mac_discovery_profile.create_or_overwrite( MAC_DISCOVERY_PROFILE_UUID, profile_id=MAC_DISCOVERY_PROFILE_UUID, + mac_change_enabled=True, mac_learning_enabled=True, tags=self.nsxpolicy.build_v3_api_version_tag()) @@ -326,8 +347,9 @@ # update the network name to indicate the neutron id too. net_name = utils.get_name_and_uuid(net_data['name'] or 'network', net_data['id']) - tags = self.nsxpolicy.build_v3_api_version_project_tag( - context.tenant_name) + tags = self.nsxpolicy.build_v3_tags_payload( + net_data, resource_type='os-neutron-net-id', + project_name=context.tenant_name) admin_state = net_data.get('admin_state_up', True) LOG.debug('create_network: %(net_name)s, %(physical_net)s, ' @@ -359,7 +381,7 @@ net_data['id'], admin_state) def _tier0_validator(self, tier0_uuid): - # Fail of the tier0 uuid was not found on the BSX + # Fail if the tier0 uuid was not found on the NSX self.nsxpolicy.tier0.get(tier0_uuid) def _get_nsx_net_tz_id(self, nsx_net): @@ -400,7 +422,10 @@ az = self._validate_obj_az_on_creation(context, net_data, 'network') self._ensure_default_security_group(context, tenant_id) - vlt = vlan_apidef.get_vlan_transparent(net_data) + + vlt = False + if extensions.is_extension_supported(self, 'vlan-transparent'): + vlt = vlan_apidef.get_vlan_transparent(net_data) self._validate_create_network(context, net_data) self._assert_on_resource_admin_state_down(net_data) @@ -423,6 +448,15 @@ self.nsxpolicy.transport_zone, self.nsxpolicy.segment, transparent_vlan=vlt) + + # Vlan range is only supported with vlan transport zone + if (vlt and + provider_data['net_type'] != utils.NsxV3NetworkTypes.VLAN and + provider_data['net_type'] != utils.NsxV3NetworkTypes.FLAT): + err_msg = (_('vlan_transparent network can be configured only ' + 'with network-type:vlan or flat')) + raise n_exc.InvalidInput(error_message=err_msg) + if (provider_data['is_provider_net'] and provider_data['net_type'] == utils.NsxV3NetworkTypes.NSX_NETWORK): @@ -436,9 +470,10 @@ created_net = super(NsxPolicyPlugin, self).create_network( context, network) net_id = created_net['id'] - super(NsxPolicyPlugin, self).update_network( - context, net_id, - {'network': {'vlan_transparent': vlt}}) + if extensions.is_extension_supported(self, 'vlan-transparent'): + super(NsxPolicyPlugin, self).update_network( + context, net_id, + {'network': {'vlan_transparent': vlt}}) self._extension_manager.process_create_network( context, net_data, created_net) if psec.PORTSECURITY not in net_data: @@ -666,8 +701,15 @@ attachment_type = policy_constants.ATTACHMENT_INDEPENDENT tags = self._build_port_tags(port_data) - tags.extend(self.nsxpolicy.build_v3_api_version_project_tag( - context.tenant_name, project_id=port_data.get('tenant_id'))) + if device_owner == const.DEVICE_OWNER_DHCP: + tag_resource_type = 'os-neutron-dport-id' + elif device_owner == l3_db.DEVICE_OWNER_ROUTER_INTF: + tag_resource_type = 'os-neutron-rport-id' + else: + tag_resource_type = 'os-neutron-port-id' + tags.extend(self.nsxpolicy.build_v3_tags_payload( + port_data, resource_type=tag_resource_type, + project_name=context.tenant_name)) if self._is_excluded_port(device_owner, is_psec_on): tags.append({'scope': security.PORT_SG_SCOPE, @@ -1092,10 +1134,20 @@ return self.nsxpolicy.tier0.get_edge_cluster_path( tier0_uuid) - def create_service_router(self, context, router_id): + def verify_sr_at_backend(self, router_id): + """Check if the backend Tier1 has a service router or not""" + if self.nsxpolicy.tier1.get_edge_cluster_path(router_id): + return True + + def create_service_router(self, context, router_id, router=None): """Create a service router and enable standby relocation""" - router = self._get_router(context, router_id) + if not router: + router = self._get_router(context, router_id) tier0_uuid = self._get_tier0_uuid_by_router(context, router) + if not tier0_uuid: + err_msg = (_("Cannot create service router for %s without a " + "gateway") % router_id) + raise n_exc.InvalidInput(error_message=err_msg) edge_cluster_path = self._get_edge_cluster_path( tier0_uuid, router) if edge_cluster_path: @@ -1124,6 +1176,9 @@ LOG.warning("Failed to disable standby relocation for router " "%s: %s", router_id, ex) + # remove the edge firewall + self.nsxpolicy.tier1.update(router_id, disable_firewall=True) + # remove the edge cluster from the tier1 router self.nsxpolicy.tier1.remove_edge_cluster(router_id) @@ -1153,13 +1208,16 @@ router['id']) router_subnets = self._find_router_subnets( context.elevated(), router_id) + sr_currently_exists = self.verify_sr_at_backend(router_id) + lb_exist = False + fw_exist = False actions = self._get_update_router_gw_actions( org_tier0_uuid, orgaddr, org_enable_snat, - new_tier0_uuid, newaddr, new_enable_snat, fw_exist=False, - lb_exist=False) + new_tier0_uuid, newaddr, new_enable_snat, + lb_exist, fw_exist, sr_currently_exists) if actions['add_service_router']: - self.create_service_router(context, router_id) + self.create_service_router(context, router_id, router=router) if actions['remove_snat_rules']: for subnet in router_subnets: @@ -1225,8 +1283,9 @@ router_name = utils.get_name_and_uuid(router['name'] or 'router', router['id']) - tags = self.nsxpolicy.build_v3_api_version_project_tag( - context.tenant_name, project_id=r.get('tenant_id')) + tags = self.nsxpolicy.build_v3_tags_payload( + r, resource_type='os-neutron-router-id', + project_name=context.tenant_name) try: self.nsxpolicy.tier1.create_or_overwrite( router_name, router['id'], @@ -1350,23 +1409,39 @@ 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) + overlay_net = self._is_overlay_network(context, network_id) router_db = self._get_router(context, router_id) gw_network_id = (router_db.gw_port.network_id if router_db.gw_port else None) - # A router interface cannot be an external network - if extern_net: - msg = _("An external network cannot be attached as " - "an interface to a router") - raise n_exc.InvalidInput(error_message=msg) - - # Update the interface of the neutron router - info = super(NsxPolicyPlugin, self).add_router_interface( - context, router_id, interface_info) + with locking.LockManager.get_lock(str(network_id)): + # disallow more than one subnets belong to same network being + # attached to routers + self._validate_multiple_subnets_routers( + context, router_id, network_id) + + # A router interface cannot be an external network + if extern_net: + msg = _("An external network cannot be attached as " + "an interface to a router") + raise n_exc.InvalidInput(error_message=msg) + + # Non overlay networks should be configured with a centralized + # router, which is allowed only if GW network is attached + if not overlay_net and not gw_network_id: + msg = _("A router attached to a VLAN backed network " + "must have an external network assigned") + raise n_exc.InvalidInput(error_message=msg) - self._validate_interface_address_scope(context, router_db, info) + # Update the interface of the neutron router + info = super(NsxPolicyPlugin, self).add_router_interface( + context, router_id, interface_info) try: + # If it is a no-snat router, interface address scope must be the + # same as the gateways + self._validate_interface_address_scope(context, router_db, info) + # Check GW & subnets TZ subnets = self._find_router_subnets(context.elevated(), router_id) tier0_uuid = self._get_tier0_uuid_by_router( @@ -1375,22 +1450,31 @@ # and not all self._validate_router_tz(context.elevated(), tier0_uuid, subnets) - #TODO(asarfaty): adding the segment name even though it was not - # changed because otherwise the NSX will set it to default. - # This code should be removed once NSX supports it. - net = self._get_network(context, network_id) - net_name = utils.get_name_and_uuid( - net['name'] or 'network', network_id) segment_id = self._get_network_nsx_segment_id(context, network_id) subnet = self.get_subnet(context, info['subnet_ids'][0]) cidr_prefix = int(subnet['cidr'].split('/')[1]) - gw_addr = "%s/%s" % (subnet['gateway_ip'], cidr_prefix) - pol_subnet = policy_defs.Subnet( - gateway_address=gw_addr) - self.nsxpolicy.segment.update(segment_id, - name=net_name, - tier1_id=router_id, - subnets=[pol_subnet]) + if overlay_net: + # overlay interface + #TODO(asarfaty): adding the segment name even though it was not + # changed because otherwise the NSX will set it to default. + # This code should be removed once NSX supports it. + net = self._get_network(context, network_id) + net_name = utils.get_name_and_uuid( + net['name'] or 'network', network_id) + gw_addr = "%s/%s" % (subnet['gateway_ip'], cidr_prefix) + pol_subnet = policy_defs.Subnet(gateway_address=gw_addr) + self.nsxpolicy.segment.update(segment_id, + name=net_name, + tier1_id=router_id, + subnets=[pol_subnet]) + else: + # Vlan interface + pol_subnet = policy_defs.InterfaceSubnet( + ip_addresses=[subnet['gateway_ip']], + prefix_len=cidr_prefix) + self.nsxpolicy.tier1.add_segment_interface( + router_id, segment_id, + segment_id, [pol_subnet]) # add the SNAT/NO_DNAT rules for this interface if router_db.enable_snat and gw_network_id: @@ -1431,11 +1515,18 @@ info = super(NsxPolicyPlugin, self).remove_router_interface( context, router_id, interface_info) network_id = info['network_id'] + overlay_net = self._is_overlay_network(context, network_id) + segment_id = self._get_network_nsx_segment_id(context, network_id) - # Remove the tier1 router from this segment on the nSX try: - segment_id = self._get_network_nsx_segment_id(context, network_id) - self.nsxpolicy.segment.remove_connectivity_and_subnets(segment_id) + if overlay_net: + # Remove the tier1 router from this segment on the NSX + self.nsxpolicy.segment.remove_connectivity_and_subnets( + segment_id) + else: + # VLAN interface + self.nsxpolicy.tier1.remove_segment_interface( + router_id, segment_id) # try to delete the SNAT/NO_DNAT rules of this subnet router_db = self._get_router(context, router_id) @@ -1448,6 +1539,7 @@ LOG.error('Failed to remove router interface for network ' '%(id)s on NSX backend. Exception: %(e)s', {'id': network_id, 'e': ex}) + return info def _get_fip_snat_rule_id(self, fip_id): @@ -1556,6 +1648,23 @@ super(NsxPolicyPlugin, self).disassociate_floatingips( context, port_id, do_notify=False) + def _prepare_common_services(self): + """Prepare services for ipv4 and ipv6 only traffic""" + + #NOTE: These services are overriden on each init. We never clean + # them up. + self.nsxpolicy.ip_protocol_service.create_or_overwrite( + NSX_P_IPV4_SERVICE_ID, + service_id=NSX_P_IPV4_SERVICE_ID, + description='all ipv4 traffic', + protocol_number=4) + + self.nsxpolicy.ip_protocol_service.create_or_overwrite( + NSX_P_IPV6_SERVICE_ID, + service_id=NSX_P_IPV6_SERVICE_ID, + description='all ipv6 traffic', + protocol_number=41) + def _prepare_default_rules(self): """Create a default group & communication map in the default domain""" # Run this code only on one worker at the time @@ -1574,7 +1683,7 @@ # Create the default group membership criteria to match all neutron # ports by scope & tag - scope_and_tag = "%s:" % (NSX_P_SECURITY_GROUP_TAG) + scope_and_tag = "%s|" % (NSX_P_SECURITY_GROUP_TAG) conditions = [self.nsxpolicy.group.build_condition( cond_val=scope_and_tag, cond_key=policy_constants.CONDITION_KEY_TAG, @@ -1596,6 +1705,8 @@ # create default section and rules logged = cfg.CONF.nsx_p.log_security_groups_blocked_traffic + scope = [self.nsxpolicy.group.get_path( + NSX_P_GLOBAL_DOMAIN_ID, NSX_P_DEFAULT_GROUP)] rule_id = 1 dhcp_client_rule = self.nsxpolicy.comm_map.build_entry( 'DHCP Reply', NSX_P_GLOBAL_DOMAIN_ID, @@ -1603,8 +1714,7 @@ rule_id, sequence_number=rule_id, service_ids=['DHCP-Client'], action=policy_constants.ACTION_ALLOW, - source_groups=None, - dest_groups=[NSX_P_DEFAULT_GROUP], + scope=scope, direction=nsxlib_consts.IN, logged=logged) rule_id += 1 @@ -1614,8 +1724,7 @@ rule_id, sequence_number=rule_id, service_ids=['DHCP-Server'], action=policy_constants.ACTION_ALLOW, - source_groups=[NSX_P_DEFAULT_GROUP], - dest_groups=None, + scope=scope, direction=nsxlib_consts.OUT, logged=logged) rule_id += 1 @@ -1624,8 +1733,7 @@ NSX_P_DEFAULT_SECTION, rule_id, sequence_number=rule_id, service_ids=None, action=policy_constants.ACTION_DENY, - source_groups=None, - dest_groups=[NSX_P_DEFAULT_GROUP], + scope=scope, direction=nsxlib_consts.IN_OUT, logged=logged) rules = [dhcp_client_rule, dhcp_server_rule, block_rule] @@ -1650,12 +1758,13 @@ Both will have the security group id as their NSX id. """ sg_id = secgroup['id'] - tags = self.nsxpolicy.build_v3_api_version_project_tag( - context.tenant_name, project_id=secgroup.get('tenant_id')) + tags = self.nsxpolicy.build_v3_tags_payload( + secgroup, resource_type='os-neutron-secg-id', + project_name=secgroup.get('tenant_id')) nsx_name = utils.get_name_and_uuid(secgroup['name'] or 'securitygroup', sg_id) # Create the groups membership criteria for ports by scope & tag - scope_and_tag = "%s:%s" % (NSX_P_SECURITY_GROUP_TAG, sg_id) + scope_and_tag = "%s|%s" % (NSX_P_SECURITY_GROUP_TAG, sg_id) condition = self.nsxpolicy.group.build_condition( cond_val=scope_and_tag, cond_key=policy_constants.CONDITION_KEY_TAG, @@ -1686,13 +1795,12 @@ self.nsxpolicy.group.delete(domain_id, sg_id) raise nsx_exc.NsxPluginException(err_msg=msg) - def _get_rule_service_id(self, context, sg_rule): + def _get_rule_service_id(self, context, sg_rule, tags): """Return the NSX Policy service id matching the SG rule""" srv_id = None l4_protocol = nsxlib_utils.get_l4_protocol_name(sg_rule['protocol']) + ethertype = sg_rule.get('ethertype') srv_name = 'Service for OS rule %s' % sg_rule['id'] - tags = self.nsxpolicy.build_v3_api_version_project_tag( - context.tenant_name, project_id=sg_rule.get('tenant_id')) if l4_protocol in [nsxlib_consts.TCP, nsxlib_consts.UDP]: # If port_range_min is not specified then we assume all ports are @@ -1733,6 +1841,12 @@ description=sg_rule.get('description'), protocol_number=l4_protocol, tags=tags) + elif ethertype == const.IPv4: + # all ipv4 traffic + srv_id = NSX_P_IPV4_SERVICE_ID + elif ethertype == const.IPv6: + # all ipv6 traffic + srv_id = NSX_P_IPV6_SERVICE_ID return srv_id @@ -1753,8 +1867,11 @@ self._fix_sg_rule_dict_ips(sg_rule) source = None destination = this_group_id - tags = self.nsxpolicy.build_v3_api_version_project_tag( - context.tenant_name, project_id=sg_rule.get('tenant_id')) + + tags = self.nsxpolicy.build_v3_tags_payload( + sg_rule, resource_type='os-neutron-secgr-id', + project_name=sg_rule.get('tenant_id')) + if sg_rule.get('remote_group_id'): # This is the ID of a security group that already exists, # so it should be known to the policy manager @@ -1786,9 +1903,10 @@ # Swap source and destination source, destination = destination, source - service = self._get_rule_service_id(context, sg_rule) + service = self._get_rule_service_id(context, sg_rule, tags) logging = (cfg.CONF.nsx_p.log_security_groups_allowed_traffic or secgroup_logging) + scope = [self.nsxpolicy.group.get_path(domain_id, this_group_id)] self.nsxpolicy.comm_map.create_entry( nsx_name, domain_id, map_id, entry_id=sg_rule['id'], description=sg_rule.get('description'), @@ -1796,6 +1914,7 @@ action=policy_constants.ACTION_ALLOW, source_groups=[source] if source else None, dest_groups=[destination] if destination else None, + scope=scope, direction=direction, logged=logging) def _create_project_domain(self, context, project_id): @@ -1943,6 +2062,7 @@ # Tenant & security group are the same for all rules in the bulk example_rule = sg_rules[0]['security_group_rule'] sg_id = example_rule['security_group_id'] + sg = self.get_security_group(context, sg_id) self._prevent_non_admin_edit_provider_sg(context, sg_id) with db_api.CONTEXT_WRITER.using(context): @@ -1953,7 +2073,7 @@ self._process_security_group_rule_properties( context, rules_db[i], r['security_group_rule']) - domain_id = example_rule['tenant_id'] + domain_id = sg['tenant_id'] secgroup_logging = self._is_security_group_logged(context, sg_id) for rule_data in rules_db: # create the NSX backend rule @@ -2004,6 +2124,9 @@ rule_id, e) # Go on with the deletion anyway + #TODO(annak): Due to platform bug, comm map may still be considered + # present for a short while. This is a workaround till issue is fixed. + time.sleep(2) self._delete_security_group_rule_backend_resources( context, domain_id, rule_db) @@ -2091,3 +2214,6 @@ def _get_net_dhcp_relay(self, context, net_id): # No dhcp relay support yet return None + + def _support_vlan_router_interfaces(self): + return True diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/plugins/nsx_v/plugin.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/plugins/nsx_v/plugin.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/plugins/nsx_v/plugin.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/plugins/nsx_v/plugin.py 2019-03-14 02:01:03.000000000 +0000 @@ -19,16 +19,24 @@ import netaddr from neutron_lib.agent import topics +from neutron_lib.api.definitions import address_scope +from neutron_lib.api.definitions import agent as agent_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 dvr as dvr_apidef from neutron_lib.api.definitions import external_net as extnet_apidef from neutron_lib.api.definitions import extra_dhcp_opt as ext_edo +from neutron_lib.api.definitions import extraroute +from neutron_lib.api.definitions import flavors as flavors_apidef from neutron_lib.api.definitions import l3 as l3_apidef +from neutron_lib.api.definitions import l3_flavors from neutron_lib.api.definitions import multiprovidernet as mpnet_apidef +from neutron_lib.api.definitions import network_availability_zone from neutron_lib.api.definitions import port as port_def 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 provider_net as pnet +from neutron_lib.api.definitions import router_availability_zone from neutron_lib.api.definitions import subnet as subnet_def from neutron_lib.api.definitions import vlantransparent as vlan_apidef from neutron_lib.api import extensions @@ -81,7 +89,6 @@ from neutron.db.models import securitygroup as securitygroup_model # noqa from neutron.db import models_v2 from neutron.db import portsecurity_db -from neutron.db import quota_db # noqa from neutron.db import securitygroups_db from neutron.db import vlantransparent_db from neutron.extensions import providernet @@ -126,6 +133,7 @@ from vmware_nsx.extensions import projectpluginmap from vmware_nsx.extensions import providersecuritygroup as provider_sg from vmware_nsx.extensions import routersize +from vmware_nsx.extensions import routertype from vmware_nsx.extensions import secgroup_rule_local_ip_prefix from vmware_nsx.extensions import securitygrouplogging as sg_logging from vmware_nsx.extensions import securitygrouppolicy as sg_policy @@ -144,7 +152,8 @@ from vmware_nsx.plugins.nsx_v.vshield import securitygroup_utils from vmware_nsx.plugins.nsx_v.vshield import vcns_driver from vmware_nsx.services.flowclassifier.nsx_v import utils as fc_utils -from vmware_nsx.services.fwaas.nsx_v import fwaas_callbacks +from vmware_nsx.services.fwaas.common import utils as fwaas_utils +from vmware_nsx.services.fwaas.nsx_v import fwaas_callbacks_v2 from vmware_nsx.services.lbaas.nsx_v.implementation import healthmon_mgr from vmware_nsx.services.lbaas.nsx_v.implementation import l7policy_mgr from vmware_nsx.services.lbaas.nsx_v.implementation import l7rule_mgr @@ -205,37 +214,37 @@ mac_db.MacLearningDbMixin, hk_ext.Housekeeper): - supported_extension_aliases = ["agent", - "allowed-address-pairs", - "address-scope", - "binding", - "dns-search-domain", - "dvr", + supported_extension_aliases = [agent_apidef.ALIAS, + addr_apidef.ALIAS, + address_scope.ALIAS, + pbin.ALIAS, + ext_dns_search_domain.ALIAS, + dvr_apidef.ALIAS, "ext-gw-mode", - "multi-provider", - "port-security", - "provider", + mpnet_apidef.ALIAS, + psec.ALIAS, + pnet.ALIAS, "quotas", - "external-net", - "extra_dhcp_opt", - "extraroute", - "router", + extnet_apidef.ALIAS, + ext_edo.ALIAS, + extraroute.ALIAS, + l3_apidef.ALIAS, "security-group", - "secgroup-rule-local-ip-prefix", - "security-group-logging", - "nsxv-router-type", - "nsxv-router-size", - "vnic-index", - "advanced-service-providers", + secgroup_rule_local_ip_prefix.ALIAS, + sg_logging.ALIAS, + routertype.ALIAS, + routersize.ALIAS, + ext_vnic_idx.ALIAS, + as_providers.ALIAS, "subnet_allocation", - "availability_zone", - "network_availability_zone", - "router_availability_zone", - "l3-flavors", - "flavors", - "dhcp-mtu", - "mac-learning", - "housekeeper", + az_def.ALIAS, + network_availability_zone.ALIAS, + router_availability_zone.ALIAS, + l3_flavors.ALIAS, + flavors_apidef.ALIAS, + ext_dhcp_mtu.ALIAS, + mac_ext.ALIAS, + hk_ext.ALIAS, "port-security-groups-filtering"] __native_bulk_support = True @@ -310,15 +319,15 @@ # Support NSX policies in default security groups self._use_nsx_policies = True # enable the extension - self.supported_extension_aliases.append("security-group-policy") - self.supported_extension_aliases.append("nsx-policy") + self.supported_extension_aliases.append(sg_policy.ALIAS) + self.supported_extension_aliases.append(nsxpolicy.ALIAS) # Support transparent VLANS from 6.3.0 onwards. The feature is only # supported if the global configuration flag vlan_transparent is # True if cfg.CONF.vlan_transparent: if c_utils.is_nsxv_version_6_3(self.nsx_v.vcns.get_version()): - self.supported_extension_aliases.append("vlan-transparent") + self.supported_extension_aliases.append(vlan_apidef.ALIAS) else: LOG.warning("Transparent support only from " "NSX 6.3 onwards") @@ -330,9 +339,7 @@ # Make sure starting rpc listeners (for QoS and other agents) # will happen only once self.start_rpc_listeners_called = False - - # Init the FWaaS support - self._init_fwaas() + self.fwaas_callbacks = None # Service insertion driver register self._si_handler = fc_utils.NsxvServiceInsertionHandler(self) @@ -346,7 +353,7 @@ resources.SUBNETPOOL_ADDRESS_SCOPE, events.AFTER_UPDATE) if c_utils.is_nsxv_version_6_2(self.nsx_v.vcns.get_version()): - self.supported_extension_aliases.append("provider-security-group") + self.supported_extension_aliases.append(provider_sg.ALIAS) # Bind QoS notifications qos_driver.register(self) @@ -370,7 +377,10 @@ return False def spawn_complete(self, resource, event, trigger, payload=None): - # This method should run only once, but after init_complete + # Init the FWaaS support with RPC listeners for the original process + self._init_fwaas(with_rpc=True) + + # The rest of this method should run only once, but after init_complete if not self.init_is_complete: self.init_complete(None, None, None) @@ -413,6 +423,10 @@ self.octavia_listener = octavia_listener.NSXOctaviaListener( **octavia_objects) + # Init the FWaaS support without RPC listeners + # for the spawn workers + self._init_fwaas(with_rpc=False) + self.init_is_complete = True def _get_octavia_objects(self): @@ -496,9 +510,12 @@ self.start_rpc_listeners_called = True return self.conn.consume_in_threads() - def _init_fwaas(self): + def _init_fwaas(self, with_rpc): # Bind FWaaS callbacks to the driver - self.fwaas_callbacks = fwaas_callbacks.NsxvFwaasCallbacks() + if fwaas_utils.is_fwaas_v2_plugin_enabled(): + LOG.info("NSXv FWaaS v2 plugin enabled") + self.fwaas_callbacks = fwaas_callbacks_v2.NsxvFwaasCallbacksV2( + with_rpc) def _create_security_group_container(self): name = "OpenStack Security Group container" @@ -1337,8 +1354,15 @@ net_data['id']) net_data[psec.PORTSECURITY] = False # Create SpoofGuard policy for network anti-spoofing + # allow_multiple_addresses will be overridden in case the user + # requires allowing multiple or cidr-based allowed address pairs + # defined per port but doesn't want to disable spoofguard globally sg_policy_id = None - if cfg.CONF.nsxv.spoofguard_enabled and backend_network: + allow_multiple_addresses = (not net_data[psec.PORTSECURITY] + and cfg.CONF.nsxv. + allow_multiple_ip_addresses) + if (cfg.CONF.nsxv.spoofguard_enabled and backend_network and not + allow_multiple_addresses): # This variable is set as the method below may result in a # exception and we may need to rollback predefined = False @@ -1724,6 +1748,75 @@ "installed in order for security-groups to " "function properly.", net_id) + def allow_multiple_addresses_configure_spoofguard(self, context, id, + net_attrs, net_morefs): + # User requires multiple addresses to be assigned to compute port + # and therefore, the spoofguard policy is being removed for this net. + orig_net = self.get_network(context, id) + if not net_attrs[psec.PORTSECURITY]: + sg_policy = nsxv_db.get_spoofguard_policy_id(context.session, + orig_net['id']) + if sg_policy: + try: + self.nsx_v.vcns.delete_spoofguard_policy(sg_policy) + except Exception as e: + LOG.error('Unable to delete spoofguard policy ' + '%(sg_policy)s. Error: %(e)s', + {'sg_policy': sg_policy, 'e': e}) + else: + LOG.warning("Could not locate spoofguard policy for " + "network %s", id) + # User requires port-security-enabled set to True and thus requires + # spoofguard installed for this network + else: + # Verifying that all ports are legal, i.e. not CIDR/subnet + filters = {'network_id': [id]} + ports = self.get_ports(context, filters=filters) + valid_ports = [] + if ports: + for port in ports: + if self._is_compute_port(port): + for ap in port[addr_apidef.ADDRESS_PAIRS]: + if len(ap['ip_address'].split('/')) > 1: + msg = _('Port %s contains CIDR/subnet, ' + 'which is not supported at the ' + 'backend ') % port['id'] + raise n_exc.BadRequest( + resource='ports', + msg=msg) + else: + valid_ports.append(port) + try: + sg_policy_id, predefined = ( + self._prepare_spoofguard_policy( + orig_net.get(pnet.NETWORK_TYPE), orig_net, + net_morefs)) + if sg_policy_id: + nsxv_db.map_spoofguard_policy_for_network( + context.session, + orig_net['id'], sg_policy_id) + except Exception as e: + msg = _('Unable to create spoofguard policy, error: %(' + 'error)s, ' + 'net_morefs=%(net_morefs)s, network_id= %(' + 'network_id)s') % {'error': e, 'net_morefs': + net_morefs, 'network_id': orig_net} + raise n_exc.BadRequest(resource='spoofguard policy', msg=msg) + + try: + for port in valid_ports: + vnic_idx = port.get(ext_vnic_idx.VNIC_INDEX) + device_id = port['device_id'] + vnic_id = self._get_port_vnic_id(vnic_idx, + device_id) + self._update_vnic_assigned_addresses(context.session, port, + vnic_id) + except Exception as e: + msg = _('Unable to add port to spoofguard policy error ' + '%s') % e + raise n_exc.BadRequest(resource='spoofguard policy', + msg=msg) + def update_network(self, context, id, network): net_attrs = network['network'] orig_net = self.get_network(context, id) @@ -1749,6 +1842,15 @@ if psec_update: self._update_network_validate_port_sec(context, id, net_attrs) + # Change spoofguard accordingly - either remove if + # port-security-enabled was set to false or add (with relevant ports) + # if set to true. + if (cfg.CONF.nsxv.spoofguard_enabled and + cfg.CONF.nsxv.allow_multiple_ip_addresses and psec_update): + self.allow_multiple_addresses_configure_spoofguard(context, id, + net_attrs, + net_morefs) + # Check if the physical network of a vlan provider network was updated updated_morefs = False if (net_attrs.get(pnet.PHYSICAL_NETWORK) and @@ -1857,17 +1959,24 @@ return net_res - def _validate_address_pairs(self, attrs, db_port): + def _validate_address_pairs(self, context, attrs, db_port): + network_port_security = self._get_network_security_binding( + context, db_port['network_id']) + if (not cfg.CONF.nsxv.allow_multiple_ip_addresses and + not network_port_security): + for ap in attrs[addr_apidef.ADDRESS_PAIRS]: + # Check that the IP address is a subnet + if len(ap['ip_address'].split('/')) > 1: + msg = _('NSXv does not support CIDR as address pairs') + raise n_exc.BadRequest(resource='address_pairs', + msg=msg) + # Check that the MAC address is the same as the port for ap in attrs[addr_apidef.ADDRESS_PAIRS]: - # Check that the IP address is a subnet - if len(ap['ip_address'].split('/')) > 1: - msg = _('NSXv does not support CIDR as address pairs') - raise n_exc.BadRequest(resource='address_pairs', msg=msg) - # Check that the MAC address is the same as the port if ('mac_address' in ap and - ap['mac_address'] != db_port['mac_address']): - msg = _('Address pairs should have same MAC as the port') - raise n_exc.BadRequest(resource='address_pairs', msg=msg) + ap['mac_address'] != db_port['mac_address']): + msg = _('Address pairs should have same MAC as the ' + 'port') + raise n_exc.BadRequest(resource='address_pairs', msg=msg) def _is_mac_in_use(self, context, network_id, mac_address): # Override this method as the backed doesn't support using the same @@ -1986,7 +2095,7 @@ if self._check_update_has_allowed_address_pairs(port): if not port_security: raise addr_exc.AddressPairAndPortSecurityRequired() - self._validate_address_pairs(attrs, neutron_db) + self._validate_address_pairs(context, attrs, neutron_db) else: # remove ATTR_NOT_SPECIFIED attrs[addr_apidef.ADDRESS_PAIRS] = [] @@ -2198,7 +2307,7 @@ self._validate_extra_dhcp_options(dhcp_opts) self._validate_port_qos(port_data) if addr_apidef.ADDRESS_PAIRS in attrs: - self._validate_address_pairs(attrs, original_port) + self._validate_address_pairs(context, attrs, original_port) self._validate_max_ips_per_port( port_data.get('fixed_ips', []), port_data.get('device_owner', original_port['device_owner'])) @@ -2562,13 +2671,11 @@ def delete_port(self, context, id, l3_port_check=True, nw_gw_port_check=True, force_delete_dhcp=False, allow_delete_internal=False): - kwargs = { - 'context': context, - 'port_check': l3_port_check, - 'port_id': id, - } # Send delete port notification to any interested service plugin - registry.notify(resources.PORT, events.BEFORE_DELETE, self, **kwargs) + registry.publish(resources.PORT, events.BEFORE_DELETE, self, + payload=events.DBEventPayload( + context, resource_id=id, + metadata={'port_check': l3_port_check})) neutron_db_port = self.get_port(context, id) device_id = neutron_db_port['device_id'] @@ -3347,8 +3454,9 @@ raise n_exc.InvalidInput(error_message=err_msg) # shared router cannot be attached to a fwaas - if self.fwaas_callbacks.should_apply_firewall_to_router( - context, router, router_id): + if (self.fwaas_callbacks and + self.fwaas_callbacks.should_apply_firewall_to_router( + context, router, router_id)): err_msg = _('Unable to create a shared router with FWaaS') raise n_exc.InvalidInput(error_message=err_msg) @@ -3914,9 +4022,29 @@ context, router_id, interface_info) def remove_router_interface(self, context, router_id, interface_info): + # Get the router interface port id + if self.fwaas_callbacks: + port_id = interface_info.get('port_id') + if not port_id: + subnet_id = interface_info['subnet_id'] + subnet = self._get_subnet(context, subnet_id) + rport_qry = context.session.query(models_v2.Port) + ports = rport_qry.filter_by( + device_id=router_id, + device_owner=l3_db.DEVICE_OWNER_ROUTER_INTF, + network_id=subnet['network_id']) + for p in ports: + if p['fixed_ips'][0]['subnet_id'] == subnet_id: + port_id = p['id'] + break + router_driver = self._find_router_driver(context, router_id) - return router_driver.remove_router_interface( + result = router_driver.remove_router_interface( context, router_id, interface_info) + # inform the FWaaS that interface port was removed + if self.fwaas_callbacks and port_id: + self.fwaas_callbacks.delete_port(context, port_id) + return result def _get_floatingips_by_router(self, context, router_id): fip_qry = context.session.query(l3_db_models.FloatingIP) @@ -4016,34 +4144,22 @@ router_db is the neutron router structure router_id is the id of the actual router that will be updated on the NSX (in case of distributed router it can be plr or tlr) + + This is just a wrapper of update_router_firewall """ if not router_id: router_id = router_db['id'] - # Add fw rules if FWaaS is enabled - # in case of a distributed-router: - # router['id'] is the id of the neutron router (=tlr) - # and router_id is the plr/tlr (the one that is being updated) - fwaas_rules = None - if (self.fwaas_callbacks.should_apply_firewall_to_router( - context, router_db, router_id)): - fwaas_rules = self.fwaas_callbacks.get_fwaas_rules_for_router( - context, router_db['id']) - - self.update_router_firewall(context, router_id, router_db, - fwaas_rules=fwaas_rules) + self.update_router_firewall(context, router_id, router_db) - def update_router_firewall(self, context, router_id, router_db, - fwaas_rules=None): + def update_router_firewall(self, context, router_id, router_db): """Recreate all rules in the router edge firewall router_db is the neutron router structure router_id is the id of the actual router that will be updated on the NSX (in case of distributed router it can be plr or tlr) - if fwaas_rules is not none - this router is attached to a firewall """ fw_rules = [] - router_with_firewall = True if fwaas_rules is not None else False edge_id = self._get_edge_id_by_rtr_id(context, router_id) # Add FW rule/s to open subnets firewall flows and static routes @@ -4056,33 +4172,41 @@ if self.metadata_proxy_handler: fw_rules += nsx_v_md_proxy.get_router_fw_rules() - # Add FWaaS rules - if router_with_firewall and fwaas_rules: - fw_rules += fwaas_rules - - if not router_with_firewall: - dnat_rule = self._get_dnat_fw_rule(context, router_db) - if dnat_rule: - fw_rules.append(dnat_rule) - - # Add rule for not NAT-ed allocation pools - alloc_pool_rule = self._get_allocation_pools_fw_rule( - context, router_db) - if alloc_pool_rule: - fw_rules.append(alloc_pool_rule) - - # Add no-snat rules - nosnat_fw_rules = self._get_nosnat_subnets_fw_rules( - context, router_db) - fw_rules.extend(nosnat_fw_rules) - - vpn_plugin = directory.get_plugin(plugin_const.VPN) - if vpn_plugin: - vpn_driver = vpn_plugin.drivers[vpn_plugin.default_provider] - vpn_rules = ( - vpn_driver._generate_ipsecvpn_firewall_rules( - self.plugin_type(), context, edge_id=edge_id)) - fw_rules.extend(vpn_rules) + # Add FWaaS rules if FWaaS is enabled + if (self.fwaas_callbacks and + self.fwaas_callbacks.should_apply_firewall_to_router( + context, router_db, router_id)): + fwaas_rules = self.fwaas_callbacks.get_fwaas_rules_for_router( + context, router_db['id'], edge_id) + if fwaas_rules: + fw_rules += fwaas_rules + + # The rules added from here forward are relevant only for interface + # ports without fwaas firewall group + # To allow this traffic on interfaces with firewall group, the user + # should add specific rules. + dnat_rule = self._get_dnat_fw_rule(context, router_db) + if dnat_rule: + fw_rules.append(dnat_rule) + + # Add rule for not NAT-ed allocation pools + alloc_pool_rule = self._get_allocation_pools_fw_rule( + context, router_db) + if alloc_pool_rule: + fw_rules.append(alloc_pool_rule) + + # Add no-snat rules + nosnat_fw_rules = self._get_nosnat_subnets_fw_rules( + context, router_db) + fw_rules.extend(nosnat_fw_rules) + + vpn_plugin = directory.get_plugin(plugin_const.VPN) + if vpn_plugin: + vpn_driver = vpn_plugin.drivers[vpn_plugin.default_provider] + vpn_rules = ( + vpn_driver._generate_ipsecvpn_firewall_rules( + self.plugin_type(), context, edge_id=edge_id)) + fw_rules.extend(vpn_rules) # Get the load balancer rules in case they are refreshed # (relevant only for older LB that are still on the router edge) @@ -4102,11 +4226,7 @@ fw = {'firewall_rule_list': fw_rules} try: - # If we have a firewall we shouldn't add the default - # allow-external rule - allow_external = False if router_with_firewall else True - edge_utils.update_firewall(self.nsx_v, context, router_id, fw, - allow_external=allow_external) + edge_utils.update_firewall(self.nsx_v, context, router_id, fw) except vsh_exc.ResourceNotFound: LOG.error("Failed to update firewall for router %s", router_id) diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/plugins/nsx_v/vshield/edge_utils.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/plugins/nsx_v/vshield/edge_utils.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/plugins/nsx_v/vshield/edge_utils.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/plugins/nsx_v/vshield/edge_utils.py 2019-03-14 02:01:03.000000000 +0000 @@ -1590,8 +1590,11 @@ raise nsx_exc.NsxPluginException(err_msg=error) def get_plr_by_tlr_id(self, context, router_id): - lswitch_id = nsxv_db.get_nsxv_router_binding( - context.session, router_id).lswitch_id + lswitch_id = None + binding = nsxv_db.get_nsxv_router_binding( + context.session, router_id) + if binding: + lswitch_id = binding.lswitch_id if lswitch_id: edge_vnic_bindings = nsxv_db.get_edge_vnic_bindings_by_int_lswitch( context.session, lswitch_id) diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/plugins/nsx_v/vshield/vcns.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/plugins/nsx_v/vshield/vcns.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/plugins/nsx_v/vshield/vcns.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/plugins/nsx_v/vshield/vcns.py 2019-03-14 02:01:03.000000000 +0000 @@ -720,6 +720,8 @@ h, c = self.do_request(HTTP_GET, section_uri, format='xml', decode=False) etag = h['etag'] + # remove extra "" from the etag + etag = etag.replace('"', '') headers = {'If-Match': etag} return headers @@ -810,6 +812,10 @@ uri = '%s/policies/%s' % (SPOOFGUARD_PREFIX, policy_id) return self.do_request(HTTP_GET, uri, decode=True) + def get_spoofguard_policy_data(self, policy_id, list_type='ALL'): + uri = '%s/%s?list=%s' % (SPOOFGUARD_PREFIX, policy_id, list_type) + return self.do_request(HTTP_GET, uri, decode=True) + def get_spoofguard_policies(self): uri = '%s/policies/' % SPOOFGUARD_PREFIX return self.do_request(HTTP_GET, uri, decode=True) diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/plugins/nsx_v3/plugin.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/plugins/nsx_v3/plugin.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/plugins/nsx_v3/plugin.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/plugins/nsx_v3/plugin.py 2019-03-14 02:01:03.000000000 +0000 @@ -18,14 +18,33 @@ import mock import netaddr from neutron_lib.agent import topics +from neutron_lib.api.definitions import address_scope +from neutron_lib.api.definitions import agent as agent_apidef from neutron_lib.api.definitions import allowedaddresspairs as addr_apidef +from neutron_lib.api.definitions import availability_zone +from neutron_lib.api.definitions import dhcpagentscheduler from neutron_lib.api.definitions import external_net as extnet_apidef +from neutron_lib.api.definitions import extra_dhcp_opt as ext_edo +from neutron_lib.api.definitions import extraroute from neutron_lib.api.definitions import l3 as l3_apidef +from neutron_lib.api.definitions import network_availability_zone from neutron_lib.api.definitions import port_security as psec +from neutron_lib.api.definitions import portbindings as pbin_apidef +from neutron_lib.api.definitions import provider_net +from neutron_lib.api.definitions import router_availability_zone +from neutron_lib.api.definitions import vlantransparent as vlan_apidef from neutron_lib.api import extensions +from neutron_lib.api import validators +from neutron_lib.callbacks import events +from neutron_lib.callbacks import exceptions as callback_exc +from neutron_lib.callbacks import registry +from neutron_lib.callbacks import resources +from neutron_lib import constants as const +from neutron_lib import context as q_context from neutron_lib.db import api as db_api from neutron_lib.db import resource_extend from neutron_lib.db import utils as db_utils +from neutron_lib import exceptions as n_exc from neutron_lib.exceptions import l3 as l3_exc from neutron_lib.plugins import constants as plugin_const from neutron_lib.plugins import directory @@ -43,17 +62,7 @@ from neutron.extensions import providernet from neutron.extensions import securitygroup as ext_sg from neutron.quota import resource_registry -from neutron_lib.api.definitions import extra_dhcp_opt as ext_edo -from neutron_lib.api.definitions import provider_net as pnet -from neutron_lib.api.definitions import vlantransparent as vlan_apidef -from neutron_lib.api import validators -from neutron_lib.callbacks import events -from neutron_lib.callbacks import exceptions as callback_exc -from neutron_lib.callbacks import registry -from neutron_lib.callbacks import resources -from neutron_lib import constants as const -from neutron_lib import context as q_context -from neutron_lib import exceptions as n_exc + from oslo_config import cfg from oslo_db import exception as db_exc from oslo_log import log @@ -72,10 +81,12 @@ from vmware_nsx.common import utils from vmware_nsx.db import db as nsx_db from vmware_nsx.dhcp_meta import rpc as nsx_rpc +from vmware_nsx.extensions import api_replay from vmware_nsx.extensions import housekeeper as hk_ext from vmware_nsx.extensions import maclearning as mac_ext from vmware_nsx.extensions import projectpluginmap from vmware_nsx.extensions import providersecuritygroup as provider_sg +from vmware_nsx.extensions import secgroup_rule_local_ip_prefix from vmware_nsx.extensions import securitygrouplogging as sg_logging from vmware_nsx.plugins.common.housekeeper import housekeeper from vmware_nsx.plugins.common_v3 import plugin as nsx_plugin_common @@ -83,7 +94,6 @@ from vmware_nsx.plugins.nsx_v3 import availability_zones as nsx_az from vmware_nsx.plugins.nsx_v3 import utils as v3_utils from vmware_nsx.services.fwaas.common import utils as fwaas_utils -from vmware_nsx.services.fwaas.nsx_v3 import fwaas_callbacks_v1 from vmware_nsx.services.fwaas.nsx_v3 import fwaas_callbacks_v2 from vmware_nsx.services.lbaas.nsx_v3.implementation import healthmonitor_mgr from vmware_nsx.services.lbaas.nsx_v3.implementation import l7policy_mgr @@ -131,28 +141,28 @@ __native_pagination_support = True __native_sorting_support = True - supported_extension_aliases = ["allowed-address-pairs", - "address-scope", + supported_extension_aliases = [addr_apidef.ALIAS, + address_scope.ALIAS, "quotas", - "binding", - "extra_dhcp_opt", - "agent", - "dhcp_agent_scheduler", + pbin_apidef.ALIAS, + ext_edo.ALIAS, + agent_apidef.ALIAS, + dhcpagentscheduler.ALIAS, "ext-gw-mode", "security-group", - "secgroup-rule-local-ip-prefix", - "port-security", - "provider", - "external-net", - "extraroute", - "router", - "availability_zone", - "network_availability_zone", - "router_availability_zone", + secgroup_rule_local_ip_prefix.ALIAS, + psec.ALIAS, + provider_net.ALIAS, + extnet_apidef.ALIAS, + extraroute.ALIAS, + l3_apidef.ALIAS, + availability_zone.ALIAS, + network_availability_zone.ALIAS, + router_availability_zone.ALIAS, "subnet_allocation", - "security-group-logging", - "provider-security-group", - "housekeeper", + sg_logging.ALIAS, + provider_sg.ALIAS, + hk_ext.ALIAS, "port-security-groups-filtering"] @resource_registry.tracked_resources( @@ -235,14 +245,14 @@ self._unsubscribe_callback_events() if cfg.CONF.api_replay_mode: - self.supported_extension_aliases.append('api-replay') + self.supported_extension_aliases.append(api_replay.ALIAS) # Support transparent VLANS from 2.2.0 onwards. The feature is only # supported if the global configuration flag vlan_transparent is # True if cfg.CONF.vlan_transparent: if self.nsxlib.feature_supported(nsxlib_consts.FEATURE_TRUNK_VLAN): - self.supported_extension_aliases.append("vlan-transparent") + self.supported_extension_aliases.append(vlan_apidef.ALIAS) else: LOG.warning("Current NSX version %s doesn't support " "transparent vlans", self.nsxlib.get_version()) @@ -392,7 +402,10 @@ return False def spawn_complete(self, resource, event, trigger, payload=None): - # This method should run only once, but after init_complete + # Init the FWaaS support with RPC listeners for the original process + self._init_fwaas(with_rpc=True) + + # The rest of this method should run only once, but after init_complete if not self.init_is_complete: self.init_complete(None, None, None) @@ -402,9 +415,6 @@ self, self._get_octavia_stats_getter())) - # Init the FWaaS support - self._init_fwaas() - def init_complete(self, resource, event, trigger, payload=None): with locking.LockManager.get_lock('plugin-init-complete'): if self.init_is_complete: @@ -426,6 +436,10 @@ # Init octavia listener and endpoints self._init_octavia() + # Init the FWaaS support without RPC listeners + # for the spawn workers + self._init_fwaas(with_rpc=False) + self.init_is_complete = True def _init_octavia(self): @@ -455,13 +469,15 @@ def _get_octavia_stats_getter(self): return listener_mgr.stats_getter - def _init_fwaas(self): - if fwaas_utils.is_fwaas_v1_plugin_enabled(): - LOG.info("NSXv3 FWaaS v1 plugin enabled") - self.fwaas_callbacks = fwaas_callbacks_v1.Nsxv3FwaasCallbacksV1() + def _init_fwaas(self, with_rpc): + if self.fwaas_callbacks: + # already initialized + return + if fwaas_utils.is_fwaas_v2_plugin_enabled(): LOG.info("NSXv3 FWaaS v2 plugin enabled") - self.fwaas_callbacks = fwaas_callbacks_v2.Nsxv3FwaasCallbacksV2() + self.fwaas_callbacks = fwaas_callbacks_v2.Nsxv3FwaasCallbacksV2( + with_rpc) def _init_lbv2_driver(self): # Get LBaaSv2 driver during plugin initialization. If the platform @@ -508,7 +524,7 @@ try: self._init_mac_learning_profile() # Only expose the extension if it is supported - self.supported_extension_aliases.append('mac-learning') + self.supported_extension_aliases.append(mac_ext.ALIAS) except Exception as e: LOG.warning("Unable to initialize NSX v3 MAC Learning " "profile: %(name)s. Reason: %(reason)s", @@ -1667,14 +1683,12 @@ def _pre_delete_port_check(self, context, port_id, l2gw_port_check): """Perform checks prior to deleting a port.""" try: - kwargs = { - 'context': context, - 'port_check': l2gw_port_check, - 'port_id': port_id, - } # Send delete port notification to any interested service plugin - registry.notify( - resources.PORT, events.BEFORE_DELETE, self, **kwargs) + registry.publish( + resources.PORT, events.BEFORE_DELETE, self, + payload=events.DBEventPayload( + context, resource_id=port_id, + metadata={'port_check': l2gw_port_check})) except callback_exc.CallbackFailure as e: if len(e.errors) == 1: raise e.errors[0].error @@ -2087,9 +2101,13 @@ 'net': sub['network_id']}) raise n_exc.InvalidInput(error_message=msg) - def state_firewall_rules(self, context, router_id): + def _router_has_edge_fw_rules(self, context, router): + if not router.gw_port_id: + # No GW -> No rule on the edge firewall + return False + if self.fwaas_callbacks and self.fwaas_callbacks.fwaas_enabled: - ports = self._get_router_interfaces(context, router_id) + ports = self._get_router_interfaces(context, router.id) return self.fwaas_callbacks.router_with_fwg(context, ports) def verify_sr_at_backend(self, context, router_id): @@ -2104,15 +2122,22 @@ snat_exist = router.enable_snat lb_exist = nsx_db.has_nsx_lbaas_loadbalancer_binding_by_router( context.session, nsx_router_id) - fw_exist = self.state_firewall_rules(context, router_id) + fw_exist = self._router_has_edge_fw_rules(context, router) if snat_exist or lb_exist or fw_exist: return True return snat_exist or lb_exist or fw_exist - def create_service_router(self, context, router_id): + def create_service_router(self, context, router_id, router=None, + update_firewall=True): """Create a service router and enable standby relocation""" - router = self._get_router(context, router_id) + if not router: + router = self._get_router(context, router_id) tier0_uuid = self._get_tier0_uuid_by_router(context, router) + if not tier0_uuid: + err_msg = (_("Cannot create service router for %s without a " + "gateway") % router_id) + raise n_exc.InvalidInput(error_message=err_msg) + edge_cluster_uuid = self._get_edge_cluster(tier0_uuid, router) nsx_router_id = nsx_db.get_nsx_router_id(context.session, router_id) @@ -2126,6 +2151,14 @@ edge_cluster_id=edge_cluster_uuid, enable_standby_relocation=enable_standby_relocation) + LOG.info("Created service router for %s (NSX logical router %s)", + router_id, nsx_router_id) + + # update firewall rules (there might be FW group waiting for a + # service router) + if update_firewall: + self.update_router_firewall(context, router_id) + def delete_service_router(self, context, router_id): nsx_router_id = nsx_db.get_nsx_router_id(context.session, router_id) @@ -2135,6 +2168,8 @@ nsx_router_id, edge_cluster_id=None, enable_standby_relocation=False) + LOG.info("Deleted service router for %s (NSX logical router %s)", + router_id, nsx_router_id) def _update_router_gw_info(self, context, router_id, info): router = self._get_router(context, router_id) @@ -2164,17 +2199,18 @@ lb_exist = nsx_db.has_nsx_lbaas_loadbalancer_binding_by_router( context.session, nsx_router_id) - fw_exist = self.state_firewall_rules(context, router_id) + fw_exist = self._router_has_edge_fw_rules(context, router) + sr_currently_exists = self.verify_sr_at_backend(context, router_id) actions = self._get_update_router_gw_actions( org_tier0_uuid, orgaddr, org_enable_snat, - new_tier0_uuid, newaddr, new_enable_snat, lb_exist, fw_exist) + new_tier0_uuid, newaddr, new_enable_snat, + lb_exist, fw_exist, sr_currently_exists) if actions['add_service_router']: - self.create_service_router(context, router_id) + self.create_service_router(context, router_id, router=router) if actions['revocate_bgp_announce']: - # TODO(berlin): revocate bgp announce on org tier0 router pass if actions['remove_snat_rules']: @@ -2502,7 +2538,7 @@ def update_router_firewall(self, context, router_id, from_fw=False): """Rewrite all the rules in the router edge firewall - This method should be called on FWaaS v1/v2 updates, and on router + This method should be called on FWaaS v2 updates, and on router interfaces changes. When FWaaS is disabled, there is no need to update the NSX router FW, as the default rule is allow-all. @@ -2584,7 +2620,8 @@ relay_target = [] if self.fwaas_callbacks: relay_target = (self.fwaas_callbacks.fwaas_driver. - translate_addresses_to_target(set(relay_servers))) + translate_addresses_to_target(set(relay_servers), + self.plugin_type())) dhcp_services = self._get_port_relay_services() @@ -2637,44 +2674,6 @@ address_groups.append(address_group) return (ports, address_groups) - def _validate_multiple_subnets_routers(self, context, router_id, net_id): - network = self.get_network(context, net_id) - net_type = network.get(pnet.NETWORK_TYPE) - if (net_type and - not self.nsxlib.feature_supported( - nsxlib_consts.FEATURE_VLAN_ROUTER_INTERFACE) and - not self._is_overlay_network(context, net_id)): - err_msg = (_("Only overlay networks can be attached to a logical " - "router. Network %(net_id)s is a %(net_type)s based " - "network") % {'net_id': net_id, 'net_type': net_type}) - LOG.error(err_msg) - raise n_exc.InvalidInput(error_message=err_msg) - # Unable to attach a trunked network to a router interface - if cfg.CONF.vlan_transparent: - if network.get('vlan_transparent') is True: - err_msg = (_("Transparent VLAN networks cannot be attached to " - "a logical router.")) - LOG.error(err_msg) - raise n_exc.InvalidInput(error_message=err_msg) - port_filters = {'device_owner': [l3_db.DEVICE_OWNER_ROUTER_INTF], - 'network_id': [net_id]} - intf_ports = self.get_ports(context.elevated(), filters=port_filters) - router_ids = [port['device_id'] - for port in intf_ports if port['device_id']] - if len(router_ids) > 0: - err_msg = _("Only one subnet of network %(net_id)s can be " - "attached to router, one subnet is already attached " - "to router %(router_id)s") % { - 'net_id': net_id, - 'router_id': router_ids[0]} - LOG.error(err_msg) - if router_id in router_ids: - # attach to the same router again - raise n_exc.InvalidInput(error_message=err_msg) - else: - # attach to multiple routers - raise l3_exc.RouterInterfaceAttachmentConflict(reason=err_msg) - def _add_router_interface_wrapper(self, context, router_id, interface_info): if cfg.CONF.api_replay_mode: @@ -2899,6 +2898,8 @@ # update the load balancer virtual server's VIP with # floating ip, but don't add NAT rules device_id = port['device_id'] + if device_id.startswith(oct_const.DEVICE_ID_PREFIX): + device_id = device_id[len(oct_const.DEVICE_ID_PREFIX):] lb_tag = [{'scope': 'os-lbaas-lb-id', 'tag': device_id}] vs_list = self.nsxlib.search_by_tags( tags=lb_tag, resource_type='LbVirtualServer') @@ -3247,25 +3248,40 @@ context, firewall_section['id'], ns_group['id'], logging, action, sg_rules) self.save_security_group_rule_mappings(context, rules['rules']) - except nsx_lib_exc.ManagerError: - with excutils.save_and_reraise_exception(): - LOG.exception("Failed to create backend firewall rules " - "for security-group %(name)s (%(id)s), " - "rolling back changes.", secgroup_db) - # default security group deletion requires admin context - if default_sg: - context = context.elevated() - super(NsxV3Plugin, self).delete_security_group( - context, secgroup_db['id']) - self.nsxlib.ns_group.delete(ns_group['id']) - self.nsxlib.firewall_section.delete(firewall_section['id']) + except nsx_lib_exc.ManagerError as ex: + msg = ("Failed to create backend firewall rules " + "for security-group %(name)s (%(id)s), " + "rolling back changes." % secgroup_db) + LOG.exception(msg) + # default security group deletion requires admin context + if default_sg: + context = context.elevated() + super(NsxV3Plugin, self).delete_security_group( + context, secgroup_db['id']) + self.nsxlib.ns_group.delete(ns_group['id']) + self.nsxlib.firewall_section.delete(firewall_section['id']) + + if ex.__class__ is nsx_lib_exc.ResourceNotFound: + # This may happen due to race condition during + # backend reboot. The exception raised should reflect + # short-term availability issue (500) rather than 404 + raise nsx_exc.NsxPluginTemporaryError(err_msg=msg) + else: + raise ex return secgroup_db + def _prevent_nsx_internal_sg_modification(self, sg_id): + if sg_id == NSX_V3_OS_DFW_UUID: + msg = _("Cannot modify NSX internal security group") + raise n_exc.InvalidInput(error_message=msg) + def update_security_group(self, context, id, security_group): orig_secgroup = self.get_security_group( context, id, fields=['id', 'name', 'description']) self._prevent_non_admin_edit_provider_sg(context, id) + self._prevent_nsx_internal_sg_modification(id) + with db_api.CONTEXT_WRITER.using(context): secgroup_res = ( super(NsxV3Plugin, self).update_security_group(context, id, @@ -3290,6 +3306,7 @@ def delete_security_group(self, context, id): self._prevent_non_admin_edit_provider_sg(context, id) + self._prevent_nsx_internal_sg_modification(id) nsgroup_id, section_id = nsx_db.get_sg_mappings( context.session, id) super(NsxV3Plugin, self).delete_security_group(context, id) @@ -3325,6 +3342,7 @@ # group. We should be validating that this is the case though... sg_id = sg_rules[0]['security_group_rule']['security_group_id'] self._prevent_non_admin_edit_provider_sg(context, sg_id) + self._prevent_nsx_internal_sg_modification(sg_id) security_group = self.get_security_group( context, sg_id) @@ -3355,6 +3373,7 @@ rule_db = self._get_security_group_rule(context, id) sg_id = rule_db['security_group_id'] self._prevent_non_admin_edit_provider_sg(context, sg_id) + self._prevent_nsx_internal_sg_modification(sg_id) nsgroup_id, section_id = nsx_db.get_sg_mappings(context.session, sg_id) fw_rule_id = nsx_db.get_sg_rule_mapping(context.session, id) self.nsxlib.firewall_section.delete_rule(section_id, fw_rule_id) @@ -3418,3 +3437,7 @@ def _get_net_dhcp_relay(self, context, net_id): return self.get_network_az_by_net_id( context, net_id).dhcp_relay_service + + def _support_vlan_router_interfaces(self): + return self.nsxlib.feature_supported( + nsxlib_consts.FEATURE_VLAN_ROUTER_INTERFACE) diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/dynamic_routing/bgp_plugin.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/dynamic_routing/bgp_plugin.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/dynamic_routing/bgp_plugin.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/dynamic_routing/bgp_plugin.py 2019-03-14 02:01:03.000000000 +0000 @@ -43,7 +43,7 @@ """ supported_extension_aliases = [bgp_ext.BGP_EXT_ALIAS, - ext_esg.ESG_BGP_PEER_EXT_ALIAS] + ext_esg.ALIAS] def __init__(self): super(NSXBgpPlugin, self).__init__() diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/fwaas/common/fwaas_callbacks_v1.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/fwaas/common/fwaas_callbacks_v1.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/fwaas/common/fwaas_callbacks_v1.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/fwaas/common/fwaas_callbacks_v1.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,158 +0,0 @@ -# Copyright 2017 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_log import log as logging - -from neutron.agent.l3 import router_info -from neutron.common import config as neutron_config # noqa -from neutron_lib import constants as nl_constants -from neutron_lib import context as n_context -from neutron_lib.exceptions import firewall_v1 as exceptions -from neutron_lib.plugins import directory - -LOG = logging.getLogger(__name__) - -try: - from neutron_fwaas.db.firewall import firewall_db # noqa - from neutron_fwaas.db.firewall import firewall_router_insertion_db \ - as fw_r_ins_db - from neutron_fwaas.services.firewall.service_drivers.agents.l3reference \ - import firewall_l3_agent -except ImportError: - # FWaaS project no found - from vmware_nsx.services.fwaas.common import fwaas_mocks \ - as firewall_l3_agent - - -class NsxFwaasCallbacks(firewall_l3_agent.L3WithFWaaS): - """Common NSX RPC callbacks for Firewall As A Service - V1.""" - def __init__(self): - # The super code needs a configuration object with the neutron host - # and an agent_mode, which our driver doesn't use. - neutron_conf = cfg.CONF - neutron_conf.agent_mode = 'nsx' - super(NsxFwaasCallbacks, self).__init__(conf=neutron_conf) - self._core_plugin = None - - @property - def plugin_type(self): - pass - - @property - def core_plugin(self): - """Get the NSX-V3 core plugin""" - if not self._core_plugin: - self._core_plugin = directory.get_plugin() - if self._core_plugin.is_tvd_plugin(): - # get the plugin that match this driver - self._core_plugin = self._core_plugin.get_plugin_by_type( - self.plugin_type) - return self._core_plugin - - # Override functions using the agent_api that is not used by our plugin - def _get_router_ids_for_fw(self, context, fw, to_delete=False): - """Return the router_ids either from fw dict or tenant routers.""" - routers_in_proj = self._get_routers_in_project( - context, fw['tenant_id']) - if self._has_router_insertion_fields(fw): - # it is a new version of plugin (supports specific routers) - ids = (fw['del-router-ids'] if to_delete - else fw['add-router-ids']) - project_ids = [router['id'] for router in routers_in_proj - if router['id'] in ids] - if len(project_ids) < len(ids) and not to_delete: - # This means that there is a router from another project. - LOG.error("Failed to attach routers from a different project " - "to firewall %(fw)s: %(routers)s", - {'fw': fw['id'], - 'routers': list(set(ids) - set(project_ids))}) - self.fwplugin_rpc.set_firewall_status( - context, - fw['id'], - nl_constants.ERROR) - raise exceptions.FirewallInternalDriverError( - driver=self.fwaas_driver.driver_name) - return ids - else: - return [router['id'] for router in routers_in_proj] - - def _get_routers_in_project(self, context, project_id): - return self.core_plugin.get_routers( - context, - filters={'project_id': [project_id]}) - - def _router_dict_to_obj(self, r): - # The callbacks expect a router-info object with an agent config - agent_conf = cfg.CONF - agent_conf.metadata_access_mark = '0x1' - return router_info.RouterInfo( - None, r['id'], router=r, - agent_conf=agent_conf, - interface_driver=None, - use_ipv6=False) - - def _get_router_info_list_for_tenant(self, router_ids, tenant_id): - """Returns the list of router info objects on which to apply the fw.""" - context = n_context.get_admin_context() - tenant_routers = self._get_routers_in_project(context, tenant_id) - return [self._router_dict_to_obj(ri) for ri in tenant_routers - if ri['id'] in router_ids] - - def should_apply_firewall_to_router(self, context, router_id): - """Return True if the FWaaS rules should be added to this router.""" - if not self.fwaas_enabled: - return False - - ctx = context.elevated() - fw_id = self._get_router_firewall_id(ctx, router_id) - if fw_id is None: - # No FWaas Firewall was assigned to this router - return False - - # check the state of this firewall - firewall = self._get_fw_from_plugin(ctx, fw_id) - if firewall is not None: - if firewall.get('status') in (nl_constants.ERROR, - nl_constants.PENDING_DELETE): - # Do not add rules of firewalls with errors - LOG.warning("Router %(rtr)s will not get rules from firewall " - "%(fw)s which is in %(status)s", - {'rtr': router_id, 'fw': fw_id, - 'status': firewall['status']}) - return False - - return True - - # TODO(asarfaty): add this api to fwaas firewall-router-insertion-db - def _get_router_firewall_id(self, context, router_id): - entry = context.session.query( - fw_r_ins_db.FirewallRouterAssociation).filter_by( - router_id=router_id).first() - if entry: - return entry.fw_id - - def _get_fw_from_plugin(self, context, fw_id): - # NOTE(asarfaty): currently there is no api to get a specific firewall - fw_list = self.fwplugin_rpc.get_firewalls_for_tenant(context) - for fw in fw_list: - if fw['id'] == fw_id: - return fw - - def get_router_firewall(self, context, router_id): - ctx_elevated = context.elevated() - fw_id = self._get_router_firewall_id(ctx_elevated, router_id) - if fw_id: - return self._get_fw_from_plugin(ctx_elevated, fw_id) diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/fwaas/common/fwaas_callbacks_v2.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/fwaas/common/fwaas_callbacks_v2.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/fwaas/common/fwaas_callbacks_v2.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/fwaas/common/fwaas_callbacks_v2.py 2019-03-14 02:01:03.000000000 +0000 @@ -1,4 +1,4 @@ -# Copyright 2017 VMware, Inc. +# Copyright 2018 VMware, Inc. # All Rights Reserved # # Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -41,29 +41,34 @@ class NsxFwaasCallbacksV2(firewall_l3_agent_v2.L3WithFWaaS): """Common NSX RPC callbacks for Firewall As A Service - V2.""" - def __init__(self): + def __init__(self, with_rpc): # The super code needs a configuration object with the neutron host # and an agent_mode, which our driver doesn't use. neutron_conf = cfg.CONF neutron_conf.agent_mode = 'nsx' + self.with_rpc = with_rpc super(NsxFwaasCallbacksV2, self).__init__(conf=neutron_conf) self.agent_api = DummyAgentApi() - self._core_plugin = None + self.core_plugin = self._get_core_plugin() + + def start_rpc_listeners(self, host, conf): + # Make sure RPC queue will be created only when needed + if not self.with_rpc: + return + return super(NsxFwaasCallbacksV2, self).start_rpc_listeners(host, conf) @property def plugin_type(self): pass - @property - def core_plugin(self): - """Get the NSX-V3 core plugin""" - if not self._core_plugin: - self._core_plugin = directory.get_plugin() - if self._core_plugin.is_tvd_plugin(): - # get the plugin that match this driver - self._core_plugin = self._core_plugin.get_plugin_by_type( - self.plugin_type) - return self._core_plugin + def _get_core_plugin(self): + """Get the NSX core plugin""" + core_plugin = directory.get_plugin() + if core_plugin.is_tvd_plugin(): + # get the plugin that match this driver + core_plugin = core_plugin.get_plugin_by_type( + self.plugin_type) + return core_plugin # Override functions using the agent_api that is not used by our plugin def _get_firewall_group_ports(self, context, firewall_group, @@ -80,6 +85,14 @@ fwg_port_ids = firewall_group['del-port-ids'] else: fwg_port_ids = firewall_group['add-port-ids'] + if (not firewall_group.get('del-port-ids') and + not firewall_group.get('add-port-ids') and + firewall_group.get('ports')): + # No change in ports, but policy changed so all ports are + # relevant + fwg_port_ids = firewall_group['ports'] + # Mark to the driver that this is not port deletion + firewall_group['last-port'] = False elif not require_new_plugin: routers = self._get_routers_in_project( context, firewall_group['tenant_id']) @@ -203,3 +216,33 @@ port_id=port_id).first() if entry: return entry.firewall_group_id + + def should_apply_firewall_to_router(self, context, router_id): + """Return True if there are FWaaS rules that are attached to an + interface of the given router. + """ + if not self.fwaas_enabled: + return False + + ctx = context.elevated() + router_interfaces = self.core_plugin._get_router_interfaces( + ctx, router_id) + for port in router_interfaces: + fwg_id = self._get_port_firewall_group_id(ctx, port['id']) + if fwg_id: + # check the state of this firewall group + fwg = self._get_fw_group_from_plugin(ctx, fwg_id) + if fwg is not None: + if fwg.get('status') not in (nl_constants.ERROR, + nl_constants.PENDING_DELETE): + # Found a router interface port with rules + return True + return False + + def delete_port(self, context, port_id): + # Mark the FW group as inactive if this is the last port + fwg = self.get_port_fwg(context, port_id) + if (fwg and fwg.get('status') == nl_constants.ACTIVE and + len(fwg.get('ports', [])) <= 1): + self.fwplugin_rpc.set_firewall_group_status( + context, fwg['id'], nl_constants.INACTIVE) diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/fwaas/common/fwaas_driver_base.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/fwaas/common/fwaas_driver_base.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/fwaas/common/fwaas_driver_base.py 1970-01-01 00:00:00.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/fwaas/common/fwaas_driver_base.py 2019-03-14 02:01:03.000000000 +0000 @@ -0,0 +1,89 @@ +# Copyright 2017 VMware, Inc. +# All Rights Reserved +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import abc + +from oslo_log import helpers as log_helpers +from oslo_log import log as logging + +try: + from neutron_fwaas.services.firewall.service_drivers.agents.drivers \ + import fwaas_base +except ImportError: + # FWaaS project no found + from vmware_nsx.services.fwaas.common import fwaas_mocks \ + as fwaas_base + +LOG = logging.getLogger(__name__) + + +class EdgeFwaasDriverBaseV2(fwaas_base.FwaasDriverBase): + """NSX Base driver for Firewall As A Service - V2.""" + + def __init__(self, driver_name): + super(EdgeFwaasDriverBaseV2, self).__init__() + self.driver_name = driver_name + + @log_helpers.log_method_call + def create_firewall_group(self, agent_mode, apply_list, firewall_group): + """Create the Firewall with a given policy. """ + self._validate_firewall_group(firewall_group) + self._update_backend_routers(apply_list, firewall_group['id']) + + @log_helpers.log_method_call + def update_firewall_group(self, agent_mode, apply_list, firewall_group): + """Remove previous policy and apply the new policy.""" + self._validate_firewall_group(firewall_group) + self._update_backend_routers(apply_list, firewall_group['id']) + + @log_helpers.log_method_call + def delete_firewall_group(self, agent_mode, apply_list, firewall_group): + """Delete firewall. + + Removes rules created by this instance from the backend firewall + And add the default allow rule. + """ + self._update_backend_routers(apply_list, firewall_group['id']) + + @log_helpers.log_method_call + def apply_default_policy(self, agent_mode, apply_list, firewall_group): + """Apply the default policy (deny all). + + The backend firewall always has this policy (=deny all) as default, + so we only need to delete the current rules. + """ + self._update_backend_routers(apply_list, firewall_group['id']) + + @abc.abstractmethod + def _update_backend_routers(self, apply_list, fwg_id): + """Update all the affected router on the backend""" + pass + + def _validate_firewall_group(self, firewall_group): + """Validate the rules in the firewall group""" + for rule in firewall_group['egress_rule_list']: + if (rule.get('source_ip_address') and + not rule['source_ip_address'].startswith('0.0.0.0/')): + # Ignoring interface port as we cannot set it with the ip + LOG.info("Rule %(id)s with source ips used in an egress " + "policy: interface port will be ignored in the NSX " + "rule", {'id': rule['id']}) + for rule in firewall_group['ingress_rule_list']: + if (rule.get('destination_ip_address') and + not rule['destination_ip_address'].startswith('0.0.0.0/')): + # Ignoring interface port as we cannot set it with the ip + LOG.info("Rule %(id)s with destination ips used in an " + "ingress policy: interface port will be ignored " + "in the NSX rule", {'id': rule['id']}) diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/fwaas/common/fwaas_mocks.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/fwaas/common/fwaas_mocks.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/fwaas/common/fwaas_mocks.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/fwaas/common/fwaas_mocks.py 2019-03-14 02:01:03.000000000 +0000 @@ -16,7 +16,6 @@ # This file contains FWaaS mocks, to allow the vmware nsx plugins to work when # FWaaS code does not exist, and FWaaS is not configured in neutron -FIREWALL = 'FIREWALL' FIREWALL_V2 = 'FIREWALL_V2' @@ -29,10 +28,6 @@ pass -class FirewallPlugin(object): - pass - - class FirewallPluginV2(object): pass diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/fwaas/common/utils.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/fwaas/common/utils.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/fwaas/common/utils.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/fwaas/common/utils.py 2019-03-14 02:01:03.000000000 +0000 @@ -23,12 +23,6 @@ as fwaas_constants -def is_fwaas_v1_plugin_enabled(): - fwaas_plugin = directory.get_plugin(fwaas_constants.FIREWALL) - if fwaas_plugin: - return True - - def is_fwaas_v2_plugin_enabled(): fwaas_plugin = directory.get_plugin(fwaas_constants.FIREWALL_V2) if fwaas_plugin: diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/fwaas/nsx_tv/edge_fwaas_driver_v1.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/fwaas/nsx_tv/edge_fwaas_driver_v1.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/fwaas/nsx_tv/edge_fwaas_driver_v1.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/fwaas/nsx_tv/edge_fwaas_driver_v1.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,99 +0,0 @@ -# Copyright 2017 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_log import helpers as log_helpers -from oslo_log import log as logging - -from neutron_lib.exceptions import firewall_v1 as exceptions - -from vmware_nsx.extensions import projectpluginmap -from vmware_nsx.plugins.nsx import utils as tvd_utils -from vmware_nsx.services.fwaas.nsx_v import edge_fwaas_driver as v_driver -from vmware_nsx.services.fwaas.nsx_v3 import edge_fwaas_driver_v1 as t_driver - -LOG = logging.getLogger(__name__) -FWAAS_DRIVER_NAME = 'FwaaS V1 NSX-TV driver' - -try: - from neutron_fwaas.services.firewall.service_drivers.agents.drivers \ - import fwaas_base -except ImportError: - # FWaaS project no found - from vmware_nsx.services.fwaas.common import fwaas_mocks \ - as fwaas_base - - -class EdgeFwaasTVDriverV1(fwaas_base.FwaasDriverBase): - """NSX-TV driver for Firewall As A Service - V1. - - This driver is just a wrapper calling the relevant nsx-v/t driver - """ - - def __init__(self): - super(EdgeFwaasTVDriverV1, self).__init__() - self.driver_name = FWAAS_DRIVER_NAME - - # supported drivers: - self.drivers = {} - try: - self.drivers[projectpluginmap.NsxPlugins.NSX_T] = ( - t_driver.EdgeFwaasV3DriverV1()) - except Exception: - LOG.warning("EdgeFwaasTVDriverV1 failed to initialize the NSX-T " - "driver") - self.drivers[projectpluginmap.NsxPlugins.NSX_T] = None - try: - self.drivers[projectpluginmap.NsxPlugins.NSX_V] = ( - v_driver.EdgeFwaasDriver()) - except Exception: - LOG.warning("EdgeFwaasTVDriverV1 failed to initialize the NSX-V " - "driver") - self.drivers[projectpluginmap.NsxPlugins.NSX_V] = None - - def get_T_driver(self): - return self.drivers[projectpluginmap.NsxPlugins.NSX_T] - - def get_V_driver(self): - return self.drivers[projectpluginmap.NsxPlugins.NSX_V] - - def _get_driver_for_project(self, project): - plugin_type = tvd_utils.get_tvd_plugin_type_for_project(project) - if not self.drivers.get(plugin_type): - LOG.error("Project %(project)s with plugin %(plugin)s has no " - "support for FWaaS V1", {'project': project, - 'plugin': plugin_type}) - raise exceptions.FirewallInternalDriverError( - driver=self.driver_name) - return self.drivers[plugin_type] - - @log_helpers.log_method_call - def create_firewall(self, agent_mode, apply_list, firewall): - d = self._get_driver_for_project(firewall['tenant_id']) - return d.create_firewall(agent_mode, apply_list, firewall) - - @log_helpers.log_method_call - def update_firewall(self, agent_mode, apply_list, firewall): - d = self._get_driver_for_project(firewall['tenant_id']) - return d.update_firewall(agent_mode, apply_list, firewall) - - @log_helpers.log_method_call - def delete_firewall(self, agent_mode, apply_list, firewall): - d = self._get_driver_for_project(firewall['tenant_id']) - return d.delete_firewall(agent_mode, apply_list, firewall) - - @log_helpers.log_method_call - def apply_default_policy(self, agent_mode, apply_list, firewall): - d = self._get_driver_for_project(firewall['tenant_id']) - return d.apply_default_policy(agent_mode, apply_list, firewall) diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/fwaas/nsx_tv/edge_fwaas_driver_v2.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/fwaas/nsx_tv/edge_fwaas_driver_v2.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/fwaas/nsx_tv/edge_fwaas_driver_v2.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/fwaas/nsx_tv/edge_fwaas_driver_v2.py 2019-03-14 02:01:03.000000000 +0000 @@ -20,6 +20,7 @@ from vmware_nsx.extensions import projectpluginmap from vmware_nsx.plugins.nsx import utils as tvd_utils +from vmware_nsx.services.fwaas.nsx_v import edge_fwaas_driver_v2 as v_driver from vmware_nsx.services.fwaas.nsx_v3 import edge_fwaas_driver_v2 as t_driver LOG = logging.getLogger(__name__) @@ -36,15 +37,13 @@ class EdgeFwaasTVDriverV2(fwaas_base_v2.FwaasDriverBase): """NSX-TV driver for Firewall As A Service - V2. - - This driver is just a wrapper calling the relevant nsx-v3 driver """ def __init__(self): super(EdgeFwaasTVDriverV2, self).__init__() self.driver_name = FWAAS_DRIVER_NAME - # supported drivers (Only NSX-T): + # supported drivers: self.drivers = {} try: self.drivers[projectpluginmap.NsxPlugins.NSX_T] = ( @@ -53,10 +52,20 @@ LOG.warning("EdgeFwaasTVDriverV2 failed to initialize the NSX-T " "driver") self.drivers[projectpluginmap.NsxPlugins.NSX_T] = None + try: + self.drivers[projectpluginmap.NsxPlugins.NSX_V] = ( + v_driver.EdgeFwaasVDriverV2()) + except Exception: + LOG.warning("EdgeFwaasTVDriverV2 failed to initialize the NSX-V " + "driver") + self.drivers[projectpluginmap.NsxPlugins.NSX_V] = None def get_T_driver(self): return self.drivers[projectpluginmap.NsxPlugins.NSX_T] + def get_V_driver(self): + return self.drivers[projectpluginmap.NsxPlugins.NSX_V] + def _get_driver_for_project(self, project): plugin_type = tvd_utils.get_tvd_plugin_type_for_project(project) if not self.drivers.get(plugin_type): @@ -87,8 +96,12 @@ d = self._get_driver_for_project(firewall_group['tenant_id']) return d.apply_default_policy(agent_mode, apply_list, firewall_group) - def translate_addresses_to_target(self, cidrs, fwaas_rule_id=None): + def translate_addresses_to_target(self, cidrs, plugin_type, + fwaas_rule_id=None): # This api is called directly from the core plugin - # Assuming nsx-T as it is the only one supported now. - return self.get_T_driver().translate_addresses_to_target( - cidrs, fwaas_rule_id=fwaas_rule_id) + if not self.drivers.get(plugin_type): + LOG.error("%s has no support for plugin %s", + self.driver_name, plugin_type) + else: + return self.drivers[plugin_type].translate_addresses_to_target( + cidrs, fwaas_rule_id=fwaas_rule_id) diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/fwaas/nsx_tv/plugin_v1.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/fwaas/nsx_tv/plugin_v1.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/fwaas/nsx_tv/plugin_v1.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/fwaas/nsx_tv/plugin_v1.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,52 +0,0 @@ -# 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 neutron_lib import exceptions as n_exc -from neutron_lib.plugins import directory - -from vmware_nsx.plugins.nsx import utils as tvd_utils - -try: - from neutron_fwaas.services.firewall import fwaas_plugin -except ImportError: - # FWaaS project no found - from vmware_nsx.services.fwaas.common import fwaas_mocks \ - as fwaas_plugin - - -@tvd_utils.filter_plugins -class FwaasTVPluginV1(fwaas_plugin.FirewallPlugin): - """NSX-TV plugin for Firewall As A Service - V1. - - This plugin adds separation between T/V instances - """ - methods_to_separate = ['get_firewalls', - 'get_firewall_policies', - 'get_firewall_rules'] - - def validate_firewall_routers_not_in_use( - self, context, router_ids, fwid=None): - # Override this method to verify that the router & firewall belongs to - # the same plugin - context_plugin_type = tvd_utils.get_tvd_plugin_type_for_project( - context.project_id, context) - core_plugin = directory.get_plugin() - for rtr_id in router_ids: - rtr_plugin = core_plugin._get_plugin_from_router_id( - context, rtr_id) - if rtr_plugin.plugin_type() != context_plugin_type: - err_msg = (_('Router should belong to the %s plugin ' - 'as the firewall') % context_plugin_type) - raise n_exc.InvalidInput(error_message=err_msg) diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/fwaas/nsx_v/edge_fwaas_driver.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/fwaas/nsx_v/edge_fwaas_driver.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/fwaas/nsx_v/edge_fwaas_driver.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/fwaas/nsx_v/edge_fwaas_driver.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,269 +0,0 @@ -# Copyright 2017 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 neutron_lib import context as n_context -from neutron_lib.exceptions import firewall_v1 as exceptions -from neutron_lib.plugins import directory -from oslo_log import helpers as log_helpers -from oslo_log import log as logging - -from vmware_nsx.common import locking -from vmware_nsx.extensions import projectpluginmap -from vmware_nsx.plugins.nsx_v.vshield import edge_utils - -LOG = logging.getLogger(__name__) -FWAAS_DRIVER_NAME = 'Fwaas V1 NSX-V driver' -RULE_NAME_PREFIX = 'Fwaas-' - -try: - from neutron_fwaas.services.firewall.service_drivers.agents.drivers \ - import fwaas_base -except ImportError: - # FWaaS project no found - from vmware_nsx.services.fwaas.common import fwaas_mocks \ - as fwaas_base - - -class EdgeFwaasDriver(fwaas_base.FwaasDriverBase): - """NSX-V driver for Firewall As A Service - V1.""" - - @property - def core_plugin(self): - if not self._core_plugin: - self._core_plugin = directory.get_plugin() - if self._core_plugin.is_tvd_plugin(): - self._core_plugin = self._core_plugin.get_plugin_by_type( - projectpluginmap.NsxPlugins.NSX_V) - # make sure plugin init was completed - if not self._core_plugin.init_is_complete: - self._core_plugin.init_complete(None, None, {}) - return self._core_plugin - - @property - def edge_manager(self): - return self.core_plugin.edge_manager - - def __init__(self): - LOG.debug("Loading FWaaS V1 NsxVDriver.") - super(EdgeFwaasDriver, self).__init__() - self.driver_name = FWAAS_DRIVER_NAME - self._core_plugin = None - - def should_apply_firewall_to_router(self, router_data, - raise_exception=True): - """Return True if the firewall rules should be added the router - - Return False in those cases: - - router without an external gateway (rule may be added later when - there is a gateway) - - Raise an exception if the router is unsupported - (and raise_exception is True): - - shared router (not supported) - - md proxy router (not supported) - - """ - if (not router_data.get('distributed') and - router_data.get('router_type') == 'shared'): - LOG.error("Cannot apply firewall to shared router %s", - router_data['id']) - if raise_exception: - raise exceptions.FirewallInternalDriverError( - driver=self.driver_name) - return False - - if router_data.get('name', '').startswith('metadata_proxy_router'): - LOG.error("Cannot apply firewall to the metadata proxy router %s", - router_data['id']) - if raise_exception: - raise exceptions.FirewallInternalDriverError( - driver=self.driver_name) - return False - - if not router_data.get('external_gateway_info'): - LOG.info("Cannot apply firewall to router %s with no gateway", - router_data['id']) - return False - - return True - - def _get_routers_edges(self, context, apply_list, delete_fw=False): - # Get edges for all the routers in the apply list. - # note that shared routers are currently not supported - edge_manager = self.edge_manager - edges_map = {} - for router_info in apply_list: - - # No FWaaS rules needed if there is no external gateway - if not self.should_apply_firewall_to_router( - router_info.router, raise_exception=(not delete_fw)): - continue - - lookup_id = None - router_id = router_info.router_id - if router_info.router.get('distributed'): - # Distributed router - # we need the plr edge id - lookup_id = edge_manager.get_plr_by_tlr_id( - context, router_id) - else: - # Exclusive router - lookup_id = router_id - if lookup_id: - # look for the edge id in the DB - edge_id = edge_utils.get_router_edge_id(context, lookup_id) - if edge_id: - edges_map[router_id] = {'edge_id': edge_id, - 'lookup_id': lookup_id} - return edges_map - - def _translate_rules(self, fwaas_rules, logged=False): - translated_rules = [] - for rule in fwaas_rules: - if not rule['enabled']: - # skip disabled rules - continue - # Make sure the rule has a name, and it starts with the prefix - # (backend max name length is 30) - if rule.get('name'): - rule['name'] = RULE_NAME_PREFIX + rule['name'] - else: - rule['name'] = RULE_NAME_PREFIX + rule['id'] - rule['name'] = rule['name'][:30] - # source & destination should be lists - if rule.get('destination_ip_address'): - rule['destination_ip_address'] = [ - rule['destination_ip_address']] - if rule.get('source_ip_address'): - rule['source_ip_address'] = [rule['source_ip_address']] - if logged: - rule['logged'] = True - translated_rules.append(rule) - - return translated_rules - - def _set_rules_on_router_edge(self, context, router_id, neutron_id, - edge_id, fw_id, translated_rules, - delete_fw=False): - """Recreate router edge firewall rules - - Using the plugin code to recreate all the rules with the additional - FWaaS rules. - - router_id is the is of the router about to be updated - (in case of distributed router - the plr) - neutron_id is the neutron router id - """ - # update the backend - router_db = self.core_plugin._get_router(context, neutron_id) - try: - with locking.LockManager.get_lock(str(edge_id)): - self.core_plugin.update_router_firewall( - context, router_id, router_db, - fwaas_rules=translated_rules) - except Exception as e: - # catch known library exceptions and raise Fwaas generic exception - LOG.error("Failed to update firewall %(fw)s on edge %(edge_id)s: " - "%(e)s", {'e': e, 'fw': fw_id, 'edge_id': edge_id}) - raise exceptions.FirewallInternalDriverError( - driver=self.driver_name) - - def _create_or_update_firewall(self, agent_mode, apply_list, firewall): - # admin state down means default block rule firewall - if not firewall['admin_state_up']: - self.apply_default_policy(agent_mode, apply_list, firewall) - return - - # get router-edge mapping - context = n_context.get_admin_context() - edges_map = self._get_routers_edges(context, apply_list) - if not edges_map: - routers = [r.router_id for r in apply_list] - LOG.warning("Cannot apply the firewall %(fw)s to any of the " - "routers %(rtrs)s", - {'fw': firewall['id'], 'rtrs': routers}) - return - - # Translate the FWaaS rules - # TODO(asarfaty): get this value from the firewall extensions - logged = False - rules = self._translate_rules(firewall['firewall_rule_list'], - logged=logged) - - # update each relevant edge with the new rules - for router_info in apply_list: - neutron_id = router_info.router_id - info = edges_map.get(neutron_id) - if info: - self._set_rules_on_router_edge( - context, info['lookup_id'], neutron_id, info['edge_id'], - firewall['id'], rules) - - @log_helpers.log_method_call - def create_firewall(self, agent_mode, apply_list, firewall): - """Create the Firewall with a given policy. """ - self._create_or_update_firewall(agent_mode, apply_list, firewall) - - @log_helpers.log_method_call - def update_firewall(self, agent_mode, apply_list, firewall): - """Remove previous policy and apply the new policy.""" - self._create_or_update_firewall(agent_mode, apply_list, firewall) - - def _delete_firewall_or_set_default_policy(self, apply_list, firewall, - delete_fw=False): - # get router-edge mapping - context = n_context.get_admin_context() - edges_map = self._get_routers_edges(context, apply_list, - delete_fw=delete_fw) - - # if the firewall is deleted, rules should be None - rules = None if delete_fw else [] - - # Go over all routers and update them on backend - for router_info in apply_list: - neutron_id = router_info.router_id - info = edges_map.get(neutron_id) - if info: - self._set_rules_on_router_edge( - context, info['lookup_id'], neutron_id, info['edge_id'], - firewall['id'], rules, delete_fw=delete_fw) - - @log_helpers.log_method_call - def delete_firewall(self, agent_mode, apply_list, firewall): - """Delete firewall. - - Removes rules created by this instance from the backend firewall - And add the default allow-external rule. - """ - self._delete_firewall_or_set_default_policy(apply_list, firewall, - delete_fw=True) - - @log_helpers.log_method_call - def apply_default_policy(self, agent_mode, apply_list, firewall): - """Apply the default policy (deny all). - - The backend firewall always has this policy (=deny all) as default, - so we only need to delete the current rules. - """ - self._delete_firewall_or_set_default_policy(apply_list, firewall, - delete_fw=False) - - def get_firewall_translated_rules(self, firewall): - if firewall['admin_state_up']: - # TODO(asarfaty): get this value from the firewall extensions - logged = False - return self._translate_rules(firewall['firewall_rule_list'], - logged=logged) - return [] diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/fwaas/nsx_v/edge_fwaas_driver_v2.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/fwaas/nsx_v/edge_fwaas_driver_v2.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/fwaas/nsx_v/edge_fwaas_driver_v2.py 1970-01-01 00:00:00.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/fwaas/nsx_v/edge_fwaas_driver_v2.py 2019-03-14 02:01:03.000000000 +0000 @@ -0,0 +1,142 @@ +# 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 neutron_lib import context as n_context +from oslo_log import log as logging + +from neutron_lib.exceptions import firewall_v2 as exceptions +from neutron_lib.plugins import directory + +from vmware_nsx.common import locking +from vmware_nsx.extensions import projectpluginmap +from vmware_nsx.plugins.nsx_v.vshield import edge_utils +from vmware_nsx.services.fwaas.common import fwaas_driver_base + +LOG = logging.getLogger(__name__) +FWAAS_DRIVER_NAME = 'Fwaas V2 NSX-V driver' + + +class EdgeFwaasVDriverV2(fwaas_driver_base.EdgeFwaasDriverBaseV2): + """NSX-V driver for Firewall As A Service - V2.""" + + def __init__(self): + super(EdgeFwaasVDriverV2, self).__init__(FWAAS_DRIVER_NAME) + self._core_plugin = None + + @property + def core_plugin(self): + """Get the NSX-V core plugin""" + if not self._core_plugin: + self._core_plugin = directory.get_plugin() + if self._core_plugin.is_tvd_plugin(): + self._core_plugin = self._core_plugin.get_plugin_by_type( + projectpluginmap.NsxPlugins.NSX_V) + if not self._core_plugin: + # The NSX-V plugin was not initialized + return + # make sure plugin init was completed + if not self._core_plugin.init_is_complete: + self._core_plugin.init_complete(None, None, {}) + return self._core_plugin + + def should_apply_firewall_to_router(self, router_data, + raise_exception=True): + """Return True if the firewall rules allowed to be added the router + + Return False in those cases: + - router without an external gateway (rule may be added later when + there is a gateway) + + Raise an exception if the router is unsupported + (and raise_exception is True): + - shared router (not supported) + - md proxy router (not supported) + + """ + if (not router_data.get('distributed') and + router_data.get('router_type') == 'shared'): + LOG.error("Cannot apply firewall to shared router %s", + router_data['id']) + if raise_exception: + raise exceptions.FirewallInternalDriverError( + driver=self.driver_name) + return False + + if router_data.get('name', '').startswith('metadata_proxy_router'): + LOG.error("Cannot apply firewall to the metadata proxy router %s", + router_data['id']) + if raise_exception: + raise exceptions.FirewallInternalDriverError( + driver=self.driver_name) + return False + + if not router_data.get('external_gateway_info'): + LOG.info("Cannot apply firewall to router %s with no gateway", + router_data['id']) + return False + + return True + + def _update_backend_routers(self, apply_list, fwg_id): + """Update all the affected routers on the backend""" + LOG.info("Updating routers firewall for firewall group %s", fwg_id) + context = n_context.get_admin_context() + routers = set() + routers_mapping = {} + # the apply_list is a list of tuples: routerInfo, port-id + for router_info, port_id in apply_list: + # Skip dummy entries that were added only to avoid errors + if isinstance(router_info, str): + continue + # Skip unsupported routers + if not self.should_apply_firewall_to_router(router_info.router): + continue + + lookup_id = None + router_id = router_info.router_id + if router_info.router.get('distributed'): + # Distributed router (need to update the plr edge) + lookup_id = self.core_plugin.edge_manager.get_plr_by_tlr_id( + context, router_id) + else: + # Exclusive router + lookup_id = router_id + if lookup_id: + # look for the edge id in the DB + edge_id = edge_utils.get_router_edge_id(context, lookup_id) + if edge_id: + routers_mapping[router_id] = {'edge_id': edge_id, + 'lookup_id': lookup_id} + routers.add(router_id) + + # update each router once using the core plugin + for router_id in routers: + router_db = self.core_plugin._get_router(context, router_id) + edge_id = routers_mapping[router_id]['edge_id'] + LOG.info("Updating FWaaS rules for router %s on edge %s", + router_id, edge_id) + router_lookup_id = routers_mapping[router_id]['lookup_id'] + try: + with locking.LockManager.get_lock(str(edge_id)): + self.core_plugin.update_router_firewall( + context, router_lookup_id, router_db) + except Exception as e: + # catch known library exceptions and raise Fwaas generic + # exception + LOG.error("Failed to update firewall rules on edge " + "%(edge_id)s for router %(rtr)s: %(e)s", + {'e': e, 'rtr': router_id, 'edge_id': edge_id}) + raise exceptions.FirewallInternalDriverError( + driver=self.driver_name) diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/fwaas/nsx_v/fwaas_callbacks.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/fwaas/nsx_v/fwaas_callbacks.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/fwaas/nsx_v/fwaas_callbacks.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/fwaas/nsx_v/fwaas_callbacks.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,82 +0,0 @@ -# Copyright 2017 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_log import log as logging - -from vmware_nsx.extensions import projectpluginmap -from vmware_nsx.services.fwaas.common import fwaas_callbacks_v1 as com_clbcks -from vmware_nsx.services.fwaas.nsx_tv import edge_fwaas_driver_v1 as tv_driver - -LOG = logging.getLogger(__name__) - - -class NsxvFwaasCallbacks(com_clbcks.NsxFwaasCallbacks): - """NSX-V RPC callbacks for Firewall As A Service - V1.""" - - def __init__(self): - super(NsxvFwaasCallbacks, self).__init__() - # update the fwaas driver in case of TV plugin - if self.fwaas_enabled: - if self.fwaas_driver.driver_name == tv_driver.FWAAS_DRIVER_NAME: - self.internal_driver = self.fwaas_driver.get_V_driver() - else: - self.internal_driver = self.fwaas_driver - - @property - def plugin_type(self): - return projectpluginmap.NsxPlugins.NSX_V - - def should_apply_firewall_to_router(self, context, router, router_id): - """Return True if the FWaaS rules should be added to this router.""" - # in case of a distributed-router: - # router['id'] is the id of the neutron router (=tlr) - # and router_id is the plr/tlr (the one that is being updated) - if not super(NsxvFwaasCallbacks, self).should_apply_firewall_to_router( - context, router['id']): - return False - - # get all the relevant router info - # ("router" does not have all the fields) - ctx_elevated = context.elevated() - router_data = self.core_plugin.get_router(ctx_elevated, router['id']) - if not router_data: - LOG.error("Couldn't read router %s data", router['id']) - return False - - if router_data.get('distributed'): - if router_id == router['id']: - # Do not add firewall rules on the tlr router. - return False - - # Check if the FWaaS driver supports this router - if not self.internal_driver.should_apply_firewall_to_router( - router_data, raise_exception=False): - return False - - return True - - def get_fwaas_rules_for_router(self, context, router_id): - """Return the list of (translated) FWaaS rules for this router.""" - ctx_elevated = context.elevated() - fw_id = self._get_router_firewall_id(ctx_elevated, router_id) - if fw_id: - return self._get_fw_applicable_rules(ctx_elevated, fw_id) - return [] - - def _get_fw_applicable_rules(self, context, fw_id): - fw = self._get_fw_from_plugin(context, fw_id) - if fw is not None and fw['id'] == fw_id: - return self.internal_driver.get_firewall_translated_rules(fw) - return [] diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/fwaas/nsx_v/fwaas_callbacks_v2.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/fwaas/nsx_v/fwaas_callbacks_v2.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/fwaas/nsx_v/fwaas_callbacks_v2.py 1970-01-01 00:00:00.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/fwaas/nsx_v/fwaas_callbacks_v2.py 2019-03-14 02:01:03.000000000 +0000 @@ -0,0 +1,169 @@ +# 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_log import log as logging + +from vmware_nsx.db import nsxv_db +from vmware_nsx.extensions import projectpluginmap +from vmware_nsx.plugins.nsx_v.vshield import edge_firewall_driver +from vmware_nsx.services.fwaas.common import fwaas_callbacks_v2 as \ + com_callbacks +from vmware_nsx.services.fwaas.nsx_tv import edge_fwaas_driver_v2 as tv_driver + +LOG = logging.getLogger(__name__) +RULE_NAME_PREFIX = 'Fwaas-' + + +class NsxvFwaasCallbacksV2(com_callbacks.NsxFwaasCallbacksV2): + """NSX-V RPC callbacks for Firewall As A Service - V2.""" + + def __init__(self, with_rpc): + super(NsxvFwaasCallbacksV2, self).__init__(with_rpc) + # update the fwaas driver in case of TV plugin + self.internal_driver = None + if self.fwaas_enabled: + if self.fwaas_driver.driver_name == tv_driver.FWAAS_DRIVER_NAME: + self.internal_driver = self.fwaas_driver.get_V_driver() + else: + self.internal_driver = self.fwaas_driver + + @property + def plugin_type(self): + return projectpluginmap.NsxPlugins.NSX_V + + def should_apply_firewall_to_router(self, context, router, router_id): + """Return True if the FWaaS rules should be added to this router.""" + # in case of a distributed-router: + # router['id'] is the id of the neutron router (=tlr) + # and router_id is the plr/tlr (the one that is being updated) + + # First check if there are rules attached to this router + if not super(NsxvFwaasCallbacksV2, + self).should_apply_firewall_to_router( + context, router['id']): + return False + + # get all the relevant router info + # ("router" does not have all the fields) + ctx_elevated = context.elevated() + router_data = self.core_plugin.get_router(ctx_elevated, router['id']) + if not router_data: + LOG.error("Couldn't read router %s data", router['id']) + return False + + if router_data.get('distributed'): + if router_id == router['id']: + # Do not add firewall rules on the tlr router. + return False + + # Check if the FWaaS driver supports this router + if not self.internal_driver.should_apply_firewall_to_router( + router_data, raise_exception=False): + return False + + return True + + def get_fwaas_rules_for_router(self, context, router_id, edge_id): + """Return the list of (translated) FWaaS rules for this router.""" + ctx_elevated = context.elevated() + router_interfaces = self.core_plugin._get_router_interfaces( + ctx_elevated, router_id) + + fw_rules = [] + # Add firewall rules per port attached to a firewall group + for port in router_interfaces: + fwg = self.get_port_fwg(ctx_elevated, port['id']) + if fwg: + # get the interface vnic + edge_vnic_bind = nsxv_db.get_edge_vnic_binding( + context.session, edge_id, port['network_id']) + vnic_id = 'vnic-index-%s' % edge_vnic_bind.vnic_index + # Add the FWaaS rules for this port + fw_rules.extend( + self.get_port_translated_rules(vnic_id, fwg)) + + return fw_rules + + def get_port_translated_rules(self, vnic_id, firewall_group): + """Return the list of translated rules per port + + Ingress/Egress firewall rules + default ingress/egress drop + """ + port_rules = [] + logged = False + # Add the firewall group ingress/egress rules only if the fw is up + if firewall_group['admin_state_up']: + port_rules.extend(self.translate_rules( + firewall_group['ingress_rule_list'], + replace_dest=vnic_id, + logged=logged, + is_ingress=True)) + port_rules.extend(self.translate_rules( + firewall_group['egress_rule_list'], + replace_src=vnic_id, + logged=logged, + is_ingress=False)) + + # Add ingress/egress block rules for this port + port_rules.extend([ + {'name': "Block port ingress", + 'action': edge_firewall_driver.FWAAS_DENY, + 'destination_vnic_groups': [vnic_id], + 'logged': logged}, + {'name': "Block port egress", + 'action': edge_firewall_driver.FWAAS_DENY, + 'source_vnic_groups': [vnic_id], + 'logged': logged}]) + + return port_rules + + def translate_rules(self, fwaas_rules, replace_dest=None, replace_src=None, + logged=False, is_ingress=True): + translated_rules = [] + for rule in fwaas_rules: + if not rule['enabled']: + # skip disabled rules + continue + # Make sure the rule has a name, and it starts with the prefix + # (backend max name length is 30) + if rule.get('name'): + rule['name'] = RULE_NAME_PREFIX + rule['name'] + else: + rule['name'] = RULE_NAME_PREFIX + rule['id'] + rule['name'] = rule['name'][:30] + if rule.get('id'): + # update rules ID to prevent DB duplications in + # NsxvEdgeFirewallRuleBinding + if is_ingress: + rule['id'] = ('ingress-%s' % rule['id'])[:36] + else: + rule['id'] = ('egress-%s' % rule['id'])[:36] + # source & destination should be lists + if (rule.get('destination_ip_address') and + not rule['destination_ip_address'].startswith('0.0.0.0/')): + rule['destination_ip_address'] = [ + rule['destination_ip_address']] + elif replace_dest: + rule['destination_vnic_groups'] = [replace_dest] + if (rule.get('source_ip_address') and + not rule['source_ip_address'].startswith('0.0.0.0/')): + rule['source_ip_address'] = [rule['source_ip_address']] + elif replace_src: + rule['source_vnic_groups'] = [replace_src] + if logged: + rule['logged'] = True + translated_rules.append(rule) + + return translated_rules diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/fwaas/nsx_v3/edge_fwaas_driver_base.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/fwaas/nsx_v3/edge_fwaas_driver_base.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/fwaas/nsx_v3/edge_fwaas_driver_base.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/fwaas/nsx_v3/edge_fwaas_driver_base.py 2019-03-14 02:01:03.000000000 +0000 @@ -23,27 +23,21 @@ from oslo_log import log as logging from vmware_nsx.extensions import projectpluginmap +from vmware_nsx.services.fwaas.common import fwaas_driver_base from vmware_nsxlib.v3 import nsx_constants as consts LOG = logging.getLogger(__name__) RULE_NAME_PREFIX = 'Fwaas-' DEFAULT_RULE_NAME = 'Default LR Layer3 Rule' -try: - from neutron_fwaas.services.firewall.service_drivers.agents.drivers \ - import fwaas_base -except ImportError: - # FWaaS project no found - from vmware_nsx.services.fwaas.common import fwaas_mocks \ - as fwaas_base - -class CommonEdgeFwaasV3Driver(fwaas_base.FwaasDriverBase): +#TODO(asarfaty): this base class now serves only 1 driver and can be merged +# with it +class CommonEdgeFwaasV3Driver(fwaas_driver_base.EdgeFwaasDriverBaseV2): """Base class for NSX-V3 driver for Firewall As A Service - V1 & V2.""" def __init__(self, driver_exception, driver_name): - super(CommonEdgeFwaasV3Driver, self).__init__() - self.driver_name = driver_name + super(CommonEdgeFwaasV3Driver, self).__init__(driver_name) self.backend_support = True self.driver_exception = driver_exception registry.subscribe( @@ -89,10 +83,12 @@ self.backend_support = False def should_apply_firewall_to_router(self, router_data): - """Return True if the firewall rules should be added the router + """Return True if the firewall rules should be added the router""" + if not router_data.get('external_gateway_info'): + LOG.info("Cannot apply firewall to router %s with no gateway", + router_data['id']) + return False - Right now the driver supports for all routers. - """ return True def _translate_action(self, fwaas_action, fwaas_rule_id): @@ -115,16 +111,32 @@ raise self.driver_exception(driver=self.driver_name) def _translate_cidr(self, cidr, fwaas_rule_id): - if cidr and cidr.startswith('0.0.0.0/'): - LOG.warning("Unsupported FWAAS cidr %(cidr)s for rule %(id)s", { - 'cidr': cidr, 'id': fwaas_rule_id}) - return + # Validate that this is a legal & supported ipv4 / ipv6 cidr + error_msg = (_("Unsupported FWAAS cidr %(cidr)s for rule %(id)s") % { + 'cidr': cidr, 'id': fwaas_rule_id}) + net = netaddr.IPNetwork(cidr) + if net.version == 4: + if cidr.startswith('0.0.0.0/'): + # Treat as ANY and just log warning + LOG.warning(error_msg) + return + if net.prefixlen == 0: + LOG.error(error_msg) + raise self.driver_exception(driver=self.driver_name) + elif net.version == 6: + if str(net.ip) == "::" or net.prefixlen == 0: + LOG.error(error_msg) + raise self.driver_exception(driver=self.driver_name) + else: + LOG.error(error_msg) + raise self.driver_exception(driver=self.driver_name) return self.nsx_firewall.get_ip_cidr_reference( cidr, - consts.IPV6 if netaddr.valid_ipv6(cidr) else consts.IPV4) + consts.IPV6 if net.version == 6 else consts.IPV4) - def translate_addresses_to_target(self, cidrs, fwaas_rule_id=None): + def translate_addresses_to_target(self, cidrs, plugin_type, + fwaas_rule_id=None): translated_cidrs = [] for ip in cidrs: res = self._translate_cidr(ip, fwaas_rule_id) @@ -194,28 +206,33 @@ nsx_rule['notes'] = rule['description'] nsx_rule['action'] = self._translate_action( rule['action'], rule['id']) - if replace_dest: - # set this value as the destination logical switch, - # and set the rule to ingress - nsx_rule['destinations'] = [{'target_type': 'LogicalSwitch', - 'target_id': replace_dest}] - nsx_rule['direction'] = 'IN' - elif rule.get('destination_ip_address'): + if (rule.get('destination_ip_address') and + not rule['destination_ip_address'].startswith('0.0.0.0/')): nsx_rule['destinations'] = self.translate_addresses_to_target( [rule['destination_ip_address']], rule['id']) - if replace_src: + elif replace_dest: + # set this value as the destination logical switch + # (only if no dest IP) + nsx_rule['destinations'] = [{'target_type': 'LogicalSwitch', + 'target_id': replace_dest}] + if (rule.get('source_ip_address') and + not rule['source_ip_address'].startswith('0.0.0.0/')): + nsx_rule['sources'] = self.translate_addresses_to_target( + [rule['source_ip_address']], rule['id']) + elif replace_src: # set this value as the source logical switch, - # and set the rule to egress + # (only if no source IP) nsx_rule['sources'] = [{'target_type': 'LogicalSwitch', 'target_id': replace_src}] - nsx_rule['direction'] = 'OUT' - elif rule.get('source_ip_address'): - nsx_rule['sources'] = self.translate_addresses_to_target( - [rule['source_ip_address']], rule['id']) if rule.get('protocol'): nsx_rule['services'] = self._translate_services(rule) if logged: nsx_rule['logged'] = logged + # Set rule direction + if replace_src: + nsx_rule['direction'] = 'OUT' + elif replace_dest: + nsx_rule['direction'] = 'IN' translated_rules.append(nsx_rule) return translated_rules diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/fwaas/nsx_v3/edge_fwaas_driver_v1.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/fwaas/nsx_v3/edge_fwaas_driver_v1.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/fwaas/nsx_v3/edge_fwaas_driver_v1.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/fwaas/nsx_v3/edge_fwaas_driver_v1.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,122 +0,0 @@ -# Copyright 2017 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 neutron_lib import context as n_context -from oslo_log import helpers as log_helpers -from oslo_log import log as logging - -from neutron_lib.exceptions import firewall_v1 as exceptions - -from vmware_nsx.services.fwaas.nsx_v3 import edge_fwaas_driver_base as \ - base_driver - -LOG = logging.getLogger(__name__) -FWAAS_DRIVER_NAME = 'Fwaas V1 NSX-V3 driver' -NSX_FW_TAG = 'os-neutron-fw-id' - - -class EdgeFwaasV3DriverV1(base_driver.CommonEdgeFwaasV3Driver): - """NSX-V3 driver for Firewall As A Service - V1.""" - - def __init__(self): - exception_cls = exceptions.FirewallInternalDriverError - super(EdgeFwaasV3DriverV1, self).__init__(exception_cls, - FWAAS_DRIVER_NAME) - - @log_helpers.log_method_call - def create_firewall(self, agent_mode, apply_list, firewall): - """Create the Firewall with a given policy. """ - self._update_backend_routers(apply_list, firewall['id']) - - @log_helpers.log_method_call - def update_firewall(self, agent_mode, apply_list, firewall): - """Remove previous policy and apply the new policy.""" - self._update_backend_routers(apply_list, firewall['id']) - - @log_helpers.log_method_call - def delete_firewall(self, agent_mode, apply_list, firewall): - """Delete firewall. - - Removes rules created by this instance from the backend firewall - And add the default allow rule. - """ - self._update_backend_routers(apply_list, firewall['id']) - - @log_helpers.log_method_call - def apply_default_policy(self, agent_mode, apply_list, firewall): - """Apply the default policy (deny all). - - The backend firewall always has this policy (=deny all) as default, - so we only need to delete the current rules. - """ - self._update_backend_routers(apply_list, firewall['id']) - - def _update_backend_routers(self, apply_list, fw_id): - """"Update each router on the backend using the core plugin code""" - self.validate_backend_version() - context = n_context.get_admin_context() - for router_info in apply_list: - # Skip unsupported routers - if not self.should_apply_firewall_to_router(router_info.router): - continue - - self.core_plugin.update_router_firewall( - context, router_info.router_id) - - def update_nsx_router_tags(self, nsx_router_id, fw_id=None): - """Update the backend router with tags marking the attached fw id""" - # Get the current tags - nsx_router = self.nsx_router.get(nsx_router_id) - if 'tags' not in nsx_router: - nsx_router['tags'] = [] - tags = nsx_router['tags'] - - # Look for the firewall tag and update/remove it - update_tags = False - found_tag = False - for tag in tags: - if tag.get('scope') == NSX_FW_TAG: - found_tag = True - if not fw_id: - tags.remove(tag) - update_tags = True - break - if fw_id != tag.get('tag'): - tag['tag'] = fw_id - update_tags = True - break - # Add the tag if not found - if fw_id and not found_tag: - tags.append({'scope': NSX_FW_TAG, - 'tag': fw_id}) - update_tags = True - - # update tags on the backend router - if update_tags: - self.nsx_router.update(nsx_router_id, tags=tags) - - def get_router_translated_rules(self, router_id, firewall): - """Return the list of translated rules - - The default drop all will be added later - """ - # Return the firewall rules only if the fw is up - if firewall['admin_state_up']: - # TODO(asarfaty): get this value from the firewall extensions - logged = False - return self._translate_rules(firewall['firewall_rule_list'], - logged=logged) - - return [] diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/fwaas/nsx_v3/edge_fwaas_driver_v2.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/fwaas/nsx_v3/edge_fwaas_driver_v2.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/fwaas/nsx_v3/edge_fwaas_driver_v2.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/fwaas/nsx_v3/edge_fwaas_driver_v2.py 2019-03-14 02:01:03.000000000 +0000 @@ -14,7 +14,6 @@ # under the License. from neutron_lib import context as n_context -from oslo_log import helpers as log_helpers from oslo_log import log as logging from neutron_lib.exceptions import firewall_v2 as exceptions @@ -35,36 +34,6 @@ super(EdgeFwaasV3DriverV2, self).__init__(exception_cls, FWAAS_DRIVER_NAME) - @log_helpers.log_method_call - def create_firewall_group(self, agent_mode, apply_list, firewall_group): - """Create the Firewall with a given policy. """ - self._validate_firewall_group(firewall_group) - self._update_backend_routers(apply_list, firewall_group['id']) - - @log_helpers.log_method_call - def update_firewall_group(self, agent_mode, apply_list, firewall_group): - """Remove previous policy and apply the new policy.""" - self._validate_firewall_group(firewall_group) - self._update_backend_routers(apply_list, firewall_group['id']) - - @log_helpers.log_method_call - def delete_firewall_group(self, agent_mode, apply_list, firewall_group): - """Delete firewall. - - Removes rules created by this instance from the backend firewall - And add the default allow rule. - """ - self._update_backend_routers(apply_list, firewall_group['id']) - - @log_helpers.log_method_call - def apply_default_policy(self, agent_mode, apply_list, firewall_group): - """Apply the default policy (deny all). - - The backend firewall always has this policy (=deny all) as default, - so we only need to delete the current rules. - """ - self._update_backend_routers(apply_list, firewall_group['id']) - def _update_backend_routers(self, apply_list, fwg_id): """Update all the affected router on the backend""" self.validate_backend_version() @@ -121,22 +90,3 @@ 'direction': 'OUT'}]) return port_rules - - def _validate_firewall_group(self, firewall_group): - """Validate the rules in the firewall group""" - for rule in firewall_group['egress_rule_list']: - if rule.get('source_ip_address'): - # this rule cannot be used as egress rule - LOG.error("Rule %(id)s cannot be used in an egress " - "policy because it has a source", - {'id': rule['id']}) - raise exceptions.FirewallInternalDriverError( - driver=FWAAS_DRIVER_NAME) - for rule in firewall_group['ingress_rule_list']: - if rule.get('destination_ip_address'): - # this rule cannot be used as ingress rule - LOG.error("Rule %(id)s cannot be used in an ingress " - "policy because it has a destination", - {'id': rule['id']}) - raise exceptions.FirewallInternalDriverError( - driver=FWAAS_DRIVER_NAME) diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/fwaas/nsx_v3/fwaas_callbacks_v1.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/fwaas/nsx_v3/fwaas_callbacks_v1.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/fwaas/nsx_v3/fwaas_callbacks_v1.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/fwaas/nsx_v3/fwaas_callbacks_v1.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,102 +0,0 @@ -# Copyright 2017 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_log import log as logging - -from vmware_nsx.extensions import projectpluginmap -from vmware_nsx.services.fwaas.common import fwaas_callbacks_v1 as com_clbcks -from vmware_nsx.services.fwaas.nsx_tv import edge_fwaas_driver_v1 as tv_driver - -LOG = logging.getLogger(__name__) - - -class Nsxv3FwaasCallbacksV1(com_clbcks.NsxFwaasCallbacks): - """NSX-V3 RPC callbacks for Firewall As A Service - V1.""" - - def __init__(self): - super(Nsxv3FwaasCallbacksV1, self).__init__() - # update the fwaas driver in case of TV plugin - if self.fwaas_enabled: - if self.fwaas_driver.driver_name == tv_driver.FWAAS_DRIVER_NAME: - self.internal_driver = self.fwaas_driver.get_T_driver() - else: - self.internal_driver = self.fwaas_driver - - @property - def plugin_type(self): - return projectpluginmap.NsxPlugins.NSX_T - - def should_apply_firewall_to_router(self, context, router_id): - """Return True if the FWaaS rules should be added to this router.""" - if not super(Nsxv3FwaasCallbacksV1, - self).should_apply_firewall_to_router(context, - router_id): - return False - - # get all the relevant router info - ctx_elevated = context.elevated() - router_data = self.core_plugin.get_router(ctx_elevated, router_id) - if not router_data: - LOG.error("Couldn't read router %s data", router_id) - return False - - # Check if the FWaaS driver supports this router - if not self.internal_driver.should_apply_firewall_to_router( - router_data): - return False - - return True - - def update_router_firewall(self, context, nsxlib, router_id, - router_interfaces, nsx_router_id, section_id, - from_fw=False): - """Rewrite all the FWaaS v1 rules in the router edge firewall - - This method should be called on FWaaS updates, and on router - interfaces changes. - """ - fw_rules = [] - fw_id = None - if self.should_apply_firewall_to_router(context, router_id): - # Find the firewall attached to this router - # (must have one since should_apply returned true) - firewall = self.get_router_firewall(context, router_id) - fw_id = firewall['id'] - - # Add the FW rules - fw_rules.extend(self.internal_driver.get_router_translated_rules( - router_id, firewall)) - - # Add plugin additional allow rules - fw_rules.extend(self.core_plugin.get_extra_fw_rules( - context, router_id)) - - # Add the default drop all rule - fw_rules.append(self.internal_driver.get_default_backend_rule( - section_id, allow_all=False)) - else: - # default allow all rule - fw_rules.append(self.internal_driver.get_default_backend_rule( - section_id, allow_all=True)) - - # update the backend - nsxlib.firewall_section.update(section_id, rules=fw_rules) - - # Also update the router tags - self.internal_driver.update_nsx_router_tags(nsx_router_id, fw_id=fw_id) - - def delete_port(self, context, port_id): - # nothing to do in FWaaS v1 - pass diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/fwaas/nsx_v3/fwaas_callbacks_v2.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/fwaas/nsx_v3/fwaas_callbacks_v2.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/fwaas/nsx_v3/fwaas_callbacks_v2.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/fwaas/nsx_v3/fwaas_callbacks_v2.py 2019-03-14 02:01:03.000000000 +0000 @@ -29,8 +29,8 @@ class Nsxv3FwaasCallbacksV2(com_callbacks.NsxFwaasCallbacksV2): """NSX-V3 RPC callbacks for Firewall As A Service - V2.""" - def __init__(self): - super(Nsxv3FwaasCallbacksV2, self).__init__() + def __init__(self, with_rpc): + super(Nsxv3FwaasCallbacksV2, self).__init__(with_rpc) # update the fwaas driver in case of TV plugin self.internal_driver = None if self.fwaas_enabled: @@ -118,8 +118,8 @@ if with_fw: # firewall exists in Neutron and not on backend - create if not exists_on_backend: - self.core_plugin.create_service_router(context, router_id) - exists_on_backend = True + self.core_plugin.create_service_router( + context, router_id, update_firewall=False) else: # First, check if other services exist and use the sr sr_exists = self.core_plugin.service_router_has_services( diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/l2gateway/nsx_v3/driver.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/l2gateway/nsx_v3/driver.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/l2gateway/nsx_v3/driver.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/l2gateway/nsx_v3/driver.py 2019-03-14 02:01:03.000000000 +0000 @@ -132,10 +132,11 @@ def_l2gw_exists = True return l2_gateway - def _prevent_l2gw_port_delete(self, resource, event, trigger, **kwargs): - context = kwargs.get('context') - port_id = kwargs.get('port_id') - port_check = kwargs.get('port_check') + def _prevent_l2gw_port_delete(self, resource, event, + trigger, payload=None): + context = payload.context + port_id = payload.resource_id + port_check = payload.metadata['port_check'] if port_check: self.prevent_l2gw_port_deletion(context, port_id) diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/lbaas/nsx_v/implementation/healthmon_mgr.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/lbaas/nsx_v/implementation/healthmon_mgr.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/lbaas/nsx_v/implementation/healthmon_mgr.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/lbaas/nsx_v/implementation/healthmon_mgr.py 2019-03-14 02:01:03.000000000 +0000 @@ -186,3 +186,6 @@ nsxv_db.del_nsxv_lbaas_monitor_binding( context.session, lb_id, pool_id, hm['id'], edge_id) completor(success=True) + + def delete_cascade(self, context, hm, completor): + self.delete(context, hm, completor) diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/lbaas/nsx_v/implementation/l7policy_mgr.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/lbaas/nsx_v/implementation/l7policy_mgr.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/lbaas/nsx_v/implementation/l7policy_mgr.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/lbaas/nsx_v/implementation/l7policy_mgr.py 2019-03-14 02:01:03.000000000 +0000 @@ -321,3 +321,6 @@ # complete the transaction completor(success=True) + + def delete_cascade(self, context, policy, completor): + self.delete(context, policy, completor) diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/lbaas/nsx_v/implementation/l7rule_mgr.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/lbaas/nsx_v/implementation/l7rule_mgr.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/lbaas/nsx_v/implementation/l7rule_mgr.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/lbaas/nsx_v/implementation/l7rule_mgr.py 2019-03-14 02:01:03.000000000 +0000 @@ -62,3 +62,6 @@ def delete(self, context, rule, completor): self._handle_l7policy_rules_change(context, rule, completor, delete=True) + + def delete_cascade(self, context, rule, completor): + self.delete(context, rule, completor) diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/lbaas/nsx_v/implementation/listener_mgr.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/lbaas/nsx_v/implementation/listener_mgr.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/lbaas/nsx_v/implementation/listener_mgr.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/lbaas/nsx_v/implementation/listener_mgr.py 2019-03-14 02:01:03.000000000 +0000 @@ -300,6 +300,9 @@ completor(success=True) + def delete_cascade(self, context, listener, completor): + self.delete(context, listener, completor) + def stats_getter(context, core_plugin, ignore_list=None): """Update Octavia statistics for each listener (virtual server)""" diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/lbaas/nsx_v/implementation/loadbalancer_mgr.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/lbaas/nsx_v/implementation/loadbalancer_mgr.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/lbaas/nsx_v/implementation/loadbalancer_mgr.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/lbaas/nsx_v/implementation/loadbalancer_mgr.py 2019-03-14 02:01:03.000000000 +0000 @@ -114,7 +114,7 @@ def delete(self, context, lb, completor): # Discard any ports which are associated with LB filters = { - 'device_id': [lb['id']], + 'device_id': [lb['id'], oct_const.DEVICE_ID_PREFIX + lb['id']], 'device_owner': [constants.DEVICE_OWNER_NEUTRON_PREFIX + 'LB']} lb_ports = self.core_plugin.get_ports(context.elevated(), filters=filters) @@ -160,6 +160,10 @@ context.session, lb['id']) completor(success=True) + def delete_cascade(self, context, lb, completor): + #TODO(asarfaty): implement a better delete cascade for NSX-V + self.delete(context, lb, completor) + def refresh(self, context, lb): # TODO(kobis): implement pass @@ -236,11 +240,12 @@ if lb_ports: for lb_port in lb_ports: - # TODO(asarfaty): for Octavia this code might need to change - # as the device_id is different if lb_port['device_id']: + device_id = lb_port['device_id'] + if device_id.startswith(oct_const.DEVICE_ID_PREFIX): + device_id = device_id[len(oct_const.DEVICE_ID_PREFIX):] edge_bind = nsxv_db.get_nsxv_lbaas_loadbalancer_binding( - context.session, lb_port['device_id']) + context.session, device_id) edge_id = edge_bind['edge_id'] routes = [{'cidr': r['destination'], diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/lbaas/nsx_v/implementation/member_mgr.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/lbaas/nsx_v/implementation/member_mgr.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/lbaas/nsx_v/implementation/member_mgr.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/lbaas/nsx_v/implementation/member_mgr.py 2019-03-14 02:01:03.000000000 +0000 @@ -223,3 +223,6 @@ with excutils.save_and_reraise_exception(): completor(success=False) LOG.error('Failed to delete member on edge: %s', edge_id) + + def delete_cascade(self, context, member, completor): + self.delete(context, member, completor) diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/lbaas/nsx_v/implementation/pool_mgr.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/lbaas/nsx_v/implementation/pool_mgr.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/lbaas/nsx_v/implementation/pool_mgr.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/lbaas/nsx_v/implementation/pool_mgr.py 2019-03-14 02:01:03.000000000 +0000 @@ -205,6 +205,9 @@ completor(success=False) LOG.error('Failed to delete pool %s', pool['id']) + def delete_cascade(self, context, pool, completor): + self.delete(context, pool, completor) + def _get_lbaas_fw_section_id(self): if not self._fw_section_id: self._fw_section_id = lb_common.get_lbaas_fw_section_id(self.vcns) diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/lbaas/nsx_v3/implementation/healthmonitor_mgr.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/lbaas/nsx_v3/implementation/healthmonitor_mgr.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/lbaas/nsx_v3/implementation/healthmonitor_mgr.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/lbaas/nsx_v3/implementation/healthmonitor_mgr.py 2019-03-14 02:01:03.000000000 +0000 @@ -145,19 +145,27 @@ try: pool_client.remove_monitor_from_pool(lb_pool_id, lb_monitor_id) + except nsxlib_exc.ResourceNotFound: + pass except nsxlib_exc.ManagerError as exc: - LOG.error('Failed to remove monitor %(monitor)s from pool ' - '%(pool)s with exception from nsx %(exc)s)', - {'monitor': lb_monitor_id, - 'pool': lb_pool_id, - 'exc': exc}) + completor(success=False) + msg = _('Failed to remove monitor %(monitor)s from pool ' + '%(pool)s with exception from nsx %(exc)s)') % { + 'monitor': lb_monitor_id, + 'pool': lb_pool_id, + 'exc': exc} + raise n_exc.BadRequest(resource='lbaas-hm', msg=msg) try: monitor_client.delete(lb_monitor_id) + except nsxlib_exc.ResourceNotFound: + pass except nsxlib_exc.ManagerError as exc: - LOG.error('Failed to delete monitor %(monitor)s from ' - 'backend with exception %(exc)s', - {'monitor': lb_monitor_id, - 'exc': exc}) + completor(success=False) + msg = _('Failed to delete monitor %(monitor)s from ' + 'backend with exception %(exc)s') % { + 'monitor': lb_monitor_id, + 'exc': exc} + raise n_exc.BadRequest(resource='lbaas-hm', msg=msg) nsx_db.delete_nsx_lbaas_monitor_binding(context.session, lb_id, pool_id, hm['id']) @@ -166,3 +174,7 @@ pass completor(success=True) + + @log_helpers.log_method_call + def delete_cascade(self, context, hm, completor): + self.delete(context, hm, completor) diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/lbaas/nsx_v3/implementation/l7policy_mgr.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/lbaas/nsx_v3/implementation/l7policy_mgr.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/lbaas/nsx_v3/implementation/l7policy_mgr.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/lbaas/nsx_v3/implementation/l7policy_mgr.py 2019-03-14 02:01:03.000000000 +0000 @@ -135,3 +135,7 @@ context.session, policy['id']) completor(success=True) + + @log_helpers.log_method_call + def delete_cascade(self, context, policy, completor): + self.delete(context, policy, completor) diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/lbaas/nsx_v3/implementation/l7rule_mgr.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/lbaas/nsx_v3/implementation/l7rule_mgr.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/lbaas/nsx_v3/implementation/l7rule_mgr.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/lbaas/nsx_v3/implementation/l7rule_mgr.py 2019-03-14 02:01:03.000000000 +0000 @@ -68,3 +68,8 @@ @log_helpers.log_method_call def delete(self, context, rule, completor): self._update_l7rule_change(context, rule, completor, delete=True) + + @log_helpers.log_method_call + def delete_cascade(self, context, rulle, completor): + # No action should be taken on rules delete cascade + pass diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/lbaas/nsx_v3/implementation/lb_utils.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/lbaas/nsx_v3/implementation/lb_utils.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/lbaas/nsx_v3/implementation/lb_utils.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/lbaas/nsx_v3/implementation/lb_utils.py 2019-03-14 02:01:03.000000000 +0000 @@ -229,7 +229,8 @@ def update_router_lb_vip_advertisement(context, core_plugin, router, nsx_router_id): # Add a rule to advertise external vips on the router - external_subnets = core_plugin._find_router_gw_subnets(context, router) + external_subnets = core_plugin._find_router_gw_subnets( + context.elevated(), router) external_cidrs = [s['cidr'] for s in external_subnets] if external_cidrs: adv_rule = { diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/lbaas/nsx_v3/implementation/listener_mgr.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/lbaas/nsx_v3/implementation/listener_mgr.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/lbaas/nsx_v3/implementation/listener_mgr.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/lbaas/nsx_v3/implementation/listener_mgr.py 2019-03-14 02:01:03.000000000 +0000 @@ -149,16 +149,20 @@ # server to the lb service binding = nsx_db.get_nsx_lbaas_loadbalancer_binding( context.session, lb_id) - if binding: - lb_service_id = binding['lb_service_id'] - try: - service_client.add_virtual_server(lb_service_id, - virtual_server['id']) - except nsxlib_exc.ManagerError: - completor(success=False) - msg = _('Failed to add virtual server to lb service ' - 'at NSX backend') - raise n_exc.BadRequest(resource='lbaas-listener', msg=msg) + if not binding: + completor(success=False) + msg = _('Failed to get loadbalancer %s binding') % lb_id + raise n_exc.BadRequest(resource='lbaas-listener', msg=msg) + + lb_service_id = binding['lb_service_id'] + try: + service_client.add_virtual_server(lb_service_id, + virtual_server['id']) + except nsxlib_exc.ManagerError: + completor(success=False) + msg = _('Failed to add virtual server to lb service ' + 'at NSX backend') + raise n_exc.BadRequest(resource='lbaas-listener', msg=msg) nsx_db.add_nsx_lbaas_listener_binding( context.session, lb_id, listener['id'], app_profile_id, @@ -219,19 +223,24 @@ app_profile_id = binding['app_profile_id'] lb_binding = nsx_db.get_nsx_lbaas_loadbalancer_binding( context.session, lb_id) - if lb_binding: - try: - lbs_id = lb_binding.get('lb_service_id') - lb_service = service_client.get(lbs_id) - vs_list = lb_service.get('virtual_server_ids') - if vs_list and vs_id in vs_list: - service_client.remove_virtual_server(lbs_id, vs_id) - except nsxlib_exc.ManagerError: - completor(success=False) - msg = (_('Failed to remove virtual server: %(listener)s ' - 'from lb service %(lbs)s') % - {'listener': listener['id'], 'lbs': lbs_id}) - raise n_exc.BadRequest(resource='lbaas-listener', msg=msg) + if not lb_binding: + completor(success=False) + msg = (_('Failed to delete virtual server: %(listener)s: ' + 'loadbalancer %(lb)s mapping was not found') % + {'listener': listener['id'], 'lb': lb_id}) + raise n_exc.BadRequest(resource='lbaas-listener', msg=msg) + try: + lbs_id = lb_binding.get('lb_service_id') + lb_service = service_client.get(lbs_id) + vs_list = lb_service.get('virtual_server_ids') + if vs_list and vs_id in vs_list: + service_client.remove_virtual_server(lbs_id, vs_id) + except nsxlib_exc.ManagerError: + completor(success=False) + msg = (_('Failed to remove virtual server: %(listener)s ' + 'from lb service %(lbs)s') % + {'listener': listener['id'], 'lbs': lbs_id}) + raise n_exc.BadRequest(resource='lbaas-listener', msg=msg) try: if listener.get('default_pool_id'): vs_client.update(vs_id, pool_id='') @@ -286,8 +295,11 @@ completor(success=True) + @log_helpers.log_method_call + def delete_cascade(self, context, listener, completor): + self.delete(context, listener, completor) + -@log_helpers.log_method_call def stats_getter(context, core_plugin, ignore_list=None): """Update Octavia statistics for each listener (virtual server)""" stat_list = [] @@ -300,8 +312,6 @@ continue lb_service_id = lb_binding.get('lb_service_id') - LOG.debug("Getting listeners statistics for NSX lb service %s", - lb_service_id) try: # get the NSX statistics for this LB service rsp = lb_service_client.get_stats(lb_service_id) diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/lbaas/nsx_v3/implementation/loadbalancer_mgr.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/lbaas/nsx_v3/implementation/loadbalancer_mgr.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/lbaas/nsx_v3/implementation/loadbalancer_mgr.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/lbaas/nsx_v3/implementation/loadbalancer_mgr.py 2019-03-14 02:01:03.000000000 +0000 @@ -20,6 +20,7 @@ from oslo_utils import excutils from vmware_nsx._i18n import _ +from vmware_nsx.common import exceptions as nsx_exc from vmware_nsx.db import db as nsx_db from vmware_nsx.services.lbaas import base_mgr from vmware_nsx.services.lbaas import lb_const @@ -34,16 +35,89 @@ @log_helpers.log_method_call def create(self, context, lb, completor): - if lb_utils.validate_lb_subnet(context, self.core_plugin, - lb['vip_subnet_id']): - completor(success=True) - else: + if not lb_utils.validate_lb_subnet(context, self.core_plugin, + lb['vip_subnet_id']): + completor(success=False) msg = (_('Cannot create lb on subnet %(sub)s for ' 'loadbalancer %(lb)s. The subnet needs to connect a ' 'router which is already set gateway.') % {'sub': lb['vip_subnet_id'], 'lb': lb['id']}) raise n_exc.BadRequest(resource='lbaas-subnet', msg=msg) + router_id = lb_utils.get_router_from_network( + context, self.core_plugin, lb['vip_subnet_id']) + nsx_router_id = nsx_db.get_nsx_router_id(context.session, + router_id) + service_client = self.core_plugin.nsxlib.load_balancer.service + lb_service = service_client.get_router_lb_service(nsx_router_id) + if not lb_service: + lb_size = lb_utils.get_lb_flavor_size( + self.flavor_plugin, context, lb.get('flavor_id')) + # Make sure the NSX service router exists + if not self.core_plugin.service_router_has_services( + context, router_id): + self.core_plugin.create_service_router(context, router_id) + lb_service = self._create_lb_service( + context, service_client, lb['tenant_id'], + router_id, nsx_router_id, lb['id'], lb_size) + if not lb_service: + completor(success=False) + msg = (_('Failed to create lb service for loadbalancer ' + '%s') % lb['id']) + raise nsx_exc.NsxPluginException(err_msg=msg) + + self._add_loadbalancer_binding( + context, lb['id'], lb_service['id'], + nsx_router_id, lb['vip_address']) + + completor(success=True) + + @log_helpers.log_method_call + def _create_lb_service(self, context, service_client, tenant_id, + router_id, nsx_router_id, lb_id, lb_size): + router = self.core_plugin.get_router(context, router_id) + if not router.get('external_gateway_info'): + msg = (_('Tenant router %(router)s does not connect to ' + 'external gateway') % {'router': router['id']}) + raise n_exc.BadRequest(resource='lbaas-lbservice-create', + msg=msg) + lb_name = utils.get_name_and_uuid(router['name'] or 'router', + router_id) + tags = lb_utils.get_tags(self.core_plugin, router_id, + lb_const.LR_ROUTER_TYPE, + tenant_id, context.project_name) + attachment = {'target_id': nsx_router_id, + 'target_type': 'LogicalRouter'} + try: + lb_service = service_client.create(display_name=lb_name, + tags=tags, + attachment=attachment, + size=lb_size) + except nsxlib_exc.ManagerError as e: + LOG.error("Failed to create LB service: %s", e) + return + + # Add rule to advertise external vips + lb_utils.update_router_lb_vip_advertisement( + context, self.core_plugin, router, nsx_router_id) + + return lb_service + + @log_helpers.log_method_call + def _add_loadbalancer_binding(self, context, lb_id, lbs_id, + nsx_router_id, vip_address): + # First check if there is already binding for the lb. + # If there is no binding for the lb, add the db binding. + binding = nsx_db.get_nsx_lbaas_loadbalancer_binding( + context.session, lb_id) + if not binding: + nsx_db.add_nsx_lbaas_loadbalancer_binding( + context.session, lb_id, lbs_id, + nsx_router_id, vip_address) + else: + LOG.debug("LB binding has already been added, and no need to add " + "here.") + @log_helpers.log_method_call def update(self, context, old_lb, new_lb, completor): vs_client = self.core_plugin.nsxlib.load_balancer.virtual_server @@ -121,6 +195,11 @@ completor(success=True) @log_helpers.log_method_call + def delete_cascade(self, context, lb, completor): + """Delete all backend and DB resources of this loadbalancer""" + self.delete(context, lb, completor) + + @log_helpers.log_method_call def refresh(self, context, lb): # TODO(tongl): implement pass @@ -183,7 +262,8 @@ lb_binding = nsx_db.get_nsx_lbaas_loadbalancer_binding( context.session, id) if not lb_binding: - # No service yet + LOG.warning("Failed to get loadbalancer %s operating status. " + "Mapping was not found", id) return {} lb_service_id = lb_binding['lb_service_id'] diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/lbaas/nsx_v3/implementation/member_mgr.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/lbaas/nsx_v3/implementation/member_mgr.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/lbaas/nsx_v3/implementation/member_mgr.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/lbaas/nsx_v3/implementation/member_mgr.py 2019-03-14 02:01:03.000000000 +0000 @@ -23,10 +23,8 @@ from vmware_nsx.common import locking from vmware_nsx.db import db as nsx_db from vmware_nsx.services.lbaas import base_mgr -from vmware_nsx.services.lbaas import lb_const from vmware_nsx.services.lbaas.nsx_v3.implementation import lb_utils from vmware_nsxlib.v3 import exceptions as nsxlib_exc -from vmware_nsxlib.v3 import utils LOG = logging.getLogger(__name__) @@ -46,37 +44,6 @@ raise n_exc.BadRequest(resource='lbaas-vip', msg=msg) @log_helpers.log_method_call - def _create_lb_service(self, context, service_client, tenant_id, - router_id, nsx_router_id, lb_id, lb_size): - router = self.core_plugin.get_router(context, router_id) - if not router.get('external_gateway_info'): - msg = (_('Tenant router %(router)s does not connect to ' - 'external gateway') % {'router': router['id']}) - raise n_exc.BadRequest(resource='lbaas-lbservice-create', - msg=msg) - lb_name = utils.get_name_and_uuid(router['name'] or 'router', - router_id) - tags = lb_utils.get_tags(self.core_plugin, router_id, - lb_const.LR_ROUTER_TYPE, - tenant_id, context.project_name) - attachment = {'target_id': nsx_router_id, - 'target_type': 'LogicalRouter'} - try: - lb_service = service_client.create(display_name=lb_name, - tags=tags, - attachment=attachment, - size=lb_size) - except nsxlib_exc.ManagerError as e: - LOG.error("Failed to create LB service: %s", e) - return - - # Add rule to advertise external vips - lb_utils.update_router_lb_vip_advertisement( - context, self.core_plugin, router, nsx_router_id) - - return lb_service - - @log_helpers.log_method_call def _get_updated_pool_members(self, context, lb_pool, member): network = lb_utils.get_network_from_subnet( context, self.core_plugin, member['subnet_id']) @@ -92,21 +59,6 @@ return lb_pool['members'] @log_helpers.log_method_call - def _add_loadbalancer_binding(self, context, lb_id, lbs_id, - nsx_router_id, vip_address): - # First check if there is already binding for the lb. - # If there is no binding for the lb, add the db binding. - binding = nsx_db.get_nsx_lbaas_loadbalancer_binding( - context.session, lb_id) - if not binding: - nsx_db.add_nsx_lbaas_loadbalancer_binding( - context.session, lb_id, lbs_id, - nsx_router_id, vip_address) - else: - LOG.debug("LB binding has already been added, and no need " - "to add here.") - - @log_helpers.log_method_call def create(self, context, member, completor): with locking.LockManager.get_lock( 'member-%s' % str(member['pool']['loadbalancer_id'])): @@ -128,7 +80,6 @@ raise n_exc.BadRequest(resource='lbaas-subnet', msg=msg) pool_client = self.core_plugin.nsxlib.load_balancer.pool - service_client = self.core_plugin.nsxlib.load_balancer.service network = lb_utils.get_network_from_subnet( context, self.core_plugin, member['subnet_id']) @@ -148,42 +99,14 @@ binding = nsx_db.get_nsx_lbaas_pool_binding(context.session, lb_id, pool_id) if binding: - vs_id = binding.get('lb_vs_id') lb_pool_id = binding.get('lb_pool_id') lb_binding = nsx_db.get_nsx_lbaas_loadbalancer_binding( context.session, lb_id) - lb_service = None if not lb_binding: - nsx_router_id = nsx_db.get_nsx_router_id(context.session, - router_id) - lb_service = service_client.get_router_lb_service( - nsx_router_id) - virtual_server_ids = ( - lb_service and - lb_service.get('virtual_server_ids', []) or []) - if not lb_service: - lb_size = lb_utils.get_lb_flavor_size( - self.flavor_plugin, context, - loadbalancer.get('flavor_id')) - if not self.core_plugin.service_router_has_services( - context, - router_id): - self.core_plugin.create_service_router(context, - router_id) - lb_service = self._create_lb_service( - context, service_client, member['tenant_id'], - router_id, nsx_router_id, loadbalancer['id'], lb_size) - if lb_service: - lb_service_id = lb_service['id'] - self._add_loadbalancer_binding( - context, loadbalancer['id'], lb_service_id, - nsx_router_id, loadbalancer['vip_address']) - else: - completor(success=False) - msg = (_('Failed to get lb service to attach virtual ' - 'server %(vs)s for member %(member)s') % - {'vs': vs_id, 'member': member['id']}) - raise nsx_exc.NsxPluginException(err_msg=msg) + completor(success=False) + msg = (_('Failed to get LB binding for member %s') % + member['id']) + raise nsx_exc.NsxPluginException(err_msg=msg) with locking.LockManager.get_lock('pool-member-%s' % lb_pool_id): lb_pool = pool_client.get(lb_pool_id) @@ -196,30 +119,6 @@ members = (old_m + new_m) if old_m else new_m pool_client.update_pool_with_members(lb_pool_id, members) - # Check whether the virtual server should be added to the load - # balancing server. It is safe to perform this operation after the - # member has been added to the pool. This allows us to skip this - # check if there is already a member in the pool - if vs_id and not old_m: - # load the LB service if not already loaded - if not lb_service: - nsx_router_id = nsx_db.get_nsx_router_id(context.session, - router_id) - lb_service = service_client.get_router_lb_service( - nsx_router_id) - lb_service_id = lb_service['id'] - virtual_server_ids = lb_service.get('virtual_server_ids', - []) - if vs_id not in virtual_server_ids: - try: - service_client.add_virtual_server(lb_service_id, vs_id) - except nsxlib_exc.ManagerError: - completor(success=False) - msg = (_('Failed to attach virtual server %(vs)s ' - 'to lb service %(service)s') % - {'vs': vs_id, 'service': lb_service_id}) - raise n_exc.BadRequest(resource='lbaas-member', - msg=msg) else: completor(success=False) msg = (_('Failed to get pool binding to add member %s') % @@ -287,3 +186,8 @@ raise n_exc.BadRequest(resource='lbaas-member', msg=msg) completor(success=True) + + @log_helpers.log_method_call + def delete_cascade(self, context, member, completor): + # No action should be taken on members delete cascade + pass diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/lbaas/nsx_v3/implementation/pool_mgr.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/lbaas/nsx_v3/implementation/pool_mgr.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/lbaas/nsx_v3/implementation/pool_mgr.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/lbaas/nsx_v3/implementation/pool_mgr.py 2019-03-14 02:01:03.000000000 +0000 @@ -52,9 +52,13 @@ @log_helpers.log_method_call def _build_persistence_profile_tags(self, pool_tags, listener): tags = pool_tags[:] - tags.append({ - 'scope': 'os-lbaas-lb-name', - 'tag': listener['loadbalancer']['name'][:utils.MAX_TAG_LEN]}) + # With octavia loadbalancer name might not be among data passed + # down to the driver + lb_data = listener.get('loadbalancer') + if lb_data: + tags.append({ + 'scope': 'os-lbaas-lb-name', + 'tag': lb_data['name'][:utils.MAX_TAG_LEN]}) tags.append({ 'scope': 'os-lbaas-lb-id', 'tag': listener['loadbalancer_id']}) @@ -297,8 +301,9 @@ except IndexError: # If listeners is an empty list we hit this exception listener = None - # Perform additional validation for session persistence before - # operating on resources in the backend + + # Perform additional validation for session persistence before + # operating on resources in the backend self._validate_session_persistence(new_pool, listener, completor, old_pool=old_pool) @@ -354,3 +359,7 @@ lb_id, pool['id']) completor(success=True) + + @log_helpers.log_method_call + def delete_cascade(self, context, pool, completor): + self.delete(context, pool, completor) diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/lbaas/octavia/constants.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/lbaas/octavia/constants.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/lbaas/octavia/constants.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/lbaas/octavia/constants.py 2019-03-14 02:01:03.000000000 +0000 @@ -43,3 +43,4 @@ PROVISIONING_STATUS = 'provisioning_status' DEVICE_OWNER_OCTAVIA = 'Octavia' +DEVICE_ID_PREFIX = 'lb-' diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/lbaas/octavia/octavia_driver.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/lbaas/octavia/octavia_driver.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/lbaas/octavia/octavia_driver.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/lbaas/octavia/octavia_driver.py 2019-03-14 02:01:03.000000000 +0000 @@ -45,7 +45,7 @@ 'timeout_member_connect', 'timeout_member_data', 'timeout_tcp_inspect'], - 'HealthMonitor': ['expected_codes', 'max_retries_down'], + 'HealthMonitor': ['max_retries_down'], 'Member': ['monitor_address', 'monitor_port', 'backup']} @@ -144,7 +144,7 @@ lb_dict['vip_subnet_id'] = db_lb.vip.subnet_id return lb_dict - def _get_listener_in_pool_dict(self, pool_dict): + def _get_listener_in_pool_dict(self, pool_dict, is_update): if 'listener' not in pool_dict: if pool_dict.get('listener_id'): db_listener = self.repositories.listener.get( @@ -155,21 +155,29 @@ recurse=False, render_unsets=True) listener_dict['id'] = listener_dict['listener_id'] listener_dict['l7_policies'] = listener_dict['l7policies'] + # Add the loadbalancer to the listener dict + if pool_dict.get('loadbalancer_id'): + # Generate a loadbalancer object + listener_dict['loadbalancer'] = ( + self._get_load_balancer_dict( + pool_dict['loadbalancer_id'])) pool_dict['listener'] = listener_dict if 'listeners' not in pool_dict: # multiple listeners is not really supported yet pool_dict['listeners'] = [listener_dict] - else: + # Do not add listener in update situation, as we want to use + # the original listener of this pool + elif not is_update: pool_dict['listener'] = None if 'listeners' not in pool_dict: pool_dict['listeners'] = [] - def _get_pool_dict(self, pool_id): + def _get_pool_dict(self, pool_id, is_update): if not pool_id: - return + return {} db_pool = self.repositories.pool.get(db_apis.get_session(), id=pool_id) if not db_pool: - return + return {} pool_obj = oct_utils.db_pool_to_provider_pool(db_pool) pool_dict = pool_obj.to_dict(recurse=True, render_unsets=True) pool_dict['id'] = pool_id @@ -179,9 +187,25 @@ pool_dict['loadbalancer'] = self._get_load_balancer_dict( pool_dict['loadbalancer_id']) if 'listener' not in pool_dict: - self._get_listener_in_pool_dict(pool_dict) + self._get_listener_in_pool_dict(pool_dict, is_update) return pool_dict + def _get_hm_dict(self, hm_id, is_update): + if not hm_id: + return {} + db_hm = self.repositories.health_monitor.get( + db_apis.get_session(), id=hm_id) + if not db_hm: + return {} + hm_obj = oct_utils.db_HM_to_provider_HM(db_hm) + hm_dict = hm_obj.to_dict(recurse=True, render_unsets=True) + hm_dict['id'] = hm_id + # Get the pol object + if hm_dict.get('pool_id'): + hm_dict['pool'] = self._get_pool_dict( + hm_dict['pool_id'], is_update) + return hm_dict + def update_policy_dict(self, policy_dict, policy_obj, is_update=False): if policy_dict.get('listener_id'): db_list = self.repositories.listener.get( @@ -193,7 +217,10 @@ if policy_obj.rules: policy_dict['rules'] = [] for rule in policy_obj.rules: - rule_dict = rule.to_dict(recurse=False, render_unsets=True) + if isinstance(rule, dict): + rule_dict = rule + else: + rule_dict = rule.to_dict(recurse=False, render_unsets=True) rule_dict['id'] = rule_dict['l7rule_id'] policy_dict['rules'].append(rule_dict) elif not is_update: @@ -238,6 +265,10 @@ obj_dict['listeners'] = [] for listener in obj_dict['listeners']: listener['id'] = listener['listener_id'] + for policy in listener.get('l7policies', []): + policy['id'] = policy['l7policy_id'] + for rule in policy.get('rules', []): + rule['id'] = rule['l7rule_id'] if 'pools' in obj_dict: if is_update and not obj_dict['pools']: del obj_dict['pools'] @@ -246,6 +277,12 @@ obj_dict['pools'] = [] for pool in obj_dict['pools']: pool['id'] = pool['pool_id'] + for member in pool.get('members', []): + member['id'] = member['member_id'] + if pool.get('healthmonitor'): + pool['healthmonitor'] = self._get_hm_dict( + pool['healthmonitor']['healthmonitor_id'], + is_update) elif obj_type == 'Listener': if 'l7policies' in obj_dict: @@ -258,12 +295,13 @@ elif obj_type == 'Pool': if 'listener' not in obj_dict: - self._get_listener_in_pool_dict(obj_dict) + self._get_listener_in_pool_dict(obj_dict, is_update) elif obj_type == 'Member': # Get the pool object if obj_dict.get('pool_id'): - obj_dict['pool'] = self._get_pool_dict(obj_dict['pool_id']) + obj_dict['pool'] = self._get_pool_dict( + obj_dict['pool_id'], is_update) obj_dict['loadbalancer'] = None if 'loadbalancer' in obj_dict['pool']: obj_dict['loadbalancer'] = obj_dict['pool']['loadbalancer'] @@ -278,7 +316,8 @@ elif obj_type == 'HealthMonitor': # Get the pool object if obj_dict.get('pool_id'): - obj_dict['pool'] = self._get_pool_dict(obj_dict['pool_id']) + obj_dict['pool'] = self._get_pool_dict( + obj_dict['pool_id'], is_update) elif obj_type == 'L7Policy': self.update_policy_dict(obj_dict, obj, is_update=is_update) @@ -313,11 +352,6 @@ @log_helpers.log_method_call def loadbalancer_delete(self, loadbalancer, cascade=False): - if cascade: - # TODO(asarfaty) add support for cascade - LOG.warning("The NSX Octavia driver does not support loadbalancer " - "delete cascade") - raise exceptions.NotImplementedError() kw = {'loadbalancer': self.obj_to_dict(loadbalancer), 'cascade': cascade} self.client.cast({}, 'loadbalancer_delete', **kw) @@ -387,8 +421,9 @@ def pool_update(self, old_pool, new_pool): old_dict = self.obj_to_dict(old_pool) new_dict = copy.deepcopy(old_dict) - new_dict.update(self.obj_to_dict( - new_pool, is_update=True, project_id=old_dict.get('project_id'))) + new_pool_dict = self.obj_to_dict( + new_pool, is_update=True, project_id=old_dict.get('project_id')) + new_dict.update(new_pool_dict) kw = {'old_pool': old_dict, 'new_pool': new_dict} self.client.cast({}, 'pool_update', **kw) @@ -498,10 +533,22 @@ @log_helpers.log_method_call def update_loadbalancer_status(self, ctxt, status): - return super(NSXOctaviaDriverEndpoint, - self).update_loadbalancer_status(status) + # refresh the driver lib session + self.db_session = db_apis.get_session() + try: + return super(NSXOctaviaDriverEndpoint, + self).update_loadbalancer_status(status) + except exceptions.UpdateStatusError as e: + LOG.error("Failed to update Octavia loadbalancer status. " + "Status %s, Error %s", status, e) @log_helpers.log_method_call def update_listener_statistics(self, ctxt, statistics): - return super(NSXOctaviaDriverEndpoint, - self).update_listener_statistics(statistics) + # refresh the driver lib session + self.db_session = db_apis.get_session() + try: + return super(NSXOctaviaDriverEndpoint, + self).update_listener_statistics(statistics) + except exceptions.UpdateStatisticsError as e: + LOG.error("Failed to update Octavia listener statistics. " + "Stats %s, Error %s", statistics, e) diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/lbaas/octavia/octavia_listener.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/lbaas/octavia/octavia_listener.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/lbaas/octavia/octavia_listener.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/lbaas/octavia/octavia_listener.py 2019-03-14 02:01:03.000000000 +0000 @@ -87,11 +87,11 @@ self.l7policy = l7policy self.l7rule = l7rule - def get_completor_func(self, obj_type, obj, delete=False): + def get_completor_func(self, obj_type, obj, delete=False, cascade=False): # return a method that will be called on success/failure completion def completor_func(success=True): - LOG.debug("Octavia transaction completed. status %s", - 'success' if success else 'failure') + LOG.debug("Octavia transaction completed. delete %s, status %s", + delete, 'success' if success else 'failure') # calculate the provisioning and operating statuses main_prov_status = constants.ACTIVE @@ -119,39 +119,94 @@ loadbalancer_id = None if obj.get('loadbalancer_id'): loadbalancer_id = obj.get('loadbalancer_id') - elif obj.get('pool'): + if obj.get('pool'): pool_id = obj['pool']['id'] - loadbalancer_id = obj['pool']['loadbalancer_id'] - elif obj.get('listener'): + listener_id = obj['pool'].get('listener_id') + if not loadbalancer_id: + loadbalancer_id = obj['pool'].get('loadbalancer_id') + elif obj.get('pool_id'): + pool_id = obj['pool_id'] + if obj.get('listener'): listener_id = obj['listener']['id'] - loadbalancer_id = obj['listener']['loadbalancer_id'] - elif obj.get('policy') and obj['policy'].get('listener'): + if not loadbalancer_id: + loadbalancer_id = obj['listener'].get( + 'loadbalancer_id') + elif obj.get('listener_id'): + listener_id = obj['listener_id'] + if obj.get('policy') and obj['policy'].get('listener'): policy_id = obj['policy']['id'] - listener_id = obj['policy']['listener']['id'] - loadbalancer_id = obj['policy']['listener'][ - 'loadbalancer_id'] + if not listener_id: + listener_id = obj['policy']['listener']['id'] + if not loadbalancer_id: + loadbalancer_id = obj['policy']['listener'].get( + 'loadbalancer_id') - if loadbalancer_id: + if (loadbalancer_id and + not status_dict.get(constants.LOADBALANCERS)): status_dict[constants.LOADBALANCERS] = [{ 'id': loadbalancer_id, constants.PROVISIONING_STATUS: parent_prov_status, constants.OPERATING_STATUS: op_status}] - if listener_id: + if (listener_id and + not status_dict.get(constants.LISTENERS)): status_dict[constants.LISTENERS] = [{ 'id': listener_id, constants.PROVISIONING_STATUS: parent_prov_status, constants.OPERATING_STATUS: op_status}] - if pool_id: + if (pool_id and + not status_dict.get(constants.POOLS)): status_dict[constants.POOLS] = [{ 'id': pool_id, constants.PROVISIONING_STATUS: parent_prov_status, constants.OPERATING_STATUS: op_status}] - if policy_id: + if (policy_id and + not status_dict.get(constants.L7POLICIES)): status_dict[constants.L7POLICIES] = [{ 'id': policy_id, constants.PROVISIONING_STATUS: parent_prov_status, constants.OPERATING_STATUS: op_status}] + elif delete and cascade: + # add deleted status to all other objects + status_dict[constants.LISTENERS] = [] + status_dict[constants.POOLS] = [] + status_dict[constants.MEMBERS] = [] + status_dict[constants.L7POLICIES] = [] + status_dict[constants.L7RULES] = [] + status_dict[constants.HEALTHMONITORS] = [] + for pool in obj.get('pools', []): + for member in pool.get('members', []): + status_dict[constants.MEMBERS].append( + {'id': member['id'], + constants.PROVISIONING_STATUS: constants.DELETED, + constants.OPERATING_STATUS: op_status}) + if pool.get('healthmonitor'): + status_dict[constants.HEALTHMONITORS].append( + {'id': pool['healthmonitor']['id'], + constants.PROVISIONING_STATUS: constants.DELETED, + constants.OPERATING_STATUS: op_status}) + status_dict[constants.POOLS].append( + {'id': pool['id'], + constants.PROVISIONING_STATUS: constants.DELETED, + constants.OPERATING_STATUS: op_status}) + for listener in obj.get('listeners', []): + status_dict[constants.LISTENERS].append( + {'id': listener['id'], + constants.PROVISIONING_STATUS: constants.DELETED, + constants.OPERATING_STATUS: op_status}) + for policy in listener.get('l7policies', []): + status_dict[constants.L7POLICIES].append( + {'id': policy['id'], + constants.PROVISIONING_STATUS: constants.DELETED, + constants.OPERATING_STATUS: op_status}) + for rule in policy.get('rules', []): + status_dict[constants.L7RULES].append( + {'id': rule['id'], + constants.PROVISIONING_STATUS: + constants.DELETED, + constants.OPERATING_STATUS: op_status}) + LOG.debug("Octavia transaction completed with statuses %s", + status_dict) kw = {'status': status_dict} self.client.cast({}, 'update_loadbalancer_status', **kw) @@ -164,165 +219,281 @@ @log_helpers.log_method_call def loadbalancer_create(self, ctxt, loadbalancer): ctx = neutron_context.Context(None, loadbalancer['project_id']) - self.loadbalancer.create( - ctx, loadbalancer, - self.get_completor_func(constants.LOADBALANCERS, - loadbalancer)) + completor = self.get_completor_func(constants.LOADBALANCERS, + loadbalancer) + try: + self.loadbalancer.create(ctx, loadbalancer, completor) + except Exception as e: + LOG.error('NSX driver loadbalancer_create failed %s', e) + completor(success=False) + + @log_helpers.log_method_call + def loadbalancer_delete_cascade(self, ctxt, loadbalancer): + ctx = neutron_context.Context(None, loadbalancer['project_id']) + + def dummy_completor(success=True): + pass + + # Go over the LB tree and delete one by one using the cascade + # api implemented for each resource + for listener in loadbalancer.get('listeners', []): + for policy in listener.get('l7policies', []): + for rule in policy.get('rules', []): + self.l7rule.delete_cascade(ctx, rule, dummy_completor) + self.l7policy.delete_cascade(ctx, policy, dummy_completor) + self.listener.delete_cascade(ctx, listener, dummy_completor) + for pool in loadbalancer.get('pools', []): + for member in pool.get('members', []): + self.member.delete_cascade(ctx, member, dummy_completor) + if pool.get('healthmonitor'): + self.healthmonitor.delete_cascade( + ctx, pool['healthmonitor'], dummy_completor) + self.pool.delete_cascade(ctx, pool, dummy_completor) + + # Delete the loadbalancer itself with the completor that marks all + # as deleted + completor = self.get_completor_func(constants.LOADBALANCERS, + loadbalancer, delete=True) + try: + self.loadbalancer.delete_cascade( + ctx, loadbalancer, self.get_completor_func( + constants.LOADBALANCERS, + loadbalancer, + delete=True, cascade=True)) + except Exception as e: + LOG.error('NSX driver loadbalancer_delete_cascade failed %s', e) + completor(success=False) @log_helpers.log_method_call def loadbalancer_delete(self, ctxt, loadbalancer, cascade=False): + if cascade: + return self.loadbalancer_delete_cascade(ctxt, loadbalancer) + ctx = neutron_context.Context(None, loadbalancer['project_id']) - # TODO(asarfaty): No support for cascade. It is blocked by the driver - self.loadbalancer.delete( - ctx, loadbalancer, - self.get_completor_func(constants.LOADBALANCERS, - loadbalancer, - delete=True)) + completor = self.get_completor_func(constants.LOADBALANCERS, + loadbalancer, delete=True) + try: + self.loadbalancer.delete(ctx, loadbalancer, completor) + except Exception as e: + LOG.error('NSX driver loadbalancer_delete failed %s', e) + completor(success=False) @log_helpers.log_method_call def loadbalancer_update(self, ctxt, old_loadbalancer, new_loadbalancer): ctx = neutron_context.Context(None, old_loadbalancer['project_id']) - self.loadbalancer.update( - ctx, old_loadbalancer, new_loadbalancer, - self.get_completor_func(constants.LOADBALANCERS, - new_loadbalancer)) + completor = self.get_completor_func(constants.LOADBALANCERS, + new_loadbalancer) + try: + self.loadbalancer.update(ctx, old_loadbalancer, new_loadbalancer, + completor) + except Exception as e: + LOG.error('NSX driver loadbalancer_update failed %s', e) + completor(success=False) # Listener @log_helpers.log_method_call def listener_create(self, ctxt, listener, cert): ctx = neutron_context.Context(None, listener['project_id']) - self.listener.create(ctx, listener, - self.get_completor_func(constants.LISTENERS, - listener), - certificate=cert) + completor = self.get_completor_func(constants.LISTENERS, + listener) + try: + self.listener.create(ctx, listener, completor, + certificate=cert) + except Exception as e: + LOG.error('NSX driver listener_create failed %s', e) + completor(success=False) @log_helpers.log_method_call def listener_delete(self, ctxt, listener): ctx = neutron_context.Context(None, listener['project_id']) - self.listener.delete(ctx, listener, - self.get_completor_func(constants.LISTENERS, - listener, - delete=True)) + completor = self.get_completor_func(constants.LISTENERS, + listener, delete=True) + try: + self.listener.delete(ctx, listener, completor) + except Exception as e: + LOG.error('NSX driver listener_delete failed %s', e) + completor(success=False) @log_helpers.log_method_call def listener_update(self, ctxt, old_listener, new_listener, cert): ctx = neutron_context.Context(None, old_listener['project_id']) - self.listener.update(ctx, old_listener, new_listener, - self.get_completor_func(constants.LISTENERS, - new_listener), - certificate=cert) + completor = self.get_completor_func(constants.LISTENERS, + new_listener) + try: + self.listener.update(ctx, old_listener, new_listener, + completor, certificate=cert) + except Exception as e: + LOG.error('NSX driver listener_update failed %s', e) + completor(success=False) # Pool @log_helpers.log_method_call def pool_create(self, ctxt, pool): ctx = neutron_context.Context(None, pool['project_id']) - self.pool.create(ctx, pool, self.get_completor_func(constants.POOLS, - pool)) + completor = self.get_completor_func(constants.POOLS, + pool) + try: + self.pool.create(ctx, pool, completor) + except Exception as e: + LOG.error('NSX driver pool_create failed %s', e) + completor(success=False) @log_helpers.log_method_call def pool_delete(self, ctxt, pool): ctx = neutron_context.Context(None, pool['project_id']) - self.pool.delete(ctx, pool, self.get_completor_func(constants.POOLS, - pool, - delete=True)) + completor = self.get_completor_func(constants.POOLS, + pool, delete=True) + try: + self.pool.delete(ctx, pool, completor) + except Exception as e: + LOG.error('NSX driver pool_delete failed %s', e) + completor(success=False) @log_helpers.log_method_call def pool_update(self, ctxt, old_pool, new_pool): ctx = neutron_context.Context(None, old_pool['project_id']) - self.pool.update(ctx, old_pool, new_pool, - self.get_completor_func(constants.POOLS, new_pool)) + completor = self.get_completor_func(constants.POOLS, + new_pool) + try: + self.pool.update(ctx, old_pool, new_pool, completor) + except Exception as e: + LOG.error('NSX driver pool_update failed %s', e) + completor(success=False) # Member @log_helpers.log_method_call def member_create(self, ctxt, member): ctx = neutron_context.Context(None, member['project_id']) - self.member.create(ctx, member, - self.get_completor_func(constants.MEMBERS, - member)) + completor = self.get_completor_func(constants.MEMBERS, + member) + try: + self.member.create(ctx, member, completor) + except Exception as e: + LOG.error('NSX driver member_create failed %s', e) + completor(success=False) @log_helpers.log_method_call def member_delete(self, ctxt, member): ctx = neutron_context.Context(None, member['project_id']) - self.member.delete(ctx, member, - self.get_completor_func(constants.MEMBERS, - member, - delete=True)) + completor = self.get_completor_func(constants.MEMBERS, + member, delete=True) + try: + self.member.delete(ctx, member, completor) + except Exception as e: + LOG.error('NSX driver member_delete failed %s', e) + completor(success=False) @log_helpers.log_method_call def member_update(self, ctxt, old_member, new_member): ctx = neutron_context.Context(None, old_member['project_id']) - self.member.update(ctx, old_member, new_member, - self.get_completor_func(constants.MEMBERS, - new_member)) + completor = self.get_completor_func(constants.MEMBERS, + new_member) + try: + self.member.update(ctx, old_member, new_member, completor) + except Exception as e: + LOG.error('NSX driver member_update failed %s', e) + completor(success=False) # Health Monitor @log_helpers.log_method_call def healthmonitor_create(self, ctxt, healthmonitor): ctx = neutron_context.Context(None, healthmonitor['project_id']) - self.healthmonitor.create(ctx, healthmonitor, - self.get_completor_func( - constants.HEALTHMONITORS, healthmonitor)) + completor = self.get_completor_func(constants.HEALTHMONITORS, + healthmonitor) + try: + self.healthmonitor.create(ctx, healthmonitor, completor) + except Exception as e: + LOG.error('NSX driver healthmonitor_create failed %s', e) + completor(success=False) @log_helpers.log_method_call def healthmonitor_delete(self, ctxt, healthmonitor): ctx = neutron_context.Context(None, healthmonitor['project_id']) - self.healthmonitor.delete(ctx, healthmonitor, - self.get_completor_func( - constants.HEALTHMONITORS, healthmonitor, - delete=True)) + completor = self.get_completor_func(constants.HEALTHMONITORS, + healthmonitor, delete=True) + try: + self.healthmonitor.delete(ctx, healthmonitor, completor) + except Exception as e: + LOG.error('NSX driver healthmonitor_delete failed %s', e) + completor(success=False) @log_helpers.log_method_call def healthmonitor_update(self, ctxt, old_healthmonitor, new_healthmonitor): ctx = neutron_context.Context(None, old_healthmonitor['project_id']) - self.healthmonitor.update(ctx, old_healthmonitor, new_healthmonitor, - self.get_completor_func( - constants.HEALTHMONITORS, - new_healthmonitor)) + completor = self.get_completor_func(constants.HEALTHMONITORS, + new_healthmonitor) + try: + self.healthmonitor.update(ctx, old_healthmonitor, + new_healthmonitor, completor) + except Exception as e: + LOG.error('NSX driver healthmonitor_update failed %s', e) + completor(success=False) # L7 Policy @log_helpers.log_method_call def l7policy_create(self, ctxt, l7policy): ctx = neutron_context.Context(None, l7policy['project_id']) - self.l7policy.create(ctx, l7policy, - self.get_completor_func(constants.L7POLICIES, - l7policy)) + completor = self.get_completor_func(constants.L7POLICIES, + l7policy) + try: + self.l7policy.create(ctx, l7policy, completor) + except Exception as e: + LOG.error('NSX driver l7policy_create failed %s', e) + completor(success=False) @log_helpers.log_method_call def l7policy_delete(self, ctxt, l7policy): ctx = neutron_context.Context(None, l7policy['project_id']) - self.l7policy.delete(ctx, l7policy, - self.get_completor_func(constants.L7POLICIES, - l7policy, - delete=True)) + completor = self.get_completor_func(constants.L7POLICIES, + l7policy, delete=True) + try: + self.l7policy.delete(ctx, l7policy, completor) + except Exception as e: + LOG.error('NSX driver l7policy_delete failed %s', e) + completor(success=False) @log_helpers.log_method_call def l7policy_update(self, ctxt, old_l7policy, new_l7policy): ctx = neutron_context.Context(None, old_l7policy['project_id']) - self.l7policy.update(ctx, old_l7policy, new_l7policy, - self.get_completor_func(constants.L7POLICIES, - new_l7policy)) + completor = self.get_completor_func(constants.L7POLICIES, + new_l7policy) + try: + self.l7policy.update(ctx, old_l7policy, new_l7policy, completor) + except Exception as e: + LOG.error('NSX driver l7policy_update failed %s', e) + completor(success=False) # L7 Rule @log_helpers.log_method_call def l7rule_create(self, ctxt, l7rule): ctx = neutron_context.Context(None, l7rule['project_id']) - self.l7rule.create(ctx, l7rule, - self.get_completor_func(constants.L7RULES, l7rule)) + completor = self.get_completor_func(constants.L7RULES, l7rule) + try: + self.l7rule.create(ctx, l7rule, completor) + except Exception as e: + LOG.error('NSX driver l7rule_create failed %s', e) + completor(success=False) @log_helpers.log_method_call def l7rule_delete(self, ctxt, l7rule): ctx = neutron_context.Context(None, l7rule['project_id']) - self.l7rule.delete(ctx, l7rule, - self.get_completor_func(constants.L7RULES, - l7rule, - delete=True)) + completor = self.get_completor_func(constants.L7RULES, l7rule, + delete=True) + try: + self.l7rule.delete(ctx, l7rule, completor) + except Exception as e: + LOG.error('NSX driver l7rule_delete failed %s', e) + completor(success=False) @log_helpers.log_method_call def l7rule_update(self, ctxt, old_l7rule, new_l7rule): ctx = neutron_context.Context(None, old_l7rule['project_id']) - self.l7rule.update(ctx, old_l7rule, new_l7rule, - self.get_completor_func(constants.L7RULES, - new_l7rule)) + completor = self.get_completor_func(constants.L7RULES, new_l7rule) + try: + self.l7rule.update(ctx, old_l7rule, new_l7rule, completor) + except Exception as e: + LOG.error('NSX driver l7rule_update failed %s', e) + completor(success=False) class NSXOctaviaStatisticsCollector(object): @@ -333,7 +504,6 @@ eventlet.spawn_n(self.thread_runner, cfg.CONF.octavia_stats_interval) - @log_helpers.log_method_call def thread_runner(self, interval): while True: time.sleep(interval) @@ -353,7 +523,6 @@ nl_loadbalancers = context.session.query(models.LoadBalancer).all() return [lb.id for lb in nl_loadbalancers] - @log_helpers.log_method_call def collect(self): if not self.core_plugin.octavia_listener: return diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/qos/nsx_v/plugin.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/qos/nsx_v/plugin.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/qos/nsx_v/plugin.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/qos/nsx_v/plugin.py 2019-03-14 02:01:03.000000000 +0000 @@ -15,7 +15,7 @@ # under the License. from neutron.services.qos import qos_plugin - +from neutron_lib.api.definitions import qos as qos_apidef from oslo_config import cfg from oslo_log import log as logging @@ -29,7 +29,7 @@ """Service plugin for VMware NSX-v to implement Neutron's Qos API.""" - supported_extension_aliases = ["qos"] + supported_extension_aliases = [qos_apidef.ALIAS] def __init__(self): LOG.info("Loading VMware NSX-V Qos Service Plugin") diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/qos/nsx_v3/pol_utils.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/qos/nsx_v3/pol_utils.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/qos/nsx_v3/pol_utils.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/qos/nsx_v3/pol_utils.py 2019-03-14 02:01:03.000000000 +0000 @@ -49,10 +49,15 @@ def _nsxpolicy(self): return self.core_plugin.nsxpolicy + def _get_tags(self, context, policy): + policy_dict = {'id': policy.id, 'tenant_id': policy.tenant_id} + return self._nsxpolicy.build_v3_tags_payload( + policy_dict, resource_type='os-neutron-qos-id', + project_name=context.tenant_name) + def create_or_update_policy(self, context, policy): policy_id = policy.id - tags = self._nsxpolicy.build_v3_api_version_project_tag( - context.tenant_name, project_id=policy.tenant_id) + tags = self._get_tags(context, policy) pol_name = utils.get_name_and_uuid(policy.name or 'policy', policy.id) diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/trunk/nsx_v3/driver.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/trunk/nsx_v3/driver.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/services/trunk/nsx_v3/driver.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/services/trunk/nsx_v3/driver.py 2019-03-14 02:01:03.000000000 +0000 @@ -23,6 +23,7 @@ from neutron_lib.api.definitions import portbindings from neutron_lib.callbacks import events from neutron_lib.callbacks import registry +from neutron_lib.callbacks import resources from vmware_nsx.common import nsx_constants as nsx_consts from vmware_nsx.common import utils as nsx_utils @@ -199,16 +200,16 @@ SUPPORTED_SEGMENTATION_TYPES, agent_type=None, can_trunk_bound_port=True) - @registry.receives(trunk_consts.TRUNK_PLUGIN, [events.AFTER_INIT]) + @registry.receives(resources.TRUNK_PLUGIN, [events.AFTER_INIT]) def register(self, resource, event, trigger, payload=None): super(NsxV3TrunkDriver, self).register( resource, event, trigger, payload=payload) self._handler = NsxV3TrunkHandler(self.plugin_driver) for event in (events.AFTER_CREATE, events.AFTER_DELETE): registry.subscribe(self._handler.trunk_event, - trunk_consts.TRUNK, + resources.TRUNK, event) registry.subscribe(self._handler.subport_event, - trunk_consts.SUBPORTS, + resources.SUBPORTS, event) LOG.debug("VMware NSXv3 trunk driver initialized.") diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/shell/admin/plugins/common/v3_common_cert.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/shell/admin/plugins/common/v3_common_cert.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/shell/admin/plugins/common/v3_common_cert.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/shell/admin/plugins/common/v3_common_cert.py 2019-03-14 02:01:03.000000000 +0000 @@ -13,6 +13,7 @@ # under the License. +from oslo_config import cfg from oslo_log import log as logging from neutron_lib import context @@ -67,12 +68,21 @@ def verify_client_cert_on(plugin_conf): - if plugin_conf.nsx_use_client_auth: - return True - - LOG.info("Operation not applicable since client authentication " + if not plugin_conf.nsx_use_client_auth: + LOG.info("Operation not applicable since client authentication " "is disabled") - return False + return False + + try: + if not plugin_conf.allow_passthrough: + LOG.info("Operation not applicable since passthrough API is " + "disabled") + return False + except cfg.NoSuchOptError: + # No such option exists - passthrough check is irrelevant + pass + + return True def generate_cert(plugin_conf, **kwargs): diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/shell/admin/plugins/nsxv/resources/spoofguard_policy.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/shell/admin/plugins/nsxv/resources/spoofguard_policy.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/shell/admin/plugins/nsxv/resources/spoofguard_policy.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/shell/admin/plugins/nsxv/resources/spoofguard_policy.py 2019-03-14 02:01:03.000000000 +0000 @@ -24,6 +24,8 @@ from neutron_lib import exceptions from vmware_nsx.db import nsxv_db +from vmware_nsx.extensions import ( + vnicindex as ext_vnic_idx) from oslo_log import log as logging @@ -36,6 +38,12 @@ return nsxv.get_spoofguard_policies()[1].get("policies") +def get_spoofguard_policy_data(policy_id): + nsxv = utils.get_nsxv_client() + return nsxv.get_spoofguard_policy_data(policy_id)[1].get( + 'spoofguardList', []) + + @admin_utils.output_header def nsx_list_spoofguard_policies(resource, event, trigger, **kwargs): """List spoofguard policies from NSXv backend""" @@ -100,6 +108,134 @@ constants.SPOOFGUARD_POLICY, missing_policies, ['policy_id'])) +def get_port_vnic_id(plugin, port): + vnic_idx = port.get(ext_vnic_idx.VNIC_INDEX) + device_id = port.get('device_id') + return plugin._get_port_vnic_id(vnic_idx, device_id) + + +def nsx_list_mismatch_addresses_for_net(context, plugin, network_id, + policy_id): + policy_data = get_spoofguard_policy_data(policy_id) + missing = [] + # Get all neutron compute ports on this network + port_filters = {'network_id': [network_id]} + neutron_ports = plugin.get_ports(context, filters=port_filters) + comp_ports = [port for port in neutron_ports + if port.get('device_owner', '').startswith('compute:')] + + for port in comp_ports: + if not port['port_security_enabled']: + # This port is not in spoofguard + continue + error_data = None + port_ips = [] + for pair in port.get('allowed_address_pairs'): + port_ips.append(pair['ip_address']) + for fixed in port.get('fixed_ips'): + port_ips.append(fixed['ip_address']) + if not port_ips: + continue + port_ips.sort() + mac_addr = port['mac_address'] + vnic_id = get_port_vnic_id(plugin, port) + + # look for this port in the spoofguard data + found_port = False + for spd in policy_data: + if spd['id'] == vnic_id: + found_port = True + actual_ips = spd.get('publishedIpAddress', + {}).get('ipAddresses', []) + actual_ips.sort() + if actual_ips != port_ips: + error_data = ('Different IPs (%s/%s)' % ( + len(actual_ips), len(port_ips))) + elif spd.get('publishedMacAddress') != mac_addr: + error_data = ('Different MAC address (%s/%s)' % ( + spd.get('publishedMacAddress'), mac_addr)) + continue + + if not found_port: + error_data = 'Port missing from SG policy' + + if error_data: + missing.append({'network': network_id, + 'policy': policy_id, + 'port': port['id'], + 'data': error_data}) + return missing + + +@admin_utils.output_header +def nsx_list_mismatch_addresses(resource, event, trigger, **kwargs): + """List missing spoofguard policies approved addresses on NSXv. + + Address pairs defined on neutron compute ports that are missing from the + NSX-V spoofguard policy of a specific/all networks. + """ + network_id = None + if kwargs.get('property'): + properties = admin_utils.parse_multi_keyval_opt(kwargs['property']) + network_id = properties.get('network') + + spgapi = utils.NeutronDbClient() + + if network_id: + policy_id = nsxv_db.get_spoofguard_policy_id( + spgapi.context.session, network_id) + if not policy_id: + LOG.error("Could not find spoofguard policy for neutron network " + "%s", network_id) + return + with utils.NsxVPluginWrapper() as plugin: + missing_data = nsx_list_mismatch_addresses_for_net( + spgapi.context, plugin, network_id, policy_id) + else: + with utils.NsxVPluginWrapper() as plugin: + missing_data = [] + # Go over all the networks with spoofguard policies + mappings = get_spoofguard_policy_network_mappings() + for entry in mappings: + missing_data.extend(nsx_list_mismatch_addresses_for_net( + spgapi.context, plugin, entry['network_id'], + entry['policy_id'])) + + if missing_data: + LOG.info(formatters.output_formatter( + constants.SPOOFGUARD_POLICY, missing_data, + ['network', 'policy', 'port', 'data'])) + else: + LOG.info("No mismatches found.") + + +@admin_utils.output_header +def nsx_fix_mismatch_addresses(resource, event, trigger, **kwargs): + """Fix missing spoofguard policies approved addresses for a port.""" + + port_id = None + if kwargs.get('property'): + properties = admin_utils.parse_multi_keyval_opt(kwargs['property']) + port_id = properties.get('port') + if not port_id: + usage_msg = ("Need to specify the id of the neutron port. " + "Add --property port=") + LOG.error(usage_msg) + return + + spgapi = utils.NeutronDbClient() + with utils.NsxVPluginWrapper() as plugin: + try: + port = plugin.get_port(spgapi.context, port_id) + except exceptions.PortNotFound: + LOG.error("Could not find neutron port %s", port_id) + return + vnic_id = get_port_vnic_id(plugin, port) + plugin._update_vnic_assigned_addresses( + spgapi.context.session, port, vnic_id) + LOG.info("Done.") + + def nsx_clean_spoofguard_policy(resource, event, trigger, **kwargs): """Delete spoofguard policy""" errmsg = ("Need to specify policy-id. Add --property " @@ -143,6 +279,12 @@ registry.subscribe(nsx_list_missing_spoofguard_policies, constants.SPOOFGUARD_POLICY, shell.Operations.LIST.value) +registry.subscribe(nsx_list_mismatch_addresses, + constants.SPOOFGUARD_POLICY, + shell.Operations.LIST_MISMATCHES.value) +registry.subscribe(nsx_fix_mismatch_addresses, + constants.SPOOFGUARD_POLICY, + shell.Operations.FIX_MISMATCH.value) registry.subscribe(nsx_clean_spoofguard_policy, constants.SPOOFGUARD_POLICY, shell.Operations.CLEAN.value) diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/shell/admin/plugins/nsxv3/resources/utils.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/shell/admin/plugins/nsxv3/resources/utils.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/shell/admin/plugins/nsxv3/resources/utils.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/shell/admin/plugins/nsxv3/resources/utils.py 2019-03-14 02:01:03.000000000 +0000 @@ -27,19 +27,10 @@ from vmware_nsx.extensions import projectpluginmap from vmware_nsx.plugins.nsx_v3 import plugin from vmware_nsx.plugins.nsx_v3 import utils as v3_utils -from vmware_nsx.services.fwaas.nsx_v3 import fwaas_callbacks_v1 from vmware_nsx.services.fwaas.nsx_v3 import fwaas_callbacks_v2 from vmware_nsx.shell.admin.plugins.common import utils as admin_utils from vmware_nsxlib.v3 import nsx_constants -try: - from neutron_fwaas.services.firewall import fwaas_plugin as fwaas_plugin_v1 -except ImportError: - # FWaaS project no found - from vmware_nsx.services.fwaas.common import fwaas_mocks \ - as fwaas_plugin_v1 - - _NSXLIB = None @@ -143,7 +134,7 @@ fwaas_plugin_class = manager.NeutronManager.load_class_for_provider( 'neutron.service_plugins', provider) fwaas_plugin = fwaas_plugin_class() - self.fwaas_callbacks = callbacks_class() + self.fwaas_callbacks = callbacks_class(False) # override the fwplugin_rpc since there is no RPC support in adminutils if plugin_callbacks: self.fwaas_callbacks.fwplugin_rpc = plugin_callbacks(fwaas_plugin) @@ -162,12 +153,6 @@ 'firewall_v2', fwaas_callbacks_v2.Nsxv3FwaasCallbacksV2, None) - else: - # FWaaS V1 - self._init_fwaas_plugin( - 'firewall', - fwaas_callbacks_v1.Nsxv3FwaasCallbacksV1, - fwaas_plugin_v1.FirewallCallbacks) return def _init_dhcp_metadata(self): diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/shell/resources.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/shell/resources.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/shell/resources.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/shell/resources.py 2019-03-14 02:01:03.000000000 +0000 @@ -176,7 +176,9 @@ [Operations.LIST.value]), constants.SPOOFGUARD_POLICY: Resource(constants.SPOOFGUARD_POLICY, [Operations.LIST.value, - Operations.CLEAN.value]), + Operations.CLEAN.value, + Operations.LIST_MISMATCHES.value, + Operations.FIX_MISMATCH.value]), constants.DHCP_BINDING: Resource(constants.DHCP_BINDING, [Operations.LIST.value, Operations.NSX_UPDATE.value, diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/tests/unit/dvs/test_plugin.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/tests/unit/dvs/test_plugin.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/tests/unit/dvs/test_plugin.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/tests/unit/dvs/test_plugin.py 2019-03-14 02:01:03.000000000 +0000 @@ -255,6 +255,50 @@ port_status = port['port']['status'] self.assertEqual(port_status, 'ACTIVE') + def test_create_dvs_port_vlan_no_port_security(self): + params = {'provider:network_type': 'vlan', + 'provider:physical_network': 'dvs', + 'provider:segmentation_id': 7} + params['arg_list'] = tuple(params.keys()) + with mock.patch.object(self._plugin._dvs, 'add_port_group'),\ + mock.patch.object(self._plugin._dvs, 'delete_port_group'),\ + mock.patch.object(dvs.DvsManager, 'get_dvs_moref_by_name'),\ + mock.patch.object(dvs.DvsManager, 'add_port_group'),\ + mock.patch.object(dvs.DvsManager, 'delete_port_group'): + with self.network(**params) as network,\ + self.subnet(network) as subnet,\ + self.port(subnet) as port: + self.assertEqual('dvs', + port['port'][portbindings.VIF_TYPE]) + port_security = port['port']['port_security_enabled'] + security_groups = port['port']['security_groups'] + self.assertEqual(port_security, False) + self.assertEqual(security_groups, []) + + def test_update_dvs_port_vlan_no_port_security(self): + params = {'provider:network_type': 'vlan', + 'provider:physical_network': 'dvs', + 'provider:segmentation_id': 7} + params['arg_list'] = tuple(params.keys()) + with mock.patch.object(self._plugin._dvs, 'add_port_group'),\ + mock.patch.object(self._plugin._dvs, 'delete_port_group'),\ + mock.patch.object(dvs.DvsManager, 'get_dvs_moref_by_name'),\ + mock.patch.object(dvs.DvsManager, 'add_port_group'),\ + mock.patch.object(dvs.DvsManager, 'delete_port_group'): + with self.network(**params) as network,\ + self.subnet(network) as subnet,\ + self.port(subnet) as port: + self.assertEqual('dvs', + port['port'][portbindings.VIF_TYPE]) + data = {'port': {'port_security_enabled': True}} + req = self.new_update_request('ports', + data, port['port']['id']) + res = self.deserialize('json', req.get_response(self.api)) + port_security = res['port']['port_security_enabled'] + security_groups = res['port']['security_groups'] + self.assertEqual(port_security, False) + self.assertEqual(security_groups, []) + def test_create_router_only_dvs_backend(self): data = {'router': {'tenant_id': 'whatever'}} data['router']['name'] = 'router1' @@ -337,3 +381,25 @@ 'admin_state_up': True}} self.assertRaises(exp.BadRequest, self._plugin.create_network, context.get_admin_context(), data) + + def test_create_vlan_network_fail_duplicate_dvs(self): + params = {'provider:network_type': 'vlan', + 'admin_state_up': True, + 'name': 'test_net', + 'tenant_id': 'fake_tenant', + 'shared': False, + 'provider:physical_network': 'fake-moid', + 'provider:segmentation_id': 7, + 'port_security_enabled': False} + + with mock.patch.object(self._plugin._dvs, + 'add_port_group'),\ + mock.patch.object(dvs.DvsManager, + 'add_port_group'),\ + mock.patch.object(dvs.DvsManager, + 'get_dvs_moref_by_name', + return_value=mock.MagicMock()): + ctx = context.get_admin_context() + self._plugin.create_network(ctx, {'network': params}) + self.assertRaises(exp.InvalidInput, self._plugin.create_network, + ctx, {'network': params}) diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/tests/unit/extensions/test_networkgw.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/tests/unit/extensions/test_networkgw.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/tests/unit/extensions/test_networkgw.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/tests/unit/extensions/test_networkgw.py 2019-03-14 02:01:03.000000000 +0000 @@ -83,7 +83,7 @@ # Instantiate mock plugin and enable extensions self.plugin.return_value.supported_extension_aliases = ( - [networkgw.EXT_ALIAS]) + [networkgw.ALIAS]) directory.add_plugin(constants.CORE, self.plugin.return_value) ext_mgr = TestExtensionManager() extensions.PluginAwareExtensionManager._instance = ext_mgr @@ -1096,7 +1096,7 @@ networkgw_db.NetworkGatewayMixin): """Simple plugin class for testing db support for network gateway ext.""" - supported_extension_aliases = ["network-gateway"] + supported_extension_aliases = [networkgw.ALIAS] def __init__(self, **args): super(TestNetworkGatewayPlugin, self).__init__(**args) diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/tests/unit/extensions/test_providernet.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/tests/unit/extensions/test_providernet.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/tests/unit/extensions/test_providernet.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/tests/unit/extensions/test_providernet.py 2019-03-14 02:01:03.000000000 +0000 @@ -25,6 +25,7 @@ class TestProvidernet(test_nsx_plugin.NsxPluginV2TestCase): def test_create_delete_provider_network_default_physical_net(self): + '''Leaves physical_net unspecified''' data = {'network': {'name': 'net1', 'admin_state_up': True, 'tenant_id': 'admin', @@ -33,6 +34,22 @@ network_req = self.new_create_request('networks', data, self.fmt) net = self.deserialize(self.fmt, network_req.get_response(self.api)) self.assertEqual(net['network'][pnet.NETWORK_TYPE], 'vlan') + self.assertEqual(net['network'][pnet.SEGMENTATION_ID], 411) + req = self.new_delete_request('networks', net['network']['id']) + res = req.get_response(self.api) + self.assertEqual(res.status_int, webob.exc.HTTPNoContent.code) + + def test_create_delete_provider_network_default_physical_net_2(self): + '''Uses the 'default' keyword as physical_net''' + data = {'network': {'name': 'net1', + 'admin_state_up': True, + 'tenant_id': 'admin', + pnet.NETWORK_TYPE: 'vlan', + pnet.SEGMENTATION_ID: 411, + pnet.PHYSICAL_NETWORK: 'default'}} + network_req = self.new_create_request('networks', data, self.fmt) + net = self.deserialize(self.fmt, network_req.get_response(self.api)) + self.assertEqual(net['network'][pnet.NETWORK_TYPE], 'vlan') self.assertEqual(net['network'][pnet.SEGMENTATION_ID], 411) req = self.new_delete_request('networks', net['network']['id']) res = req.get_response(self.api) diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/tests/unit/extensions/test_provider_security_groups.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/tests/unit/extensions/test_provider_security_groups.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/tests/unit/extensions/test_provider_security_groups.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/tests/unit/extensions/test_provider_security_groups.py 2019-03-14 02:01:03.000000000 +0000 @@ -42,7 +42,7 @@ securitygroups_db.SecurityGroupDbMixin): supported_extension_aliases = ["security-group", - "provider-security-group"] + provider_sg.ALIAS] def create_security_group(self, context, security_group, default_sg=False): secgroup = security_group['security_group'] diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/tests/unit/extensions/test_secgroup_rule_local_ip_prefix.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/tests/unit/extensions/test_secgroup_rule_local_ip_prefix.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/tests/unit/extensions/test_secgroup_rule_local_ip_prefix.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/tests/unit/extensions/test_secgroup_rule_local_ip_prefix.py 2019-03-14 02:01:03.000000000 +0000 @@ -45,7 +45,7 @@ securitygroups_db.SecurityGroupDbMixin): supported_extension_aliases = ["security-group", - "secgroup-rule-local-ip-prefix"] + ext_loip.ALIAS] def create_security_group_rule(self, context, security_group_rule): rule = security_group_rule['security_group_rule'] diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/tests/unit/extensions/test_securitygroup.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/tests/unit/extensions/test_securitygroup.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/tests/unit/extensions/test_securitygroup.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/tests/unit/extensions/test_securitygroup.py 2019-03-14 02:01:03.000000000 +0000 @@ -22,6 +22,8 @@ from vmware_nsxlib.v3 import exceptions as nsxlib_exc from vmware_nsxlib.v3 import nsx_constants as consts +from webob import exc + # Pool of fake ns-groups uuids NSG_IDS = ['11111111-1111-1111-1111-111111111111', @@ -84,6 +86,26 @@ for k, v, in keys: self.assertEqual(rule['security_group_rule'][k], v) + def test_create_security_group_with_manager_error(self): + '''Reboot in multi-cluster environment may cause temporary 404 in + firewall section APIs. We should return 503 and not 404 to the user + ''' + + name = 'webservers' + description = 'my webservers' + + with mock.patch("vmware_nsxlib.v3.security.NsxLibFirewallSection." + "create_section_rules", + side_effect=nsxlib_exc.ResourceNotFound): + try: + with self.security_group(name, description): + # This should not succeed + # (assertRaises would not work with generators) + self.assertTrue(False) + + except exc.HTTPClientError: + pass + class TestSecurityGroupsNoDynamicCriteria(test_nsxv3.NsxV3PluginTestCaseMixin, test_ext_sg.TestSecurityGroups): diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/tests/unit/extensions/test_vnic_index.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/tests/unit/extensions/test_vnic_index.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/tests/unit/extensions/test_vnic_index.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/tests/unit/extensions/test_vnic_index.py 2019-03-14 02:01:03.000000000 +0000 @@ -38,7 +38,7 @@ class VnicIndexTestPlugin(db_base_plugin_v2.NeutronDbPluginV2, vnic_index_db.VnicIndexDbMixin): - supported_extension_aliases = ["vnic-index"] + supported_extension_aliases = [vnicidx.ALIAS] def update_port(self, context, id, port): p = port['port'] diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/tests/unit/nsx_p/test_plugin.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/tests/unit/nsx_p/test_plugin.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/tests/unit/nsx_p/test_plugin.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/tests/unit/nsx_p/test_plugin.py 2019-03-14 02:01:03.000000000 +0000 @@ -52,6 +52,7 @@ from vmware_nsx.tests.unit.common_plugin import common_v3 from vmware_nsxlib.v3 import exceptions as nsxlib_exc from vmware_nsxlib.v3 import nsx_constants +from vmware_nsxlib.v3 import utils as nsxlib_utils from vmware_nsxlib.v3.policy import constants as policy_constants @@ -104,6 +105,8 @@ mock.patch( "vmware_nsxlib.v3.client.RESTClient.patch").start() mock.patch( + "vmware_nsxlib.v3.client.RESTClient.update").start() + mock.patch( "vmware_nsxlib.v3.client.RESTClient.delete").start() mock.patch("vmware_nsxlib.v3.policy.core_resources." "NsxPolicyCommunicationMapApi._get_last_seq_num", @@ -126,6 +129,13 @@ "NsxPolicySegmentApi.set_admin_state").start() mock.patch("vmware_nsxlib.v3.policy.core_resources." "NsxPolicySegmentPortApi.set_admin_state").start() + mock.patch("vmware_nsxlib.v3.NsxLib.get_tag_limits", + return_value=nsxlib_utils.TagLimits(20, 40, 15)).start() + # Add some nsxlib mocks for the passthrough apis + mock.patch("vmware_nsxlib.v3.NsxLib.get_version", + return_value=nsx_constants.NSX_VERSION_2_4_0).start() + mock.patch("vmware_nsxlib.v3.core_resources.NsxLibLogicalRouter." + "update").start() def _mock_nsxlib_backend_calls(self): """Mock nsxlib backend calls used as passthrough @@ -227,6 +237,8 @@ def setUp(self, plugin=PLUGIN_NAME, ext_mgr=None, service_plugins=None): + # add vlan transparent to the configuration + cfg.CONF.set_override('vlan_transparent', True) super(NsxPTestNetworks, self).setUp(plugin=plugin, ext_mgr=ext_mgr) @@ -403,31 +415,50 @@ # should fail self.assertEqual('InvalidInput', data['NeutronError']['type']) - def test_create_transparent_vlan_network(self): - providernet_args = {vlan_apidef.VLANTRANSPARENT: True} - with mock.patch('vmware_nsxlib.v3.policy.core_resources.' - 'NsxPolicyTransportZoneApi.get_transport_type', - return_value=nsx_constants.TRANSPORT_TYPE_OVERLAY), \ - self.network(name='vt_net', - providernet_args=providernet_args, - arg_list=(vlan_apidef.VLANTRANSPARENT, )) as net: - self.assertTrue(net['network'].get(vlan_apidef.VLANTRANSPARENT)) - - def test_create_provider_vlan_network_with_transparent(self): - providernet_args = {pnet.NETWORK_TYPE: 'vlan', + def _test_transparent_vlan_net(self, net_type, tz_type, should_succeed): + providernet_args = {pnet.NETWORK_TYPE: net_type, vlan_apidef.VLANTRANSPARENT: True} with mock.patch('vmware_nsxlib.v3.policy.core_resources.' 'NsxPolicyTransportZoneApi.get_transport_type', - return_value=nsx_constants.TRANSPORT_TYPE_VLAN): - result = self._create_network(fmt='json', name='badvlan_net', + return_value=tz_type): + result = self._create_network(fmt='json', name='vlan_net', admin_state_up=True, providernet_args=providernet_args, arg_list=( pnet.NETWORK_TYPE, - pnet.SEGMENTATION_ID, vlan_apidef.VLANTRANSPARENT)) data = self.deserialize('json', result) - self.assertEqual('vlan', data['network'].get(pnet.NETWORK_TYPE)) + if should_succeed: + self.assertEqual(net_type, + data['network'].get(pnet.NETWORK_TYPE)) + self.assertTrue( + data['network'].get(vlan_apidef.VLANTRANSPARENT)) + else: + self.assertEqual('InvalidInput', data['NeutronError']['type']) + + def test_create_non_provider_network_with_transparent(self): + self._test_transparent_vlan_net( + net_type="", + tz_type=nsx_constants.TRANSPORT_TYPE_OVERLAY, + should_succeed=False) + + def test_create_provider_overlay_network_with_transparent(self): + self._test_transparent_vlan_net( + net_type=utils.NsxV3NetworkTypes.GENEVE, + tz_type=nsx_constants.TRANSPORT_TYPE_OVERLAY, + should_succeed=False) + + def test_create_provider_flat_network_with_transparent(self): + self._test_transparent_vlan_net( + net_type=utils.NsxV3NetworkTypes.FLAT, + tz_type=nsx_constants.TRANSPORT_TYPE_VLAN, + should_succeed=True) + + def test_create_provider_vlan_network_with_transparent(self): + self._test_transparent_vlan_net( + net_type=utils.NsxV3NetworkTypes.VLAN, + tz_type=nsx_constants.TRANSPORT_TYPE_VLAN, + should_succeed=True) def test_network_update_external_failure(self): data = {'network': {'name': 'net1', @@ -757,6 +788,11 @@ res = self.plugin.get_port(self.ctx, port['id']) self.assertEqual(policy_id, res['qos_policy_id']) + # now remove the qos from the port + data['port']['qos_policy_id'] = None + res = self.plugin.update_port(self.ctx, port['id'], data) + self.assertIsNone(res['qos_policy_id']) + def test_create_ext_port_with_qos_fail(self): with self._create_l3_ext_network() as network: with self.subnet(network=network, cidr='10.0.0.0/24', @@ -953,6 +989,125 @@ self.assertEqual(exc.HTTPBadRequest.code, res.status_int) + def _test_create_direct_network(self, vlan_id=0): + net_type = vlan_id and 'vlan' or 'flat' + name = 'direct_net' + providernet_args = {pnet.NETWORK_TYPE: net_type, + pnet.PHYSICAL_NETWORK: 'tzuuid'} + if vlan_id: + providernet_args[pnet.SEGMENTATION_ID] = vlan_id + + mock_tt = mock.patch('vmware_nsxlib.v3.policy' + '.core_resources.NsxPolicyTransportZoneApi' + '.get_transport_type', + return_value=nsx_constants.TRANSPORT_TYPE_VLAN) + mock_tt.start() + return self.network(name=name, + providernet_args=providernet_args, + arg_list=(pnet.NETWORK_TYPE, + pnet.PHYSICAL_NETWORK, + pnet.SEGMENTATION_ID)) + + def _test_create_port_vnic_direct(self, vlan_id): + with mock.patch('vmware_nsxlib.v3.policy.core_resources.' + 'NsxPolicyTransportZoneApi.get_transport_type', + return_value=nsx_constants.TRANSPORT_TYPE_VLAN),\ + self._test_create_direct_network(vlan_id=vlan_id) as network: + # Check that port security conflicts + kwargs = {portbindings.VNIC_TYPE: portbindings.VNIC_DIRECT, + psec.PORTSECURITY: True} + net_id = network['network']['id'] + res = self._create_port(self.fmt, net_id=net_id, + arg_list=(portbindings.VNIC_TYPE, + psec.PORTSECURITY), + **kwargs) + self.assertEqual(res.status_int, exc.HTTPBadRequest.code) + + # Check that security group conflicts + kwargs = {portbindings.VNIC_TYPE: portbindings.VNIC_DIRECT, + 'security_groups': [ + '4cd70774-cc67-4a87-9b39-7d1db38eb087'], + psec.PORTSECURITY: False} + net_id = network['network']['id'] + res = self._create_port(self.fmt, net_id=net_id, + arg_list=(portbindings.VNIC_TYPE, + psec.PORTSECURITY), + **kwargs) + self.assertEqual(res.status_int, exc.HTTPBadRequest.code) + + # All is kosher so we can create the port + kwargs = {portbindings.VNIC_TYPE: portbindings.VNIC_DIRECT} + net_id = network['network']['id'] + res = self._create_port(self.fmt, net_id=net_id, + arg_list=(portbindings.VNIC_TYPE,), + **kwargs) + port = self.deserialize('json', res) + self.assertEqual("direct", port['port'][portbindings.VNIC_TYPE]) + self.assertEqual("dvs", port['port'][portbindings.VIF_TYPE]) + self.assertEqual( + vlan_id, + port['port'][portbindings.VIF_DETAILS]['segmentation-id']) + + # try to get the same port + req = self.new_show_request('ports', port['port']['id'], self.fmt) + sport = self.deserialize(self.fmt, req.get_response(self.api)) + self.assertEqual("dvs", sport['port'][portbindings.VIF_TYPE]) + self.assertEqual("direct", sport['port'][portbindings.VNIC_TYPE]) + self.assertEqual( + vlan_id, + sport['port'][portbindings.VIF_DETAILS]['segmentation-id']) + + def test_create_port_vnic_direct_flat(self): + self._test_create_port_vnic_direct(0) + + def test_create_port_vnic_direct_vlan(self): + self._test_create_port_vnic_direct(10) + + def test_create_port_vnic_direct_invalid_network(self): + with self.network(name='not vlan/flat') as net: + kwargs = {portbindings.VNIC_TYPE: portbindings.VNIC_DIRECT, + psec.PORTSECURITY: False} + net_id = net['network']['id'] + res = self._create_port(self.fmt, net_id=net_id, + arg_list=(portbindings.VNIC_TYPE, + psec.PORTSECURITY), + **kwargs) + self.assertEqual(exc.HTTPBadRequest.code, res.status_int) + + def test_update_vnic_direct(self): + with self._test_create_direct_network(vlan_id=7) as network: + with self.subnet(network=network) as subnet: + with self.port(subnet=subnet) as port: + # need to do two updates as the update for port security + # disabled requires that it can only change 2 items + data = {'port': {psec.PORTSECURITY: False, + 'security_groups': []}} + req = self.new_update_request('ports', + data, port['port']['id']) + res = self.deserialize('json', req.get_response(self.api)) + self.assertEqual(portbindings.VNIC_NORMAL, + res['port'][portbindings.VNIC_TYPE]) + + data = {'port': {portbindings.VNIC_TYPE: + portbindings.VNIC_DIRECT}} + + req = self.new_update_request('ports', + data, port['port']['id']) + res = self.deserialize('json', req.get_response(self.api)) + self.assertEqual(portbindings.VNIC_DIRECT, + res['port'][portbindings.VNIC_TYPE]) + + def test_port_invalid_vnic_type(self): + with self._test_create_direct_network(vlan_id=7) as network: + kwargs = {portbindings.VNIC_TYPE: 'invalid', + psec.PORTSECURITY: False} + net_id = network['network']['id'] + res = self._create_port(self.fmt, net_id=net_id, + arg_list=(portbindings.VNIC_TYPE, + psec.PORTSECURITY), + **kwargs) + self.assertEqual(res.status_int, exc.HTTPBadRequest.code) + class NsxPTestSubnets(test_db_base_plugin_v2.TestSubnetsV2, NsxPPluginTestCaseMixin): @@ -1116,6 +1271,7 @@ def setUp(self, plugin=PLUGIN_NAME, ext_mgr=None): super(NsxPTestSecurityGroup, self).setUp(plugin=plugin, ext_mgr=ext_mgr) + self.project_id = test_db_base_plugin_v2.TEST_TENANT_ID def test_create_security_group_rule_icmp_with_type_and_code(self): """No non-zero icmp codes are currently supported by the NSX""" @@ -1147,130 +1303,82 @@ for k, v, in keys: self.assertEqual(rule['security_group_rule'][k], v) - def _test_create_direct_network(self, vlan_id=0): - net_type = vlan_id and 'vlan' or 'flat' - name = 'direct_net' - providernet_args = {pnet.NETWORK_TYPE: net_type, - pnet.PHYSICAL_NETWORK: 'tzuuid'} - if vlan_id: - providernet_args[pnet.SEGMENTATION_ID] = vlan_id - - mock_tt = mock.patch('vmware_nsxlib.v3.policy' - '.core_resources.NsxPolicyTransportZoneApi' - '.get_transport_type', - return_value=nsx_constants.TRANSPORT_TYPE_VLAN) - mock_tt.start() - return self.network(name=name, - providernet_args=providernet_args, - arg_list=(pnet.NETWORK_TYPE, - pnet.PHYSICAL_NETWORK, - pnet.SEGMENTATION_ID)) - - def _test_create_port_vnic_direct(self, vlan_id): - with mock.patch('vmware_nsxlib.v3.policy.core_resources.' - 'NsxPolicyTransportZoneApi.get_transport_type', - return_value=nsx_constants.TRANSPORT_TYPE_VLAN),\ - self._test_create_direct_network(vlan_id=vlan_id) as network: - # Check that port security conflicts - kwargs = {portbindings.VNIC_TYPE: portbindings.VNIC_DIRECT, - psec.PORTSECURITY: True} - net_id = network['network']['id'] - res = self._create_port(self.fmt, net_id=net_id, - arg_list=(portbindings.VNIC_TYPE, - psec.PORTSECURITY), - **kwargs) - self.assertEqual(res.status_int, exc.HTTPBadRequest.code) - - # Check that security group conflicts - kwargs = {portbindings.VNIC_TYPE: portbindings.VNIC_DIRECT, - 'security_groups': [ - '4cd70774-cc67-4a87-9b39-7d1db38eb087'], - psec.PORTSECURITY: False} - net_id = network['network']['id'] - res = self._create_port(self.fmt, net_id=net_id, - arg_list=(portbindings.VNIC_TYPE, - psec.PORTSECURITY), - **kwargs) - self.assertEqual(res.status_int, exc.HTTPBadRequest.code) - - # All is kosher so we can create the port - kwargs = {portbindings.VNIC_TYPE: portbindings.VNIC_DIRECT} - net_id = network['network']['id'] - res = self._create_port(self.fmt, net_id=net_id, - arg_list=(portbindings.VNIC_TYPE,), - **kwargs) - port = self.deserialize('json', res) - self.assertEqual("direct", port['port'][portbindings.VNIC_TYPE]) - self.assertEqual("dvs", port['port'][portbindings.VIF_TYPE]) - self.assertEqual( - vlan_id, - port['port'][portbindings.VIF_DETAILS]['segmentation-id']) - - # try to get the same port - req = self.new_show_request('ports', port['port']['id'], self.fmt) - sport = self.deserialize(self.fmt, req.get_response(self.api)) - self.assertEqual("dvs", sport['port'][portbindings.VIF_TYPE]) - self.assertEqual("direct", sport['port'][portbindings.VNIC_TYPE]) - self.assertEqual( - vlan_id, - sport['port'][portbindings.VIF_DETAILS]['segmentation-id']) - - def test_create_port_vnic_direct_flat(self): - self._test_create_port_vnic_direct(0) - - def test_create_port_vnic_direct_vlan(self): - self._test_create_port_vnic_direct(10) - - def test_create_port_vnic_direct_invalid_network(self): - with self.network(name='not vlan/flat') as net: - kwargs = {portbindings.VNIC_TYPE: portbindings.VNIC_DIRECT, - psec.PORTSECURITY: False} - net_id = net['network']['id'] - res = self._create_port(self.fmt, net_id=net_id, - arg_list=(portbindings.VNIC_TYPE, - psec.PORTSECURITY), - **kwargs) - self.assertEqual(exc.HTTPBadRequest.code, res.status_int) - - def test_update_vnic_direct(self): - with self._test_create_direct_network(vlan_id=7) as network: - with self.subnet(network=network) as subnet: - with self.port(subnet=subnet) as port: - # need to do two updates as the update for port security - # disabled requires that it can only change 2 items - data = {'port': {psec.PORTSECURITY: False, - 'security_groups': []}} - req = self.new_update_request('ports', - data, port['port']['id']) - res = self.deserialize('json', req.get_response(self.api)) - self.assertEqual(portbindings.VNIC_NORMAL, - res['port'][portbindings.VNIC_TYPE]) - - data = {'port': {portbindings.VNIC_TYPE: - portbindings.VNIC_DIRECT}} - - req = self.new_update_request('ports', - data, port['port']['id']) - res = self.deserialize('json', req.get_response(self.api)) - self.assertEqual(portbindings.VNIC_DIRECT, - res['port'][portbindings.VNIC_TYPE]) - - def test_port_invalid_vnic_type(self): - with self._test_create_direct_network(vlan_id=7) as network: - kwargs = {portbindings.VNIC_TYPE: 'invalid', - psec.PORTSECURITY: False} - net_id = network['network']['id'] - res = self._create_port(self.fmt, net_id=net_id, - arg_list=(portbindings.VNIC_TYPE, - psec.PORTSECURITY), - **kwargs) - self.assertEqual(res.status_int, exc.HTTPBadRequest.code) - @common_v3.with_no_dhcp_subnet def test_list_ports_security_group(self): return super(NsxPTestSecurityGroup, self).test_list_ports_security_group() + @mock.patch.object(nsx_plugin.NsxPolicyPlugin, 'get_security_group') + def test_create_security_group_rule_with_invalid_tcp_or_udp_protocol( + self, get_mock): + super(NsxPTestSecurityGroup, self).\ + test_create_security_group_rule_with_invalid_tcp_or_udp_protocol() + + @mock.patch.object(nsx_plugin.NsxPolicyPlugin, 'get_security_group') + def test_create_security_group_source_group_ip_and_ip_prefix( + self, get_mock): + super(NsxPTestSecurityGroup, self).\ + test_create_security_group_source_group_ip_and_ip_prefix() + + def _create_default_sg(self): + self.plugin._ensure_default_security_group( + context.get_admin_context(), self.project_id) + + def test_sg_create_on_nsx(self): + """Verify that a group and comm-map are created for a new SG""" + # Make sure the default SG is created before testing + self._create_default_sg() + name = description = 'sg1' + with mock.patch("vmware_nsxlib.v3.policy.core_resources." + "NsxPolicyGroupApi.create_or_overwrite_with_conditions" + ) as group_create,\ + mock.patch("vmware_nsxlib.v3.policy.core_resources." + "NsxPolicyCommunicationMapApi." + "create_or_overwrite_map_only") as comm_map_create,\ + self.security_group(name, description) as sg: + sg_id = sg['security_group']['id'] + nsx_name = utils.get_name_and_uuid(name, sg_id) + group_create.assert_called_once_with( + nsx_name, self.project_id, group_id=sg_id, + description=description, + conditions=[mock.ANY], tags=mock.ANY) + comm_map_create.assert_called_once_with( + nsx_name, self.project_id, map_id=sg_id, + description=description, + tags=mock.ANY, + category=policy_constants.CATEGORY_ENVIRONMENT) + + def test_sg_rule_create_on_nsx(self): + """Verify that a comm-map entry is created for a new SG rule """ + name = description = 'sg1' + direction = "ingress" + remote_ip_prefix = "10.0.0.0/24" + protocol = "tcp" + port_range_min = 80 + port_range_max = 80 + with self.security_group(name, description) as sg: + sg_id = sg['security_group']['id'] + with mock.patch("vmware_nsxlib.v3.policy.core_resources." + "NsxPolicyCommunicationMapApi.create_entry" + ) as entry_create,\ + self.security_group_rule(sg_id, direction, + protocol, port_range_min, + port_range_max, + remote_ip_prefix) as rule: + rule_id = rule['security_group_rule']['id'] + scope = [self.plugin.nsxpolicy.group.get_path( + self.project_id, sg_id)] + entry_create.assert_called_once_with( + rule_id, self.project_id, sg_id, entry_id=rule_id, + description='', + direction=nsx_constants.IN, + action=policy_constants.ACTION_ALLOW, + service_ids=mock.ANY, + source_groups=mock.ANY, + dest_groups=mock.ANY, + scope=scope, + logged=False) + class NsxPTestL3ExtensionManager(object): @@ -1785,6 +1893,9 @@ self.subnet(network=ext_net, cidr='10.0.1.0/24', enable_dhcp=False) as s,\ mock.patch("vmware_nsxlib.v3.policy.core_resources." + "NsxPolicyTier1Api.get_edge_cluster_path", + return_value=False),\ + mock.patch("vmware_nsxlib.v3.policy.core_resources." "NsxPolicyTier1Api.set_edge_cluster_path" ) as add_srv_router: self._add_external_gateway_to_router( diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/tests/unit/nsx_v/test_fwaas_driver.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/tests/unit/nsx_v/test_fwaas_driver.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/tests/unit/nsx_v/test_fwaas_driver.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/tests/unit/nsx_v/test_fwaas_driver.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,247 +0,0 @@ -# Copyright 2017 VMware, Inc. -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import copy - -import mock -from neutron_lib.exceptions import firewall_v1 as exceptions -from oslo_utils import uuidutils - -from vmware_nsx.services.fwaas.nsx_v import edge_fwaas_driver -from vmware_nsx.tests.unit.nsx_v import test_plugin as test_v_plugin - -FAKE_FW_ID = 'fake_fw_uuid' - - -class NsxvFwaasTestCase(test_v_plugin.NsxVPluginV2TestCase): - def setUp(self): - super(NsxvFwaasTestCase, self).setUp() - self.firewall = edge_fwaas_driver.EdgeFwaasDriver() - - def _fake_rules_v4(self): - rule1 = {'enabled': True, - 'action': 'allow', - 'ip_version': 4, - 'protocol': 'tcp', - 'destination_port': '80', - 'source_port': '1-65535', - 'source_ip_address': '10.24.4.2', - 'id': 'fake-fw-rule1'} - rule2 = {'enabled': True, - 'action': 'deny', - 'ip_version': 4, - 'protocol': 'tcp', - 'destination_port': '22', - 'id': 'fake-fw-rule2'} - rule3 = {'enabled': True, - 'action': 'reject', - 'ip_version': 4, - 'protocol': 'tcp', - 'destination_port': '23', - 'id': 'fake-fw-rule3'} - return [rule1, rule2, rule3] - - def _fake_backend_rules_v4(self, logged=False): - rule1 = {'enabled': True, - 'action': 'allow', - 'ip_version': 4, - 'protocol': 'tcp', - 'destination_port': '80', - 'source_port': '1-65535', - 'source_ip_address': ['10.24.4.2'], - 'position': '0', - 'id': 'fake-fw-rule1', - 'name': 'Fwaas-fake-fw-rule1'} - rule2 = {'enabled': True, - 'action': 'deny', - 'ip_version': 4, - 'protocol': 'tcp', - 'destination_port': '22', - 'id': 'fake-fw-rule2', - 'position': '1', - 'name': 'Fwaas-fake-fw-rule2'} - rule3 = {'enabled': True, - 'action': 'reject', - 'ip_version': 4, - 'protocol': 'tcp', - 'destination_port': '23', - 'position': '2', - 'id': 'fake-fw-rule3', - 'name': 'Fwaas-fake-fw-rule3'} - if logged: - for rule in (rule1, rule2, rule3): - rule['loggingEnabled'] = logged - return [rule1, rule2, rule3] - - def _fake_firewall_no_rule(self): - rule_list = [] - fw_inst = {'id': FAKE_FW_ID, - 'admin_state_up': True, - 'tenant_id': 'tenant-uuid', - 'firewall_rule_list': rule_list} - return fw_inst - - def _fake_firewall(self, rule_list): - _rule_list = copy.deepcopy(rule_list) - for rule in _rule_list: - rule['position'] = str(_rule_list.index(rule)) - fw_inst = {'id': FAKE_FW_ID, - 'admin_state_up': True, - 'tenant_id': 'tenant-uuid', - 'firewall_rule_list': _rule_list} - return fw_inst - - def _fake_firewall_with_admin_down(self, rule_list): - fw_inst = {'id': FAKE_FW_ID, - 'admin_state_up': False, - 'tenant_id': 'tenant-uuid', - 'firewall_rule_list': rule_list} - return fw_inst - - def _fake_apply_list(self, router_count=1): - apply_list = [] - while router_count > 0: - rtr_id = uuidutils.generate_uuid() - router_inst = {'id': rtr_id} - router_info_inst = mock.Mock() - router_info_inst.router = router_inst - router_info_inst.router_id = rtr_id - apply_list.append(router_info_inst) - router_count -= 1 - return apply_list - - def _get_fake_mapping(self, apply_list): - router_edge_map = {} - for router_info in apply_list: - router_edge_map[router_info.router_id] = { - 'edge_id': 'edge-1', - 'lookup_id': router_info.router_id} - return router_edge_map - - def _setup_firewall_with_rules(self, func, router_count=1): - apply_list = self._fake_apply_list(router_count=router_count) - rule_list = self._fake_rules_v4() - firewall = self._fake_firewall(rule_list) - edges = self._get_fake_mapping(apply_list) - - with mock.patch("vmware_nsx.plugins.nsx_v.plugin.NsxVPluginV2." - "update_router_firewall") as update_fw,\ - mock.patch("vmware_nsx.plugins.nsx_v.plugin.NsxVPluginV2." - "_get_router"),\ - mock.patch.object(self.firewall, - "_get_routers_edges", return_value=edges): - func('nsx', apply_list, firewall) - self.assertEqual(router_count, update_fw.call_count) - # Validate the args of the last call - self.assertEqual(apply_list[-1].router_id, - update_fw.call_args[0][1]) - backend_rules = update_fw.call_args[1]['fwaas_rules'] - self.assertEqual(len(rule_list), len(backend_rules)) - self.assertEqual(self._fake_backend_rules_v4(), backend_rules) - - def test_create_firewall_no_rules(self): - apply_list = self._fake_apply_list() - firewall = self._fake_firewall_no_rule() - edges = self._get_fake_mapping(apply_list) - with mock.patch("vmware_nsx.plugins.nsx_v.plugin.NsxVPluginV2." - "update_router_firewall") as update_fw,\ - mock.patch("vmware_nsx.plugins.nsx_v.plugin.NsxVPluginV2." - "_get_router"),\ - mock.patch.object(self.firewall, - "_get_routers_edges", return_value=edges): - self.firewall.create_firewall('nsx', apply_list, firewall) - self.assertEqual(1, update_fw.call_count) - # Validate the args of the last call - self.assertEqual(apply_list[0].router_id, - update_fw.call_args[0][1]) - backend_rules = update_fw.call_args[1]['fwaas_rules'] - self.assertEqual([], backend_rules) - - def test_create_firewall_with_rules(self): - self._setup_firewall_with_rules(self.firewall.create_firewall) - - def test_create_firewall_with_rules_two_routers(self): - self._setup_firewall_with_rules(self.firewall.create_firewall, - router_count=2) - - def test_update_firewall_with_rules(self): - self._setup_firewall_with_rules(self.firewall.update_firewall) - - def test_delete_firewall(self): - apply_list = self._fake_apply_list() - firewall = self._fake_firewall_no_rule() - edges = self._get_fake_mapping(apply_list) - with mock.patch("vmware_nsx.plugins.nsx_v.plugin.NsxVPluginV2." - "update_router_firewall") as update_fw,\ - mock.patch("vmware_nsx.plugins.nsx_v.plugin.NsxVPluginV2." - "_get_router"),\ - mock.patch.object(self.firewall, - "_get_routers_edges", return_value=edges): - self.firewall.delete_firewall('nsx', apply_list, firewall) - self.assertEqual(1, update_fw.call_count) - # Validate the args of the last call - self.assertEqual(apply_list[0].router_id, - update_fw.call_args[0][1]) - backend_rules = update_fw.call_args[1]['fwaas_rules'] - self.assertIsNone(backend_rules) - - def test_create_firewall_with_admin_down(self): - apply_list = self._fake_apply_list() - rule_list = self._fake_rules_v4() - firewall = self._fake_firewall_with_admin_down(rule_list) - edges = self._get_fake_mapping(apply_list) - with mock.patch("vmware_nsx.plugins.nsx_v.plugin.NsxVPluginV2." - "update_router_firewall") as update_fw,\ - mock.patch("vmware_nsx.plugins.nsx_v.plugin.NsxVPluginV2." - "_get_router"),\ - mock.patch.object(self.firewall, - "_get_routers_edges", return_value=edges): - self.firewall.create_firewall('nsx', apply_list, firewall) - self.assertEqual(1, update_fw.call_count) - # Validate the args of the last call - self.assertEqual(apply_list[0].router_id, - update_fw.call_args[0][1]) - backend_rules = update_fw.call_args[1]['fwaas_rules'] - self.assertEqual([], backend_rules) - - def test_should_apply_firewall_to_router(self): - router = {'id': 'fake_id', - 'external_gateway_info': 'fake_data', - 'router_type': 'exclusive', - 'distributed': False} - self.assertTrue(self.firewall.should_apply_firewall_to_router(router)) - - # no external gateway: - router['external_gateway_info'] = None - self.assertFalse(self.firewall.should_apply_firewall_to_router(router)) - router['external_gateway_info'] = 'Dummy' - - # not for shared router: - router['router_type'] = 'shared' - router['distributed'] = False - self.assertRaises(exceptions.FirewallInternalDriverError, - self.firewall.should_apply_firewall_to_router, - router) - - # should work for distributed router - router['router_type'] = 'exclusive' - router['distributed'] = True - self.assertTrue(self.firewall.should_apply_firewall_to_router(router)) - - # not for mdproxy router: - router['name'] = 'metadata_proxy_router' - self.assertRaises(exceptions.FirewallInternalDriverError, - self.firewall.should_apply_firewall_to_router, - router) diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/tests/unit/nsx_v/test_fwaas_v2_driver.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/tests/unit/nsx_v/test_fwaas_v2_driver.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/tests/unit/nsx_v/test_fwaas_v2_driver.py 1970-01-01 00:00:00.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/tests/unit/nsx_v/test_fwaas_v2_driver.py 2019-03-14 02:01:03.000000000 +0000 @@ -0,0 +1,295 @@ +# 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. + +import copy + +import mock + +from neutron_lib.plugins import directory + +from vmware_nsx.db import nsxv_models +from vmware_nsx.plugins.nsx_v.vshield import edge_firewall_driver +from vmware_nsx.plugins.nsx_v.vshield import edge_utils +from vmware_nsx.services.fwaas.nsx_v import edge_fwaas_driver_v2 +from vmware_nsx.services.fwaas.nsx_v import fwaas_callbacks_v2 +from vmware_nsx.tests.unit.nsx_v import test_plugin as test_v_plugin + +FAKE_FW_ID = 'fake_fw_uuid' +FAKE_ROUTER_ID = 'fake_rtr_uuid' +FAKE_PORT_ID = 'fake_port_uuid' +FAKE_NET_ID = 'fake_net_uuid' +FAKE_DB_OBJ = nsxv_models.NsxvEdgeVnicBinding(vnic_index='1') + + +class NsxvFwaasTestCase(test_v_plugin.NsxVPluginV2TestCase): + def setUp(self): + super(NsxvFwaasTestCase, self).setUp() + self.firewall = edge_fwaas_driver_v2.EdgeFwaasVDriverV2() + + self.plugin = directory.get_plugin() + self.plugin.fwaas_callbacks = fwaas_callbacks_v2.\ + NsxvFwaasCallbacksV2(False) + self.plugin.fwaas_callbacks.fwaas_enabled = True + self.plugin.fwaas_callbacks.fwaas_driver = self.firewall + self.plugin.fwaas_callbacks.internal_driver = self.firewall + self.plugin.init_is_complete = True + self.plugin.metadata_proxy_handler = None + + # Start some mocks + self.router = {'id': FAKE_ROUTER_ID, + 'external_gateway_info': {'network_id': 'external'}} + mock.patch.object(self.plugin, '_get_router', + return_value=self.router).start() + mock.patch.object(self.plugin, 'get_router', + return_value=self.router).start() + self.port = {'id': FAKE_PORT_ID, 'network_id': FAKE_NET_ID} + mock.patch.object(self.plugin, '_get_router_interfaces', + return_value=[self.port]).start() + mock.patch.object(self.plugin, 'get_port', + return_value=self.port).start() + mock.patch.object(self.plugin, '_get_subnet_fw_rules', + return_value=[]).start() + mock.patch.object(self.plugin, '_get_dnat_fw_rule', + return_value=[]).start() + mock.patch.object(self.plugin, '_get_allocation_pools_fw_rule', + return_value=[]).start() + mock.patch.object(self.plugin, '_get_nosnat_subnets_fw_rules', + return_value=[]).start() + + def _fake_rules_v4(self, is_ingress=True, is_conflict=False, + cidr='10.24.4.0/24'): + rule1 = {'enabled': True, + 'action': 'allow', + 'ip_version': 4, + 'protocol': 'tcp', + 'destination_port': '80', + 'id': 'fake-fw-rule1', + 'description': 'first rule', + 'position': '0'} + rule2 = {'enabled': True, + 'action': 'reject', + 'ip_version': 4, + 'protocol': 'tcp', + 'destination_port': '22:24', + 'source_port': '1:65535', + 'id': 'fake-fw-rule2', + 'position': '1'} + rule3 = {'enabled': True, + 'action': 'deny', + 'ip_version': 4, + 'protocol': 'icmp', + 'id': 'fake-fw-rule3', + 'position': '2'} + rule4 = {'enabled': True, + 'action': 'deny', + 'ip_version': 4, + 'id': 'fake-fw-rule4', + 'position': '3'} + if is_ingress: + if not is_conflict: + rule1['source_ip_address'] = cidr + else: + rule1['destination_ip_address'] = cidr + else: + if not is_conflict: + rule1['destination_ip_address'] = cidr + else: + rule1['source_ip_address'] = cidr + + return [rule1, rule2, rule3, rule4] + + def _fake_translated_rules(self, rules_list, + nsx_port_id, + is_ingress=True, + logged=False): + translated_rules = copy.copy(rules_list) + for rule in translated_rules: + if logged: + rule['logged'] = True + if is_ingress: + if not rule.get('destination_ip_address'): + rule['destination_vnic_groups'] = ['vnic-index-1'] + else: + if not rule.get('source_ip_address'): + rule['source_vnic_groups'] = ['vnic-index-1'] + if rule.get('destination_ip_address'): + rule['destination_ip_address'] = [ + rule['destination_ip_address']] + if rule.get('source_ip_address'): + rule['source_ip_address'] = [ + rule['source_ip_address']] + rule['name'] = (fwaas_callbacks_v2.RULE_NAME_PREFIX + + (rule.get('name') or rule['id']))[:30] + if rule.get('id'): + if is_ingress: + rule['id'] = ('ingress-%s' % rule['id'])[:36] + else: + rule['id'] = ('egress-%s' % rule['id'])[:36] + + return translated_rules + + def _fake_empty_firewall_group(self): + fw_inst = {'id': FAKE_FW_ID, + 'admin_state_up': True, + 'tenant_id': 'tenant-uuid', + 'ingress_rule_list': [], + 'egress_rule_list': []} + return fw_inst + + def _fake_firewall_group(self, rule_list, is_ingress=True, + admin_state_up=True): + _rule_list = copy.deepcopy(rule_list) + for rule in _rule_list: + rule['position'] = str(_rule_list.index(rule)) + fw_inst = {'id': FAKE_FW_ID, + 'admin_state_up': admin_state_up, + 'tenant_id': 'tenant-uuid', + 'ingress_rule_list': [], + 'egress_rule_list': []} + if is_ingress: + fw_inst['ingress_rule_list'] = _rule_list + else: + fw_inst['egress_rule_list'] = _rule_list + return fw_inst + + def _fake_firewall_group_with_admin_down(self, rule_list, + is_ingress=True): + return self._fake_firewall_group( + rule_list, is_ingress=is_ingress, admin_state_up=False) + + def _fake_apply_list(self): + router_inst = self.router + router_info_inst = mock.Mock() + router_info_inst.router = router_inst + router_info_inst.router_id = FAKE_ROUTER_ID + apply_list = [(router_info_inst, FAKE_PORT_ID)] + return apply_list + + def test_create_firewall_no_rules(self): + apply_list = self._fake_apply_list() + firewall = self._fake_empty_firewall_group() + with mock.patch.object(self.plugin.fwaas_callbacks, 'get_port_fwg', + return_value=firewall),\ + mock.patch.object(self.plugin.fwaas_callbacks, + '_get_port_firewall_group_id', + return_value=FAKE_FW_ID),\ + mock.patch.object(self.plugin.fwaas_callbacks, + '_get_fw_group_from_plugin', + return_value=firewall),\ + mock.patch("vmware_nsx.db.nsxv_db.get_edge_vnic_binding", + return_value=FAKE_DB_OBJ),\ + mock.patch.object(edge_utils, "update_firewall") as update_fw,\ + mock.patch.object(edge_utils, 'get_router_edge_id', + return_value='edge-1'): + self.firewall.create_firewall_group('nsx', apply_list, firewall) + # expecting 2 block rules for the logical port (egress & ingress) + # and last default allow all rule + expected_rules = [ + {'name': "Block port ingress", + 'action': edge_firewall_driver.FWAAS_DENY, + 'destination_vnic_groups': ['vnic-index-1'], + 'logged': False}, + {'name': "Block port egress", + 'action': edge_firewall_driver.FWAAS_DENY, + 'source_vnic_groups': ['vnic-index-1'], + 'logged': False}] + update_fw.assert_called_once_with( + self.plugin.nsx_v, mock.ANY, FAKE_ROUTER_ID, + {'firewall_rule_list': expected_rules}) + + def _setup_firewall_with_rules(self, func, is_ingress=True, + is_conflict=False): + apply_list = self._fake_apply_list() + rule_list = self._fake_rules_v4(is_ingress=is_ingress, + is_conflict=is_conflict) + firewall = self._fake_firewall_group(rule_list, is_ingress=is_ingress) + with mock.patch.object(self.plugin.fwaas_callbacks, 'get_port_fwg', + return_value=firewall),\ + mock.patch.object(self.plugin.fwaas_callbacks, + '_get_port_firewall_group_id', + return_value=FAKE_FW_ID),\ + mock.patch.object(self.plugin.fwaas_callbacks, + '_get_fw_group_from_plugin', + return_value=firewall),\ + mock.patch("vmware_nsx.db.nsxv_db.get_edge_vnic_binding", + return_value=FAKE_DB_OBJ),\ + mock.patch.object(edge_utils, "update_firewall") as update_fw,\ + mock.patch.object(edge_utils, 'get_router_edge_id', + return_value='edge-1'): + func('nsx', apply_list, firewall) + expected_rules = self._fake_translated_rules( + rule_list, + 'vnic-index-1', is_ingress=is_ingress) + [ + {'name': "Block port ingress", + 'action': edge_firewall_driver.FWAAS_DENY, + 'destination_vnic_groups': ['vnic-index-1'], + 'logged': False}, + {'name': "Block port egress", + 'action': edge_firewall_driver.FWAAS_DENY, + 'source_vnic_groups': ['vnic-index-1'], + 'logged': False}] + + update_fw.assert_called_once_with( + self.plugin.nsx_v, mock.ANY, FAKE_ROUTER_ID, + {'firewall_rule_list': expected_rules}) + + def test_create_firewall_with_ingress_rules(self): + self._setup_firewall_with_rules(self.firewall.create_firewall_group) + + def test_update_firewall_with_ingress_rules(self): + self._setup_firewall_with_rules(self.firewall.update_firewall_group) + + def test_create_firewall_with_egress_rules(self): + self._setup_firewall_with_rules(self.firewall.create_firewall_group, + is_ingress=False) + + def test_update_firewall_with_egress_rules(self): + self._setup_firewall_with_rules(self.firewall.update_firewall_group, + is_ingress=False) + + def test_update_firewall_with_egress_conflicting_rules(self): + self._setup_firewall_with_rules(self.firewall.update_firewall_group, + is_ingress=False, is_conflict=True) + + def test_update_firewall_with_ingress_conflicting_rules(self): + self._setup_firewall_with_rules(self.firewall.update_firewall_group, + is_ingress=True, is_conflict=True) + + def test_delete_firewall(self): + apply_list = self._fake_apply_list() + firewall = self._fake_empty_firewall_group() + with mock.patch.object(self.plugin.fwaas_callbacks, 'get_port_fwg', + return_value=None),\ + mock.patch("vmware_nsx.db.db.get_nsx_switch_and_port_id", + return_value=('vnic-index-1', 0)),\ + mock.patch.object(edge_utils, "update_firewall") as update_fw,\ + mock.patch.object(edge_utils, 'get_router_edge_id', + return_value='edge-1'): + self.firewall.delete_firewall_group('nsx', apply_list, firewall) + update_fw.assert_called_once_with( + self.plugin.nsx_v, mock.ANY, FAKE_ROUTER_ID, + {'firewall_rule_list': []}) + + def test_create_firewall_with_admin_down(self): + apply_list = self._fake_apply_list() + rule_list = self._fake_rules_v4() + firewall = self._fake_firewall_group_with_admin_down(rule_list) + with mock.patch.object(edge_utils, "update_firewall") as update_fw,\ + mock.patch.object(edge_utils, 'get_router_edge_id', + return_value='edge-1'): + self.firewall.create_firewall_group('nsx', apply_list, firewall) + update_fw.assert_called_once_with( + self.plugin.nsx_v, mock.ANY, FAKE_ROUTER_ID, + {'firewall_rule_list': []}) diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/tests/unit/nsx_v/test_plugin.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/tests/unit/nsx_v/test_plugin.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/tests/unit/nsx_v/test_plugin.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/tests/unit/nsx_v/test_plugin.py 2019-03-14 02:01:03.000000000 +0000 @@ -615,6 +615,33 @@ # Assert neutron name is not truncated self.assertEqual(net['network']['name'], name) + def test_create_update_network_allow_multiple_addresses_spoofguard(self): + # allow_multiple_addresses flag is True, first step is to check that + # when port-security-allowed is false - spoofguard policy is not + # created. + # next step is to update port-security-allowed to true - spoofguard + # policy is now created for this network. + q_context = context.Context('', 'tenant_1') + providernet_args = {psec.PORTSECURITY: False} + cfg.CONF.set_default('allow_multiple_ip_addresses', True, 'nsxv') + res = self._create_network(fmt='json', name='net-1', + admin_state_up=True, + providernet_args=providernet_args, + arg_list=(psec.PORTSECURITY,)) + network1 = self.deserialize(self.fmt, res) + net1_id = network1['network']['id'] + # not creating spoofguard policy + self.assertIsNone(nsxv_db.get_spoofguard_policy_id(q_context.session, + net1_id)) + args = {'network': {psec.PORTSECURITY: True}} + req = self.new_update_request('networks', args, + network1['network']['id'], fmt='json') + res = self.deserialize('json', req.get_response(self.api)) + net1_id = res['network']['id'] + # creating spoofguard policy + self.assertIsNotNone(nsxv_db.get_spoofguard_policy_id( + q_context.session, net1_id)) + def test_update_network_with_admin_false(self): data = {'network': {'admin_state_up': False}} with self.network() as net: @@ -1769,6 +1796,93 @@ self.assertEqual("PortSecurityAndIPRequiredForSecurityGroups", res['NeutronError']['type']) + def test_port_add_to_spoofguard_allow_multiple_addresses(self): + # allow_multiple_addresses flag is True, first step is to check that + # when port-security-allowed is false - spoofguard policy is not + # created. + # next step is to update port-security-allowed to true - spoofguard + # policy is now created for this network. + providernet_args = {psec.PORTSECURITY: False} + cfg.CONF.set_default('allow_multiple_ip_addresses', True, 'nsxv') + res = self._create_network(fmt='json', name='net-1', + admin_state_up=True, + providernet_args=providernet_args, + arg_list=(psec.PORTSECURITY,)) + network1 = self.deserialize(self.fmt, res) + net1_id = network1['network']['id'] + with self.subnet(network=network1, cidr='10.0.0.0/24'): + # create a compute port with port security + address_pairs = [{'ip_address': '192.168.1.1'}] + device_id = _uuid() + vnic_index = 3 + compute_port_create = self._create_port( + 'json', net1_id, + arg_list=( + 'port_security_enabled', + 'device_id', + 'device_owner', + 'allowed_address_pairs',), + port_security_enabled=True, + device_id=device_id, + device_owner='compute:None', + allowed_address_pairs=address_pairs) + port = self.deserialize('json', compute_port_create) + port = self._update_port_index( + port['port']['id'], device_id, vnic_index) + # Verify the port is added to the spoofguard policy + with mock.patch.object( + self.plugin, '_update_vnic_assigned_addresses') as \ + update_approved_port: + args = {'network': {psec.PORTSECURITY: True}} + req = self.new_update_request('networks', args, net1_id, + fmt='json') + req.get_response(self.api) + # The expected vnic-id format by NsxV + update_approved_port.assert_called_once_with( + mock.ANY, mock.ANY, '%s.%03d' % (device_id, vnic_index)) + + def test_port_add_to_spoofguard_allow_multiple_addresses_fail(self): + # allow_multiple_addresses flag is True, first step is to check that + # when port-security-allowed is false - spoofguard policy is not + # created. + # next step is to update port-security-allowed to true but the port + # has CIDR defined as a address pair - action is aborted. + # policy is now created for this network. + providernet_args = {psec.PORTSECURITY: False} + cfg.CONF.set_default('allow_multiple_ip_addresses', True, 'nsxv') + res = self._create_network(fmt='json', name='net-1', + admin_state_up=True, + providernet_args=providernet_args, + arg_list=(psec.PORTSECURITY,)) + network1 = self.deserialize(self.fmt, res) + net1_id = network1['network']['id'] + with self.subnet(network=network1, cidr='10.0.0.0/24'): + # create a compute port with port security + address_pairs = [{'ip_address': '192.168.1.0/24'}] + device_id = _uuid() + vnic_index = 3 + compute_port_create = self._create_port( + 'json', net1_id, + arg_list=( + 'port_security_enabled', + 'device_id', + 'device_owner', + 'allowed_address_pairs',), + port_security_enabled=True, + device_id=device_id, + device_owner='compute:None', + allowed_address_pairs=address_pairs) + port = self.deserialize('json', compute_port_create) + port = self._update_port_index( + port['port']['id'], device_id, vnic_index) + # Action is failed due to CIDR defined in the port. + args = {'network': {psec.PORTSECURITY: True}} + plugin = directory.get_plugin() + self.assertRaises(n_exc.BadRequest, + plugin.update_network, + context.get_admin_context(), + net1_id, args) + class TestSubnetsV2(NsxVPluginV2TestCase, test_plugin.TestSubnetsV2): diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/tests/unit/nsx_v/vshield/fake_vcns.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/tests/unit/nsx_v/vshield/fake_vcns.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/tests/unit/nsx_v/vshield/fake_vcns.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/tests/unit/nsx_v/vshield/fake_vcns.py 2019-03-14 02:01:03.000000000 +0000 @@ -1141,6 +1141,9 @@ raise exceptions.VcnsGeneralException( _("Spoofguard policy not found")) + def get_spoofguard_policy_data(self, policy_id, list_type='INACTIVE'): + return None, {'spoofguardList': []} + def get_spoofguard_policies(self): return None, {'policies': self._spoofguard_policies} diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/tests/unit/nsx_v3/test_api_replay.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/tests/unit/nsx_v3/test_api_replay.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/tests/unit/nsx_v3/test_api_replay.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/tests/unit/nsx_v3/test_api_replay.py 2019-03-14 02:01:03.000000000 +0000 @@ -13,6 +13,7 @@ # 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_v3 import test_plugin from neutron_lib.api import attributes @@ -34,7 +35,7 @@ # remove the extension from the plugin directory.get_plugin().supported_extension_aliases.remove( - 'api-replay') + api_replay.ALIAS) # Revert the attributes map back to normal for attr_name in ('ports', 'networks', 'security_groups', diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/tests/unit/nsx_v3/test_fwaas_v1_driver.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/tests/unit/nsx_v3/test_fwaas_v1_driver.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/tests/unit/nsx_v3/test_fwaas_v1_driver.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/tests/unit/nsx_v3/test_fwaas_v1_driver.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,370 +0,0 @@ -# Copyright 2017 VMware, Inc. -# All Rights Reserved -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import copy - -import mock -from neutron_lib.plugins import directory - -from vmware_nsx.services.fwaas.nsx_v3 import edge_fwaas_driver_base -from vmware_nsx.services.fwaas.nsx_v3 import edge_fwaas_driver_v1 as \ - edge_fwaas_driver -from vmware_nsx.services.fwaas.nsx_v3 import fwaas_callbacks_v1 -from vmware_nsx.tests.unit.nsx_v3 import test_plugin as test_v3_plugin -from vmware_nsxlib.v3 import nsx_constants as consts - -FAKE_FW_ID = 'fake_fw_uuid' -FAKE_ROUTER_ID = 'fake_rtr_uuid' -MOCK_NSX_ID = 'nsx_router_id' -FAKE_PORT_ID = 'fake_port_uuid' -FAKE_NET_ID = 'fake_net_uuid' -FAKE_NSX_PORT_ID = 'fake_nsx_port_uuid' -MOCK_DEFAULT_RULE_ID = 'nsx_default_rule_id' -MOCK_SECTION_ID = 'sec_id' -DEFAULT_RULE = {'is_default': True, - 'display_name': edge_fwaas_driver_base.DEFAULT_RULE_NAME, - 'id': MOCK_DEFAULT_RULE_ID, - 'action': consts.FW_ACTION_DROP} - - -class Nsxv3FwaasTestCase(test_v3_plugin.NsxV3PluginTestCaseMixin): - def setUp(self): - super(Nsxv3FwaasTestCase, self).setUp() - self.firewall = edge_fwaas_driver.EdgeFwaasV3DriverV1() - - # Start some nsxlib/DB mocks - mock.patch( - "vmware_nsxlib.v3.core_resources.NsxLibLogicalRouter." - "get_firewall_section_id", - return_value=MOCK_SECTION_ID).start() - - mock.patch( - "vmware_nsxlib.v3.security.NsxLibFirewallSection." - "get_default_rule", - return_value={'id': MOCK_DEFAULT_RULE_ID}).start() - - mock.patch( - "vmware_nsx.db.db.get_nsx_router_id", - return_value=MOCK_NSX_ID).start() - - self.plugin = directory.get_plugin() - self.plugin.fwaas_callbacks = fwaas_callbacks_v1.\ - Nsxv3FwaasCallbacksV1() - self.plugin.fwaas_callbacks.fwaas_enabled = True - self.plugin.fwaas_callbacks.fwaas_driver = self.firewall - self.plugin.fwaas_callbacks.internal_driver = self.firewall - self.plugin.init_is_complete = True - - def _default_rule(self, drop=True): - rule = DEFAULT_RULE - if drop: - rule['action'] = consts.FW_ACTION_DROP - else: - rule['action'] = consts.FW_ACTION_ALLOW - return rule - - def _fake_rules_v4(self, cidr='10.24.4.0/24'): - rule1 = {'enabled': True, - 'action': 'allow', - 'ip_version': 4, - 'protocol': 'tcp', - 'destination_port': '80', - 'source_ip_address': cidr, - 'id': 'fake-fw-rule1', - 'description': 'first rule'} - rule2 = {'enabled': True, - 'action': 'reject', - 'ip_version': 4, - 'protocol': 'tcp', - 'destination_port': '22:24', - 'source_port': '1:65535', - 'id': 'fake-fw-rule2'} - rule3 = {'enabled': True, - 'action': 'deny', - 'ip_version': 4, - 'protocol': 'icmp', - 'id': 'fake-fw-rule3'} - rule4 = {'enabled': True, - 'action': 'deny', - 'ip_version': 4, - 'source_ip_address': cidr, - 'id': 'fake-fw-rule4'} - return [rule1, rule2, rule3, rule4] - - def _translated_cidr(self, cidr): - if cidr is None: - return [] - else: - return [{'target_id': cidr, - 'target_type': 'IPv4Address'}] - - def _fake_translated_rules(self, logged=False, cidr='10.24.4.0/24'): - # The expected translation of the rules in _fake_rules_v4 - service1 = {'l4_protocol': 'TCP', - 'resource_type': 'L4PortSetNSService', - 'destination_ports': ['80'], - 'source_ports': []} - rule1 = {'action': 'ALLOW', - 'services': [{'service': service1}], - 'sources': self._translated_cidr(cidr), - 'display_name': 'Fwaas-fake-fw-rule1', - 'notes': 'first rule'} - service2 = {'l4_protocol': 'TCP', - 'resource_type': 'L4PortSetNSService', - 'destination_ports': ['22-24'], - 'source_ports': ['1-65535']} - rule2 = {'action': 'DROP', # Reject is replaced with deny - 'services': [{'service': service2}], - 'display_name': 'Fwaas-fake-fw-rule2'} - service3_1 = {'resource_type': 'ICMPTypeNSService', - 'protocol': 'ICMPv4'} - service3_2 = {'resource_type': 'ICMPTypeNSService', - 'protocol': 'ICMPv6'} - rule3 = {'action': 'DROP', - # icmp is translated to icmp v4 & v6 - 'services': [{'service': service3_1}, - {'service': service3_2}], - 'display_name': 'Fwaas-fake-fw-rule3'} - rule4 = {'action': 'DROP', - 'sources': self._translated_cidr(cidr), - 'display_name': 'Fwaas-fake-fw-rule4'} - - if logged: - for rule in (rule1, rule2, rule3, rule4): - rule['logged'] = logged - return [rule1, rule2, rule3, rule4] - - def _fake_firewall_no_rule(self): - rule_list = [] - fw_inst = {'id': FAKE_FW_ID, - 'admin_state_up': True, - 'tenant_id': 'tenant-uuid', - 'firewall_rule_list': rule_list} - return fw_inst - - def _fake_firewall(self, rule_list): - _rule_list = copy.deepcopy(rule_list) - for rule in _rule_list: - rule['position'] = str(_rule_list.index(rule)) - fw_inst = {'id': FAKE_FW_ID, - 'admin_state_up': True, - 'tenant_id': 'tenant-uuid', - 'firewall_rule_list': _rule_list} - return fw_inst - - def _fake_firewall_with_admin_down(self, rule_list): - fw_inst = {'id': FAKE_FW_ID, - 'admin_state_up': False, - 'tenant_id': 'tenant-uuid', - 'firewall_rule_list': rule_list} - return fw_inst - - def _fake_apply_list(self, router_count=1): - apply_list = [] - while router_count > 0: - router_inst = {'id': FAKE_ROUTER_ID} - router_info_inst = mock.Mock() - router_info_inst.router = router_inst - apply_list.append(router_info_inst) - router_count -= 1 - return apply_list - - def _setup_firewall_with_rules(self, func, router_count=1): - apply_list = self._fake_apply_list(router_count=router_count) - rule_list = self._fake_rules_v4() - firewall = self._fake_firewall(rule_list) - with mock.patch("vmware_nsxlib.v3.security.NsxLibFirewallSection." - "update") as update_fw, \ - mock.patch.object(self.plugin, '_get_router_interfaces', - return_value=[]), \ - mock.patch.object(self.plugin, 'get_ports', - return_value=[]), \ - mock.patch.object(self.plugin, 'get_router', - return_value=apply_list[0]), \ - mock.patch.object(self.plugin.fwaas_callbacks, - '_get_router_firewall_id', - return_value=firewall['id']), \ - mock.patch.object(self.plugin.fwaas_callbacks, - '_get_fw_from_plugin', - return_value=firewall): - func('nsx', apply_list, firewall) - self.assertEqual(router_count, update_fw.call_count) - update_fw.assert_called_with( - MOCK_SECTION_ID, - rules=self._fake_translated_rules() + [self._default_rule()]) - - def test_create_firewall_no_rules(self): - apply_list = self._fake_apply_list() - firewall = self._fake_firewall_no_rule() - initial_tags = [{'scope': 'xxx', 'tag': 'yyy'}] - with mock.patch("vmware_nsxlib.v3.security.NsxLibFirewallSection." - "update") as update_fw,\ - mock.patch.object(self.plugin, '_get_router_interfaces', - return_value=[]), \ - mock.patch.object(self.plugin, 'get_ports', - return_value=[]), \ - mock.patch.object(self.plugin, 'get_router', - return_value=apply_list[0]), \ - mock.patch.object(self.plugin.fwaas_callbacks, - '_get_router_firewall_id', - return_value=firewall['id']), \ - mock.patch.object(self.plugin.fwaas_callbacks, - '_get_fw_from_plugin', - return_value=firewall), \ - mock.patch("vmware_nsxlib.v3.core_resources.NsxLibLogicalRouter." - "update") as update_rtr,\ - mock.patch("vmware_nsxlib.v3.core_resources.NsxLibLogicalRouter." - "get", return_value={'tags': initial_tags}) as get_rtr: - self.firewall.create_firewall('nsx', apply_list, firewall) - update_fw.assert_called_once_with( - MOCK_SECTION_ID, - rules=[self._default_rule()]) - get_rtr.assert_called_once_with(MOCK_NSX_ID) - expected_tags = initial_tags - expected_tags.append({'scope': edge_fwaas_driver.NSX_FW_TAG, - 'tag': firewall['id']}) - update_rtr.assert_called_once_with(MOCK_NSX_ID, tags=expected_tags) - - def test_create_firewall_with_rules(self): - self._setup_firewall_with_rules(self.firewall.create_firewall) - - def test_create_firewall_with_rules_two_routers(self): - self._setup_firewall_with_rules(self.firewall.create_firewall, - router_count=2) - - def test_update_firewall_with_rules(self): - self._setup_firewall_with_rules(self.firewall.update_firewall) - - def test_create_firewall_with_illegal_cidr(self): - apply_list = self._fake_apply_list() - rule_list = self._fake_rules_v4(cidr='0.0.0.0/24') - firewall = self._fake_firewall(rule_list) - with mock.patch("vmware_nsxlib.v3.security.NsxLibFirewallSection." - "update") as update_fw, \ - mock.patch.object(self.plugin, '_get_router_interfaces', - return_value=[]), \ - mock.patch.object(self.plugin, 'get_ports', - return_value=[]), \ - mock.patch.object(self.plugin, 'get_router', - return_value=apply_list[0]), \ - mock.patch.object(self.plugin.fwaas_callbacks, - '_get_router_firewall_id', - return_value=firewall['id']), \ - mock.patch.object(self.plugin.fwaas_callbacks, - '_get_fw_from_plugin', - return_value=firewall): - self.firewall.create_firewall('nsx', apply_list, firewall) - self.assertEqual(1, update_fw.call_count) - update_fw.assert_called_with( - MOCK_SECTION_ID, - rules=(self._fake_translated_rules(cidr=None) + - [self._default_rule()])) - - def test_delete_firewall(self): - apply_list = self._fake_apply_list() - firewall = self._fake_firewall_no_rule() - initial_tags = [{'scope': 'xxx', 'tag': 'yyy'}, - {'scope': edge_fwaas_driver.NSX_FW_TAG, - 'tag': firewall['id']}] - with mock.patch("vmware_nsxlib.v3.security.NsxLibFirewallSection." - "update") as update_fw,\ - mock.patch.object(self.plugin, '_get_router_interfaces', - return_value=[]), \ - mock.patch.object(self.plugin, 'get_router', - return_value=apply_list[0]), \ - mock.patch.object(self.plugin.fwaas_callbacks, - '_get_router_firewall_id', - return_value=None), \ - mock.patch("vmware_nsxlib.v3.core_resources.NsxLibLogicalRouter." - "update") as update_rtr,\ - mock.patch("vmware_nsxlib.v3.core_resources.NsxLibLogicalRouter." - "get", return_value={'tags': initial_tags}) as get_rtr: - self.firewall.delete_firewall('nsx', apply_list, firewall) - update_fw.assert_called_once_with( - MOCK_SECTION_ID, - rules=[self._default_rule(drop=False)]) - get_rtr.assert_called_once_with(MOCK_NSX_ID) - expected_tags = initial_tags - expected_tags.pop() - expected_tags.append({'scope': edge_fwaas_driver.NSX_FW_TAG, - 'tag': firewall['id']}) - update_rtr.assert_called_once_with(MOCK_NSX_ID, tags=expected_tags) - - def test_create_firewall_with_admin_down(self): - apply_list = self._fake_apply_list() - rule_list = self._fake_rules_v4() - firewall = self._fake_firewall_with_admin_down(rule_list) - with mock.patch("vmware_nsxlib.v3.security.NsxLibFirewallSection." - "update") as update_fw, \ - mock.patch.object(self.plugin, '_get_router_interfaces', - return_value=[]), \ - mock.patch.object(self.plugin, 'get_ports', - return_value=[]), \ - mock.patch.object(self.plugin, 'get_router', - return_value=apply_list[0]), \ - mock.patch.object(self.plugin.fwaas_callbacks, - '_get_router_firewall_id', - return_value=firewall['id']), \ - mock.patch.object(self.plugin.fwaas_callbacks, - '_get_fw_from_plugin', - return_value=firewall): - self.firewall.create_firewall('nsx', apply_list, firewall) - update_fw.assert_called_once_with( - MOCK_SECTION_ID, - rules=[self._default_rule()]) - - def test_create_firewall_with_dhcp_relay(self): - apply_list = self._fake_apply_list() - firewall = self._fake_firewall_no_rule() - relay_server = '1.1.1.1' - port = {'id': FAKE_PORT_ID, 'network_id': FAKE_NET_ID} - with mock.patch("vmware_nsxlib.v3.security.NsxLibFirewallSection." - "update") as update_fw,\ - mock.patch.object(self.plugin, '_get_router_interfaces', - return_value=[port]), \ - mock.patch.object(self.plugin, 'get_ports', - return_value=[port]), \ - mock.patch.object(self.plugin, 'get_router', - return_value=apply_list[0]), \ - mock.patch.object(self.plugin, '_get_port_relay_servers', - return_value=[relay_server]),\ - mock.patch.object(self.plugin.fwaas_callbacks, - '_get_router_firewall_id', - return_value=firewall['id']), \ - mock.patch.object(self.plugin.fwaas_callbacks, - '_get_fw_from_plugin', - return_value=firewall): - self.firewall.create_firewall('nsx', apply_list, firewall) - # expecting 2 allow rules for the relay servers + default rule - expected_rules = expected_rules = [ - {'display_name': "DHCP Relay ingress traffic", - 'action': consts.FW_ACTION_ALLOW, - 'destinations': None, - 'sources': [{'target_id': relay_server, - 'target_type': 'IPv4Address'}], - 'services': self.plugin._get_port_relay_services(), - 'direction': 'IN'}, - {'display_name': "DHCP Relay egress traffic", - 'action': consts.FW_ACTION_ALLOW, - 'sources': None, - 'destinations': [{'target_id': relay_server, - 'target_type': 'IPv4Address'}], - 'services': self.plugin._get_port_relay_services(), - 'direction': 'OUT'}, - self._default_rule() - ] - update_fw.assert_called_once_with( - MOCK_SECTION_ID, - rules=expected_rules) diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/tests/unit/nsx_v3/test_fwaas_v2_driver.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/tests/unit/nsx_v3/test_fwaas_v2_driver.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/tests/unit/nsx_v3/test_fwaas_v2_driver.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/tests/unit/nsx_v3/test_fwaas_v2_driver.py 2019-03-14 02:01:03.000000000 +0000 @@ -17,7 +17,6 @@ import mock -from neutron_lib.exceptions import firewall_v2 as exceptions from neutron_lib.plugins import directory from vmware_nsx.services.fwaas.nsx_v3 import edge_fwaas_driver_base @@ -62,7 +61,7 @@ self.plugin = directory.get_plugin() self.plugin.fwaas_callbacks = fwaas_callbacks_v2.\ - Nsxv3FwaasCallbacksV2() + Nsxv3FwaasCallbacksV2(False) self.plugin.fwaas_callbacks.fwaas_enabled = True self.plugin.fwaas_callbacks.fwaas_driver = self.firewall self.plugin.fwaas_callbacks.internal_driver = self.firewall @@ -73,7 +72,8 @@ rule['action'] = consts.FW_ACTION_ALLOW return rule - def _fake_rules_v4(self, is_ingress=True, cidr='10.24.4.0/24'): + def _fake_rules_v4(self, is_ingress=True, cidr='10.24.4.0/24', + is_conflict=False): rule1 = {'enabled': True, 'action': 'allow', 'ip_version': 4, @@ -98,11 +98,15 @@ 'ip_version': 4, 'id': 'fake-fw-rule4'} if is_ingress: - # source ips are allowed - rule1['source_ip_address'] = cidr + if not is_conflict: + rule1['source_ip_address'] = cidr + else: + rule1['destination_ip_address'] = cidr else: - # dest ips are allowed for egress rules - rule1['destination_ip_address'] = cidr + if not is_conflict: + rule1['destination_ip_address'] = cidr + else: + rule1['source_ip_address'] = cidr return [rule1, rule2, rule3, rule4] @@ -114,7 +118,8 @@ 'target_type': 'IPv4Address'}] def _fake_translated_rules(self, nsx_port_id, cidr='10.24.4.0/24', - is_ingress=True, logged=False): + is_ingress=True, is_conflict=False, + logged=False): # The expected translation of the rules in _fake_rules_v4 service1 = {'l4_protocol': 'TCP', 'resource_type': 'L4PortSetNSService', @@ -125,9 +130,13 @@ 'sources': self._translated_cidr(cidr), 'display_name': 'Fwaas-fake-fw-rule1', 'notes': 'first rule'} - if not is_ingress: + if ((is_ingress and is_conflict) or + (not is_ingress and not is_conflict)): + # Swap ips rule1['destinations'] = rule1['sources'] del rule1['sources'] + if 'sources' in rule1 and not rule1['sources']: + del rule1['sources'] service2 = {'l4_protocol': 'TCP', 'resource_type': 'L4PortSetNSService', 'destination_ports': ['22-24'], @@ -157,7 +166,8 @@ new_val = [{'target_id': nsx_port_id, 'target_type': 'LogicalSwitch'}] for rule in (rule1, rule2, rule3, rule4): - rule[field] = new_val + if not rule.get(field): + rule[field] = new_val rule['direction'] = direction if logged: for rule in (rule1, rule2, rule3, rule4): @@ -194,7 +204,7 @@ rule_list, is_ingress=is_ingress, admin_state_up=False) def _fake_apply_list(self): - router_inst = {'id': FAKE_ROUTER_ID} + router_inst = {'id': FAKE_ROUTER_ID, 'external_gateway_info': 'dummy'} router_info_inst = mock.Mock() router_info_inst.router = router_inst router_info_inst.router_id = FAKE_ROUTER_ID @@ -237,9 +247,11 @@ MOCK_SECTION_ID, rules=expected_rules) - def _setup_firewall_with_rules(self, func, is_ingress=True): + def _setup_firewall_with_rules(self, func, is_ingress=True, + is_conflict=False): apply_list = self._fake_apply_list() - rule_list = self._fake_rules_v4(is_ingress=is_ingress) + rule_list = self._fake_rules_v4(is_ingress=is_ingress, + is_conflict=is_conflict) firewall = self._fake_firewall_group(rule_list, is_ingress=is_ingress) port = {'id': FAKE_PORT_ID, 'network_id': FAKE_NET_ID} with mock.patch.object(self.plugin, '_get_router_interfaces', @@ -256,7 +268,8 @@ "update") as update_fw: func('nsx', apply_list, firewall) expected_rules = self._fake_translated_rules( - FAKE_NSX_LS_ID, is_ingress=is_ingress) + [ + FAKE_NSX_LS_ID, is_ingress=is_ingress, + is_conflict=is_conflict) + [ {'display_name': "Block port ingress", 'action': consts.FW_ACTION_DROP, 'destinations': [{'target_type': 'LogicalSwitch', @@ -287,14 +300,13 @@ self._setup_firewall_with_rules(self.firewall.update_firewall_group, is_ingress=False) - def test_create_firewall_with_illegal_rules(self): - """Use ingress rules as the egress list and verify failure""" - apply_list = self._fake_apply_list() - rule_list = self._fake_rules_v4(is_ingress=True) - firewall = self._fake_firewall_group(rule_list, is_ingress=False) - self.assertRaises(exceptions.FirewallInternalDriverError, - self.firewall.create_firewall_group, 'nsx', - apply_list, firewall) + def test_create_firewall_with_egress_conflicting_rules(self): + self._setup_firewall_with_rules(self.firewall.update_firewall_group, + is_ingress=False, is_conflict=True) + + def test_create_firewall_with_ingress_conflicting_rules(self): + self._setup_firewall_with_rules(self.firewall.update_firewall_group, + is_ingress=True, is_conflict=True) def test_create_firewall_with_illegal_cidr(self): apply_list = self._fake_apply_list() diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/tests/unit/nsx_v3/test_plugin.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/tests/unit/nsx_v3/test_plugin.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/tests/unit/nsx_v3/test_plugin.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/tests/unit/nsx_v3/test_plugin.py 2019-03-14 02:01:03.000000000 +0000 @@ -211,6 +211,9 @@ 'neutron_lib.rpc.Connection.consume_in_threads', return_value=[]).start() + mock.patch.object(nsx_plugin.NsxV3Plugin, + '_cleanup_duplicates').start() + def setUp(self, plugin=PLUGIN_NAME, ext_mgr=None, service_plugins=None, **kwargs): @@ -1116,6 +1119,11 @@ res = self.plugin.get_port(self.ctx, port['id']) self.assertEqual(policy_id, res['qos_policy_id']) + # now remove the qos from the port + data['port']['qos_policy_id'] = None + res = self.plugin.update_port(self.ctx, port['id'], data) + self.assertIsNone(res['qos_policy_id']) + def test_create_ext_port_with_qos_fail(self): with self._create_l3_ext_network() as network: with self.subnet(network=network, cidr='10.0.0.0/24'),\ @@ -2658,7 +2666,9 @@ # create a router with this gateway with self.router() as r, \ - self._mock_add_remove_service_router() as change_sr: + mock.patch("vmware_nsxlib.v3.router.RouterLib." + "has_service_router", return_value=False),\ + self._mock_add_remove_service_router() as change_sr: router_id = r['router']['id'] self._add_external_gateway_to_router( router_id, ext_subnet['network_id']) @@ -2679,7 +2689,9 @@ self._add_external_gateway_to_router( r['router']['id'], ext_subnet['network_id']) - with self._mock_add_remove_service_router() as change_sr: + with mock.patch("vmware_nsxlib.v3.router.RouterLib." + "has_service_router", return_value=True),\ + self._mock_add_remove_service_router() as change_sr: self._update_router_enable_snat( r['router']['id'], ext_subnet['network_id'], @@ -3020,7 +3032,9 @@ # create a router with this gateway with self.router() as r, \ - self._mock_add_remove_service_router() as change_sr: + mock.patch("vmware_nsxlib.v3.router.RouterLib." + "has_service_router", return_value=False),\ + self._mock_add_remove_service_router() as change_sr: router_id = r['router']['id'] self._add_external_gateway_to_router( router_id, ext_subnet['network_id']) diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/tests/unit/osc/v2/test_port.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/tests/unit/osc/v2/test_port.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/tests/unit/osc/v2/test_port.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/tests/unit/osc/v2/test_port.py 2019-03-14 02:01:03.000000000 +0000 @@ -20,12 +20,15 @@ from openstackclient.tests.unit.network.v2 import test_port from openstackclient.tests.unit import utils as tests_utils +from vmware_nsx.extensions import maclearning +from vmware_nsx.extensions import providersecuritygroup +from vmware_nsx.extensions import vnicindex from vmware_nsx.osc.v2 import port -supported_extensions = ('vnic-index', - 'provider-security-group', - 'mac-learning') +supported_extensions = (vnicindex.ALIAS, + providersecuritygroup.ALIAS, + maclearning.ALIAS) class TestCreatePort(test_port.TestCreatePort): diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/tests/unit/osc/v2/test_router.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/tests/unit/osc/v2/test_router.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/tests/unit/osc/v2/test_router.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/tests/unit/osc/v2/test_router.py 2019-03-14 02:01:03.000000000 +0000 @@ -24,7 +24,7 @@ from vmware_nsx.osc.v2 import router -supported_extensions = ('nsxv-router-size', 'nsxv-router-type') +supported_extensions = (routersize.ALIAS, routertype.ALIAS) class TestCreateRouter(test_router.TestCreateRouter): diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/tests/unit/osc/v2/test_security_group.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/tests/unit/osc/v2/test_security_group.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/tests/unit/osc/v2/test_security_group.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/tests/unit/osc/v2/test_security_group.py 2019-03-14 02:01:03.000000000 +0000 @@ -20,12 +20,16 @@ test_security_group_network as test_security_group) from openstackclient.tests.unit import utils as tests_utils + +from vmware_nsx.extensions import providersecuritygroup +from vmware_nsx.extensions import securitygrouplogging +from vmware_nsx.extensions import securitygrouppolicy from vmware_nsx.osc.v2 import security_group -supported_extensions = ('security-group-logging', - 'provider-security-group', - 'security-group-policy') +supported_extensions = (securitygrouplogging.ALIAS, + providersecuritygroup.ALIAS, + securitygrouppolicy.ALIAS) class TestCreateSecurityGroup( diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/tests/unit/osc/v2/test_subnet.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/tests/unit/osc/v2/test_subnet.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/tests/unit/osc/v2/test_subnet.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/tests/unit/osc/v2/test_subnet.py 2019-03-14 02:01:03.000000000 +0000 @@ -19,10 +19,12 @@ from openstackclient.tests.unit.network.v2 import test_subnet from openstackclient.tests.unit import utils as tests_utils +from vmware_nsx.extensions import dhcp_mtu +from vmware_nsx.extensions import dns_search_domain from vmware_nsx.osc.v2 import subnet -supported_extensions = ('dhcp-mtu', 'dns-search-domain') +supported_extensions = (dhcp_mtu.ALIAS, dns_search_domain.ALIAS) class TestCreateSubnet(test_subnet.TestCreateSubnet): diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/tests/unit/services/dynamic_routing/test_nsxv_bgp_driver.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/tests/unit/services/dynamic_routing/test_nsxv_bgp_driver.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/tests/unit/services/dynamic_routing/test_nsxv_bgp_driver.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/tests/unit/services/dynamic_routing/test_nsxv_bgp_driver.py 2019-03-14 02:01:03.000000000 +0000 @@ -120,6 +120,24 @@ yield self.bgp_plugin.get_bgp_speaker(self.context, bgp_speaker_id) + def test_get_external_networks_for_port_same_address_scope_v6(self): + self.skipTest("IPv6 not supported by this plugin.") + + def test_get_external_networks_for_port_different_address_scope_v6(self): + self.skipTest("IPv6 not supported by this plugin.") + + def test__get_dvr_fixed_ip_routes_by_bgp_speaker_same_scope(self): + self.skipTest("DVR specific.") + + def test_get_external_networks_for_port_different_address_scope_v4(self): + self.skipTest("DVR specific.") + + def test__get_dvr_fixed_ip_routes_by_bgp_speaker_different_scope(self): + self.skipTest("DVR specific.") + + def test__get_dvr_fixed_ip_routes_by_bgp_speaker_no_scope(self): + self.skipTest("DVR specific.") + def test_create_v6_bgp_speaker(self): fake_bgp_speaker = { "bgp_speaker": { diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/tests/unit/services/lbaas/test_nsxv3_driver.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/tests/unit/services/lbaas/test_nsxv3_driver.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/tests/unit/services/lbaas/test_nsxv3_driver.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/tests/unit/services/lbaas/test_nsxv3_driver.py 2019-03-14 02:01:03.000000000 +0000 @@ -248,7 +248,12 @@ def test_create(self): with mock.patch.object(lb_utils, 'validate_lb_subnet' - ) as mock_validate_lb_subnet: + ) as mock_validate_lb_subnet,\ + mock.patch.object(lb_utils, 'get_router_from_network'),\ + mock.patch.object(nsx_db, 'get_nsx_lbaas_loadbalancer_binding'),\ + mock.patch.object(nsx_db, 'get_nsx_router_id'),\ + mock.patch.object(self.service_client, 'get_router_lb_service'),\ + mock.patch.object(nsx_db, 'add_nsx_lbaas_loadbalancer_binding'): mock_validate_lb_subnet.return_value = True self.edge_driver.loadbalancer.create(self.context, self.lb) @@ -371,7 +376,6 @@ mock_add_listener_binding.assert_called_with( self.context.session, LB_ID, LISTENER_ID, APP_PROFILE_ID, LB_VS_ID) - mock_successful_completion = ( self.lbv2_driver.listener.successful_completion) mock_successful_completion.assert_called_with(self.context, @@ -889,66 +893,7 @@ def _tested_entity(self): return 'member' - def _test_create(self, lb_binding, pool_binding): - with mock.patch.object(lb_utils, 'validate_lb_member_subnet' - ) as mock_validate_lb_subnet, \ - mock.patch.object(self.lbv2_driver.plugin, 'get_pool_members' - ) as mock_get_pool_members, \ - mock.patch.object(lb_utils, 'get_network_from_subnet' - ) as mock_get_network, \ - mock.patch.object(lb_utils, 'get_router_from_network' - ) as mock_get_router, \ - mock.patch.object(nsx_db, 'get_nsx_lbaas_pool_binding' - ) as mock_get_pool_binding, \ - mock.patch.object(nsx_db, 'get_nsx_lbaas_loadbalancer_binding' - ) as mock_get_lb_binding, \ - mock.patch.object(nsx_db, 'get_nsx_router_id' - ) as mock_get_nsx_router_id, \ - mock.patch.object(self.service_client, 'get_router_lb_service' - ) as mock_get_lb_service, \ - mock.patch.object(nsx_db, 'add_nsx_lbaas_loadbalancer_binding' - ) as mock_add_loadbalancer_binding, \ - mock.patch.object(self.service_client, - 'add_virtual_server' - ) as mock_add_vs_to_service, \ - mock.patch.object(self.pool_client, 'get' - ) as mock_get_pool, \ - mock.patch.object(self.pool_client, 'update_pool_with_members' - ) as mock_update_pool_with_members: - mock_validate_lb_subnet.return_value = True - mock_get_pool_members.return_value = [self.member] - mock_get_network.return_value = LB_NETWORK - mock_get_router.return_value = LB_ROUTER_ID - mock_get_pool_binding.return_value = pool_binding - mock_get_lb_binding.return_value = lb_binding - mock_get_nsx_router_id.return_value = LB_ROUTER_ID - mock_get_lb_service.return_value = {'id': LB_SERVICE_ID} - mock_get_pool.return_value = LB_POOL - - self.edge_driver.member.create(self.context, self.member) - if not lb_binding: - mock_add_loadbalancer_binding.assert_called_with( - self.context.session, LB_ID, LB_SERVICE_ID, LB_ROUTER_ID, - LB_VIP) - else: - mock_add_loadbalancer_binding.assert_not_called() - mock_add_vs_to_service.assert_called_with(LB_SERVICE_ID, LB_VS_ID) - mock_update_pool_with_members.assert_called_with(LB_POOL_ID, - [LB_MEMBER]) - mock_successful_completion = ( - self.lbv2_driver.member.successful_completion) - mock_successful_completion.assert_called_with(self.context, - self.member, - delete=False) - def test_create(self): - self._test_create(None, POOL_BINDING) - - def test_create_existing_binding(self): - self._test_create(LB_BINDING, POOL_BINDING) - - def test_create_with_service(self): - ext_cidr = '1.1.1.0/24' with mock.patch.object(lb_utils, 'validate_lb_member_subnet' ) as mock_validate_lb_subnet, \ mock.patch.object(self.lbv2_driver.plugin, 'get_pool_members' @@ -965,95 +910,29 @@ ) as mock_get_nsx_router_id, \ mock.patch.object(self.service_client, 'get_router_lb_service' ) as mock_get_lb_service, \ - mock.patch.object(self.service_client, 'create' - ) as mock_create_lb_service, \ - mock.patch.object(nsx_db, 'add_nsx_lbaas_loadbalancer_binding' - ) as mock_add_loadbalancer_bidning, \ - mock.patch.object(self.service_client, - 'add_virtual_server' - ) as mock_add_vs_to_service, \ mock.patch.object(self.pool_client, 'get' ) as mock_get_pool, \ mock.patch.object(self.pool_client, 'update_pool_with_members' - ) as mock_update_pool_with_members,\ - mock.patch.object(self.core_plugin.nsxlib.logical_router, - 'update_advertisement_rules') as update_adv,\ - mock.patch.object(self.core_plugin, '_find_router_gw_subnets' - ) as mock_get_subnets,\ - mock.patch.object(self.core_plugin, 'get_router' - ) as mock_core_get_router: + ) as mock_update_pool_with_members: mock_validate_lb_subnet.return_value = True mock_get_pool_members.return_value = [self.member] mock_get_network.return_value = LB_NETWORK mock_get_router.return_value = LB_ROUTER_ID mock_get_pool_binding.return_value = POOL_BINDING - mock_get_lb_binding.return_value = None + mock_get_lb_binding.return_value = LB_BINDING mock_get_nsx_router_id.return_value = LB_ROUTER_ID - mock_get_lb_service.return_value = {} - mock_create_lb_service.return_value = {'id': LB_SERVICE_ID} + mock_get_lb_service.return_value = {'id': LB_SERVICE_ID} mock_get_pool.return_value = LB_POOL - mock_core_get_router.return_value = { - 'id': LB_ROUTER_ID, - 'name': 'router1', - 'external_gateway_info': 'dummy'} - mock_get_subnets.return_value = [{'cidr': ext_cidr}] self.edge_driver.member.create(self.context, self.member) - - mock_add_loadbalancer_bidning.assert_called_with( - self.context.session, LB_ID, LB_SERVICE_ID, LB_ROUTER_ID, - LB_VIP) - mock_add_vs_to_service.assert_called_with(LB_SERVICE_ID, LB_VS_ID) mock_update_pool_with_members.assert_called_with(LB_POOL_ID, [LB_MEMBER]) - update_adv.assert_called_with( - LB_ROUTER_ID, - [{'networks': [ext_cidr], - 'display_name': lb_utils.ADV_RULE_NAME, - 'rule_filter': {'match_route_types': ['T1_LB_VIP'], - 'prefix_operator': 'GE'}, - 'action': 'ALLOW'}], - name_prefix=lb_utils.ADV_RULE_NAME) mock_successful_completion = ( self.lbv2_driver.member.successful_completion) mock_successful_completion.assert_called_with(self.context, self.member, delete=False) - def test_create_lbs_no_router_gateway(self): - with mock.patch.object(lb_utils, 'validate_lb_member_subnet' - ) as mock_validate_lb_subnet, \ - mock.patch.object(self.lbv2_driver.plugin, 'get_pool_members' - ) as mock_get_pool_members, \ - mock.patch.object(lb_utils, 'get_network_from_subnet' - ) as mock_get_network, \ - mock.patch.object(lb_utils, 'get_router_from_network' - ) as mock_get_router_from_network, \ - mock.patch.object(nsx_db, 'get_nsx_lbaas_pool_binding' - ) as mock_get_pool_binding, \ - mock.patch.object(nsx_db, 'get_nsx_lbaas_loadbalancer_binding' - ) as mock_get_lb_binding, \ - mock.patch.object(nsx_db, 'get_nsx_router_id' - ) as mock_get_nsx_router_id, \ - mock.patch.object(self.service_client, 'get_router_lb_service' - ) as mock_get_lb_service, \ - mock.patch.object(self.core_plugin, 'get_router' - ) as mock_get_router: - mock_validate_lb_subnet.return_value = True - mock_get_pool_members.return_value = [self.member] - mock_get_network.return_value = LB_NETWORK - mock_get_router_from_network.return_value = LB_ROUTER_ID - mock_get_pool_binding.return_value = POOL_BINDING - mock_get_lb_binding.return_value = None - mock_get_nsx_router_id.return_value = LB_ROUTER_ID - mock_get_lb_service.return_value = None - mock_get_router.return_value = {'id': 'router1-xxx'} - - self.assertRaises(n_exc.BadRequest, - self.edge_driver.member.create, - self.context, - self.member) - def test_create_member_different_router(self): with mock.patch.object(self.lbv2_driver.plugin, 'get_pool_members' ) as mock_get_pool_members, \ diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/tests/unit/services/lbaas/test_octavia_listener.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/tests/unit/services/lbaas/test_octavia_listener.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/tests/unit/services/lbaas/test_octavia_listener.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/tests/unit/services/lbaas/test_octavia_listener.py 2019-03-14 02:01:03.000000000 +0000 @@ -16,6 +16,7 @@ import mock import testtools +from neutron_lib import exceptions from oslo_utils import uuidutils from vmware_nsx.services.lbaas.octavia import octavia_listener @@ -25,18 +26,36 @@ create_called = False update_called = False delete_called = False + delete_cascade_called = False + to_raise = False def create(self, ctx, lb_obj, completor_func, **args): self.create_called = True - completor_func(success=True) + if self.to_raise: + raise exceptions.InvalidInput(error_message='test') + else: + completor_func(success=True) def update(self, ctx, old_lb_obj, new_lb_obj, completor_func, **args): self.update_called = True - completor_func(success=True) + if self.to_raise: + raise exceptions.InvalidInput(error_message='test') + else: + completor_func(success=True) def delete(self, ctx, lb_obj, completor_func, **args): self.delete_called = True - completor_func(success=True) + if self.to_raise: + raise exceptions.InvalidInput(error_message='test') + else: + completor_func(success=True) + + def delete_cascade(self, ctx, lb_obj, completor_func, **args): + self.delete_cascade_called = True + if self.to_raise: + raise exceptions.InvalidInput(error_message='test') + else: + completor_func(success=True) class TestNsxOctaviaListener(testtools.TestCase): @@ -77,6 +96,19 @@ 'provisioning_status': 'ACTIVE', 'id': mock.ANY}]}) + def test_loadbalancer_create_failed(self): + self.dummyResource.create_called = False + self.dummyResource.to_raise = True + self.endpoint.loadbalancer_create(self.ctx, self.dummyObj) + self.assertTrue(self.dummyResource.create_called) + self.clientMock.cast.assert_called_once_with( + {}, 'update_loadbalancer_status', + status={'loadbalancers': [ + {'operating_status': 'ERROR', + 'provisioning_status': 'ERROR', + 'id': mock.ANY}]}) + self.dummyResource.to_raise = False + def test_loadbalancer_delete(self): self.dummyResource.delete_called = False self.endpoint.loadbalancer_delete(self.ctx, self.dummyObj) @@ -88,6 +120,24 @@ 'provisioning_status': 'DELETED', 'id': mock.ANY}]}) + def test_loadbalancer_delete_cascade(self): + self.dummyResource.delete_called = False + self.endpoint.loadbalancer_delete(self.ctx, self.dummyObj, + cascade=True) + self.assertTrue(self.dummyResource.delete_cascade_called) + self.clientMock.cast.assert_called_once_with( + {}, 'update_loadbalancer_status', + status={ + 'loadbalancers': [{'operating_status': 'ONLINE', + 'provisioning_status': 'DELETED', + 'id': mock.ANY}], + 'l7policies': [], + 'pools': [], + 'listeners': [], + 'l7rules': [], + 'members': [], + 'healthmonitors': []}) + def test_loadbalancer_update(self): self.dummyResource.update_called = False self.endpoint.loadbalancer_update(self.ctx, self.dummyObj, @@ -147,14 +197,33 @@ def test_pool_delete(self): self.dummyResource.delete_called = False - self.endpoint.pool_delete(self.ctx, self.dummyObj) + lb_id = uuidutils.generate_uuid() + listener_id = uuidutils.generate_uuid() + pool_id = uuidutils.generate_uuid() + pool_obj = { + 'id': pool_id, + 'pool_id': pool_id, + 'project_id': uuidutils.generate_uuid(), + 'listener_id': listener_id, + 'loadbalancer_id': lb_id, + 'listener': {'protocol': 'HTTP', + 'id': listener_id, + 'default_pool_id': pool_id, + 'loadbalancer': {'id': lb_id}}} + self.endpoint.pool_delete(self.ctx, pool_obj) self.assertTrue(self.dummyResource.delete_called) self.clientMock.cast.assert_called_once_with( {}, 'update_loadbalancer_status', - status={'pools': [ - {'operating_status': 'ONLINE', - 'provisioning_status': 'DELETED', - 'id': mock.ANY}]}) + status={'loadbalancers': [{'operating_status': 'ONLINE', + 'provisioning_status': 'ACTIVE', + 'id': lb_id}], + 'pools': [{'operating_status': 'ONLINE', + 'provisioning_status': 'DELETED', + 'id': pool_id}], + 'listeners': [{'operating_status': 'ONLINE', + 'provisioning_status': 'ACTIVE', + 'id': listener_id}], + }) def test_pool_update(self): self.dummyResource.update_called = False @@ -169,14 +238,40 @@ def test_member_create(self): self.dummyResource.create_called = False - self.endpoint.member_create(self.ctx, self.dummyObj) + lb_id = uuidutils.generate_uuid() + pool_id = uuidutils.generate_uuid() + listener_id = uuidutils.generate_uuid() + member_id = uuidutils.generate_uuid() + member_obj = { + 'id': member_id, + 'protocol_port': 80, + 'name': 'dummy', + 'pool_id': pool_id, + 'project_id': uuidutils.generate_uuid(), + 'pool': {'listener_id': listener_id, + 'id': pool_id, + 'loadbalancer_id': lb_id, + 'listener': {'protocol': 'HTTP', + 'id': listener_id, + 'default_pool_id': pool_id, + 'loadbalancer': {'id': lb_id}}}} + self.endpoint.member_create(self.ctx, member_obj) self.assertTrue(self.dummyResource.create_called) self.clientMock.cast.assert_called_once_with( {}, 'update_loadbalancer_status', - status={'members': [ - {'operating_status': 'ONLINE', - 'provisioning_status': 'ACTIVE', - 'id': mock.ANY}]}) + status={'members': [{'operating_status': 'ONLINE', + 'provisioning_status': 'ACTIVE', + 'id': member_id}], + 'loadbalancers': [{'operating_status': 'ONLINE', + 'provisioning_status': 'ACTIVE', + 'id': lb_id}], + 'pools': [{'operating_status': 'ONLINE', + 'provisioning_status': 'ACTIVE', + 'id': pool_id}], + 'listeners': [{'operating_status': 'ONLINE', + 'provisioning_status': 'ACTIVE', + 'id': listener_id}], + }) def test_member_delete(self): self.dummyResource.delete_called = False diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/tests/unit/services/qos/test_nsxp_notification.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/tests/unit/services/qos/test_nsxp_notification.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/tests/unit/services/qos/test_nsxp_notification.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/tests/unit/services/qos/test_nsxp_notification.py 2019-03-14 02:01:03.000000000 +0000 @@ -93,6 +93,12 @@ self.nsxlib = v3_utils.get_nsxlib_wrapper() + def _get_expected_tags(self): + policy_dict = {'id': self.policy.id, 'tenant_id': self.project_id} + return self.nsxlib.build_v3_tags_payload( + policy_dict, resource_type='os-neutron-qos-id', + project_name=self.ctxt.tenant_name) + @mock.patch.object(QoSPolicy, 'create_rbac_policy') def test_policy_create_profile(self, *mocks): # test the profile creation when a QoS policy is created @@ -103,9 +109,6 @@ return_value=self.policy),\ mock.patch.object(QoSPolicy, 'create'): self.qos_plugin.create_policy(self.ctxt, self.policy_data) - expected_tags = self.nsxlib.build_v3_api_version_project_tag( - project_name=self.ctxt.tenant_name, - project_id=self.project_id) exp_name = utils.get_name_and_uuid(self.policy.name, self.policy.id) @@ -115,7 +118,7 @@ description=self.policy_data["policy"]["description"], dscp=None, shaper_configurations=[], - tags=expected_tags) + tags=self._get_expected_tags()) @mock.patch.object(QoSPolicy, '_reload_rules') def test_bw_rule_create_profile(self, *mocks): @@ -139,9 +142,6 @@ rule_dict['max_kbps']) / 1024)) expected_burst = rule_dict['max_burst_kbps'] * 128 expected_peak = int(expected_bw * self.peak_bw_multiplier) - expected_tags = self.nsxlib.build_v3_api_version_project_tag( - project_name=self.ctxt.tenant_name, - project_id=self.project_id) exp_name = utils.get_name_and_uuid(self.policy.name, self.policy.id) # egress neutron rule -> ingress nsx args @@ -158,7 +158,7 @@ description=self.policy_data["policy"]["description"], dscp=None, shaper_configurations=[mock.ANY], - tags=expected_tags) + tags=self._get_expected_tags()) # Compare the shaper actual_shaper = create_profile.call_args[1][ 'shaper_configurations'][0] @@ -190,9 +190,6 @@ expected_peak = int(expected_bw * self.peak_bw_multiplier) exp_name = utils.get_name_and_uuid(self.policy.name, self.policy.id) - expected_tags = self.nsxlib.build_v3_api_version_project_tag( - project_name=self.ctxt.tenant_name, - project_id=self.project_id) # ingress neutron rule -> egress nsx args shaper_type = policy_defs.QoSRateLimiter.EGRESS_RATE_LIMITER_TYPE expected_shaper = policy_defs.QoSRateLimiter( @@ -207,7 +204,7 @@ description=self.policy_data["policy"]["description"], dscp=None, shaper_configurations=[mock.ANY], - tags=expected_tags) + tags=self._get_expected_tags()) # Compare the shaper actual_shaper = create_profile.call_args[1][ 'shaper_configurations'][0] @@ -287,9 +284,6 @@ exp_name = utils.get_name_and_uuid(self.policy.name, self.policy.id) - expected_tags = self.nsxlib.build_v3_api_version_project_tag( - project_name=self.ctxt.tenant_name, - project_id=self.project_id) expected_dscp = policy_defs.QoSDscp( mode=policy_defs.QoSDscp.QOS_DSCP_UNTRUSTED, priority=dscp_mark) @@ -299,7 +293,7 @@ description=self.policy_data["policy"]["description"], dscp=mock.ANY, shaper_configurations=[], - tags=expected_tags) + tags=self._get_expected_tags()) # Compare the dscp obj actual_dscp = create_profile.call_args[1]['dscp'] self.assertEqual(expected_dscp.get_obj_dict(), @@ -342,9 +336,6 @@ self.qos_plugin.delete_policy_bandwidth_limit_rule( self.ctxt, self.rule.id, self.policy.id) # validate the data on the profile - expected_tags = self.nsxlib.build_v3_api_version_project_tag( - project_name=self.ctxt.tenant_name, - project_id=self.project_id) exp_name = utils.get_name_and_uuid(self.policy.name, self.policy.id) @@ -354,7 +345,7 @@ description=self.policy_data["policy"]["description"], dscp=None, shaper_configurations=[], - tags=expected_tags) + tags=self._get_expected_tags()) @mock.patch('neutron.objects.db.api.get_object', return_value=None) def test_policy_delete_profile(self, *mocks): diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/tests/unit/services/vpnaas/test_nsxv3_vpnaas.py vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/tests/unit/services/vpnaas/test_nsxv3_vpnaas.py --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx/tests/unit/services/vpnaas/test_nsxv3_vpnaas.py 2019-01-31 14:40:06.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx/tests/unit/services/vpnaas/test_nsxv3_vpnaas.py 2019-03-14 02:01:03.000000000 +0000 @@ -604,10 +604,13 @@ providernet_args = {extnet_apidef.EXTERNAL: True} router_db = namedtuple("Router", FAKE_ROUTER.keys())( *FAKE_ROUTER.values()) + tier0_uuid = 'tier-0' with self.network(name='ext-net', providernet_args=providernet_args, arg_list=(extnet_apidef.EXTERNAL, )) as ext_net,\ self.subnet(ext_net),\ + mock.patch.object(self.plugin, '_get_tier0_uuid_by_router', + return_value=tier0_uuid),\ self.router(external_gateway_info={'network_id': ext_net['network']['id']}) as router,\ self.subnet() as sub: @@ -620,7 +623,6 @@ dummy_port = {'id': 'dummy_port', 'fixed_ips': [{'ip_address': '1.1.1.1'}]} tier0_rtr = {'high_availability_mode': 'ACTIVE_STANDBY'} - tier0_uuid = 'tier-0' with mock.patch.object(self.service_plugin, '_get_vpnservice', return_value=FAKE_VPNSERVICE),\ mock.patch.object(self.nsxlib_vpn.service, @@ -631,8 +633,6 @@ return_value=FAKE_ROUTER),\ mock.patch.object(self.plugin, 'get_ports', return_value=[dummy_port]),\ - mock.patch.object(self.plugin, '_get_tier0_uuid_by_router', - return_value=tier0_uuid),\ mock.patch.object(self.plugin.nsxlib.logical_router, 'get', return_value=tier0_rtr): self.driver.create_vpnservice(self.context, FAKE_VPNSERVICE) @@ -656,10 +656,13 @@ providernet_args = {extnet_apidef.EXTERNAL: True} router_db = namedtuple("Router", FAKE_ROUTER.keys())( *FAKE_ROUTER.values()) + tier0_rtr_id = _uuid() with self.network(name='ext-net', providernet_args=providernet_args, arg_list=(extnet_apidef.EXTERNAL, )) as ext_net,\ self.subnet(ext_net),\ + mock.patch.object(self.plugin, '_get_tier0_uuid_by_router', + return_value=tier0_rtr_id),\ self.router(external_gateway_info={'network_id': ext_net['network']['id']}) as router,\ self.subnet() as sub: @@ -671,7 +674,6 @@ # create the service dummy_port = {'id': 'dummy_port', 'fixed_ips': [{'ip_address': '1.1.1.1'}]} - tier0_rtr_id = _uuid() tier0_rtr = {'id': tier0_rtr_id, 'high_availability_mode': 'ACTIVE_STANDBY'} nsx_srv = {'logical_router_id': tier0_rtr_id, @@ -690,8 +692,6 @@ return_value=FAKE_ROUTER),\ mock.patch.object(self.plugin, 'get_ports', return_value=[dummy_port]),\ - mock.patch.object(self.plugin, '_get_tier0_uuid_by_router', - return_value=tier0_rtr_id),\ mock.patch.object(self.plugin.nsxlib.logical_router, 'get', return_value=tier0_rtr): self.driver.create_vpnservice(self.context, FAKE_VPNSERVICE) diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx.egg-info/entry_points.txt vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx.egg-info/entry_points.txt --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx.egg-info/entry_points.txt 2019-01-31 14:40:20.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx.egg-info/entry_points.txt 2019-03-14 02:01:09.000000000 +0000 @@ -4,12 +4,9 @@ nsxadmin = vmware_nsx.shell.nsxadmin:main [firewall_drivers] -vmware_nsxtvd_edge_v1 = vmware_nsx.services.fwaas.nsx_tv.edge_fwaas_driver_v1:EdgeFwaasTVDriverV1 vmware_nsxtvd_edge_v2 = vmware_nsx.services.fwaas.nsx_tv.edge_fwaas_driver_v2:EdgeFwaasTVDriverV2 -vmware_nsxv3_edge = vmware_nsx.services.fwaas.nsx_v3.edge_fwaas_driver_v1:EdgeFwaasV3DriverV1 -vmware_nsxv3_edge_v1 = vmware_nsx.services.fwaas.nsx_v3.edge_fwaas_driver_v1:EdgeFwaasV3DriverV1 vmware_nsxv3_edge_v2 = vmware_nsx.services.fwaas.nsx_v3.edge_fwaas_driver_v2:EdgeFwaasV3DriverV2 -vmware_nsxv_edge = vmware_nsx.services.fwaas.nsx_v.edge_fwaas_driver:EdgeFwaasDriver +vmware_nsxv_edge_v2 = vmware_nsx.services.fwaas.nsx_v.edge_fwaas_driver_v2:EdgeFwaasVDriverV2 [networking_sfc.flowclassifier.drivers] vmware-nsxv-sfc = vmware_nsx.services.flowclassifier.nsx_v.driver:NsxvFlowClassifierDriver @@ -39,7 +36,6 @@ [neutron.service_plugins] vmware_nsx_lbaasv2 = vmware_nsx.services.lbaas.nsx_plugin:LoadBalancerNSXPluginV2 vmware_nsx_vpnaas = vmware_nsx.services.vpnaas.nsx_plugin:NsxVPNPlugin -vmware_nsxtvd_fwaasv1 = vmware_nsx.services.fwaas.nsx_tv.plugin_v1:FwaasTVPluginV1 vmware_nsxtvd_fwaasv2 = vmware_nsx.services.fwaas.nsx_tv.plugin_v2:FwaasTVPluginV2 vmware_nsxtvd_l2gw = vmware_nsx.services.l2gateway.nsx_tvd.plugin:L2GatewayPlugin vmware_nsxtvd_lbaasv2 = vmware_nsx.services.lbaas.nsx.plugin:LoadBalancerTVPluginV2 diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx.egg-info/pbr.json vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx.egg-info/pbr.json --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx.egg-info/pbr.json 2019-01-31 14:40:20.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx.egg-info/pbr.json 2019-03-14 02:01:09.000000000 +0000 @@ -1 +1 @@ -{"git_version": "17b5ad567", "is_release": false} \ No newline at end of file +{"git_version": "8426b63a4", "is_release": false} \ No newline at end of file diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx.egg-info/PKG-INFO vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx.egg-info/PKG-INFO --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx.egg-info/PKG-INFO 2019-01-31 14:40:20.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx.egg-info/PKG-INFO 2019-03-14 02:01:09.000000000 +0000 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: vmware-nsx -Version: 13.0.1.dev386 +Version: 13.0.1.dev506 Summary: VMware NSX library for OpenStack projects Home-page: https://launchpad.net/vmware-nsx Author: OpenStack diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx.egg-info/requires.txt vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx.egg-info/requires.txt --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx.egg-info/requires.txt 2019-01-31 14:40:20.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx.egg-info/requires.txt 2019-03-14 02:01:09.000000000 +0000 @@ -10,14 +10,14 @@ neutron-dynamic-routing>=12.0.0 neutron-fwaas>=12.0.0 neutron-lbaas>=12.0.0 -neutron-lib>=1.22.0 +neutron-lib>=1.25.0 neutron-vpnaas>=12.0.0 neutron>=12.0.0 osc-lib>=1.10.0 oslo.concurrency>=3.26.0 oslo.config>=5.2.0 oslo.context>=2.19.2 -oslo.db>=4.27.0 +oslo.db>=4.37.0 oslo.i18n>=3.15.3 oslo.log>=3.36.0 oslo.serialization!=2.19.1,>=2.18.0 diff -Nru vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx.egg-info/SOURCES.txt vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx.egg-info/SOURCES.txt --- vmware-nsx-14.0.0~b1~git2019013109.17b5ad567/vmware_nsx.egg-info/SOURCES.txt 2019-01-31 14:40:20.000000000 +0000 +++ vmware-nsx-14.0.0~b1~git2019031322.8426b63a4/vmware_nsx.egg-info/SOURCES.txt 2019-03-14 02:01:10.000000000 +0000 @@ -75,6 +75,7 @@ releasenotes/notes/nsxv-edge-random-placement-9534371967edec8f.yaml releasenotes/notes/nsxv-exclusive-dhcp-7e5cde1cd88f8c5b.yaml releasenotes/notes/nsxv-fwaas-driver-4c457dee3fc3bae2.yaml +releasenotes/notes/nsxv-fwaas-v2-driver-0b78d5e2c4034b21.yaml releasenotes/notes/nsxv-ipam-support-6eb1ac4e0e025ddd.yaml releasenotes/notes/nsxv-lbaas-l7-704f748300d1a399.yaml releasenotes/notes/nsxv-policy-3f552191f94873cd.yaml @@ -89,6 +90,7 @@ releasenotes/notes/nsxv3-init-from-tags-bcd4f3245a78e9a6.yaml releasenotes/notes/nsxv3-ipam-support-137174152c65459d.yaml releasenotes/notes/nsxv3-lbaasv2-driver-57f37d6614eb1510.yaml +releasenotes/notes/nsxv3-lbaasv2-error-no-member-635ffc6308289aca.yaml releasenotes/notes/nsxv3-multi-managers-b645c4202a8476e9.yaml releasenotes/notes/nsxv3-native-dhcp-config-2b6bdd372a2d643f.yaml releasenotes/notes/nsxv3-native-dhcp-metadata-27af1de98302162f.yaml @@ -114,6 +116,9 @@ releasenotes/source/unreleased.rst releasenotes/source/_static/.placeholder releasenotes/source/_templates/.placeholder +rhosp13/instructions.rst +rhosp13/nsx-openstack-puppet.tar.gz +rhosp13/nsx-openstack-tripleo-heat-templates.tar.gz tools/__init__.py tools/clean.sh tools/coding-checks.sh @@ -232,6 +237,7 @@ vmware_nsx/db/migration/alembic_migrations/versions/queens/contract/a1be06050b41_update_nsx_binding_types.py vmware_nsx/db/migration/alembic_migrations/versions/queens/expand/0dbeda408e41_nsxv3_vpn_mapping.py vmware_nsx/db/migration/alembic_migrations/versions/queens/expand/9799427fc0e1_nsx_tv_map.py +vmware_nsx/db/migration/alembic_migrations/versions/stein/expand/99bfcb6003c6_lbaas_error_no_member.py vmware_nsx/db/migration/alembic_migrations/versions/stein/expand/fc6308289aca_lbaas_no_foreign_key.py vmware_nsx/db/migration/models/__init__.py vmware_nsx/db/migration/models/head.py @@ -371,23 +377,19 @@ vmware_nsx/services/flowclassifier/nsx_v/utils.py vmware_nsx/services/fwaas/__init__.py vmware_nsx/services/fwaas/common/__init__.py -vmware_nsx/services/fwaas/common/fwaas_callbacks_v1.py vmware_nsx/services/fwaas/common/fwaas_callbacks_v2.py +vmware_nsx/services/fwaas/common/fwaas_driver_base.py vmware_nsx/services/fwaas/common/fwaas_mocks.py vmware_nsx/services/fwaas/common/utils.py vmware_nsx/services/fwaas/nsx_tv/__init__.py -vmware_nsx/services/fwaas/nsx_tv/edge_fwaas_driver_v1.py vmware_nsx/services/fwaas/nsx_tv/edge_fwaas_driver_v2.py -vmware_nsx/services/fwaas/nsx_tv/plugin_v1.py vmware_nsx/services/fwaas/nsx_tv/plugin_v2.py vmware_nsx/services/fwaas/nsx_v/__init__.py -vmware_nsx/services/fwaas/nsx_v/edge_fwaas_driver.py -vmware_nsx/services/fwaas/nsx_v/fwaas_callbacks.py +vmware_nsx/services/fwaas/nsx_v/edge_fwaas_driver_v2.py +vmware_nsx/services/fwaas/nsx_v/fwaas_callbacks_v2.py vmware_nsx/services/fwaas/nsx_v3/__init__.py vmware_nsx/services/fwaas/nsx_v3/edge_fwaas_driver_base.py -vmware_nsx/services/fwaas/nsx_v3/edge_fwaas_driver_v1.py vmware_nsx/services/fwaas/nsx_v3/edge_fwaas_driver_v2.py -vmware_nsx/services/fwaas/nsx_v3/fwaas_callbacks_v1.py vmware_nsx/services/fwaas/nsx_v3/fwaas_callbacks_v2.py vmware_nsx/services/ipam/__init__.py vmware_nsx/services/ipam/common/__init__.py @@ -610,7 +612,7 @@ vmware_nsx/tests/unit/nsx_v/__init__.py vmware_nsx/tests/unit/nsx_v/test_availability_zones.py vmware_nsx/tests/unit/nsx_v/test_edge_loadbalancer_driver_v2.py -vmware_nsx/tests/unit/nsx_v/test_fwaas_driver.py +vmware_nsx/tests/unit/nsx_v/test_fwaas_v2_driver.py vmware_nsx/tests/unit/nsx_v/test_lbaas_common.py vmware_nsx/tests/unit/nsx_v/test_misc.py vmware_nsx/tests/unit/nsx_v/test_nsxv_loadbalancer.py @@ -628,7 +630,6 @@ vmware_nsx/tests/unit/nsx_v3/test_client_cert.py vmware_nsx/tests/unit/nsx_v3/test_constants.py vmware_nsx/tests/unit/nsx_v3/test_dhcp_metadata.py -vmware_nsx/tests/unit/nsx_v3/test_fwaas_v1_driver.py vmware_nsx/tests/unit/nsx_v3/test_fwaas_v2_driver.py vmware_nsx/tests/unit/nsx_v3/test_plugin.py vmware_nsx/tests/unit/nsx_v3/housekeeper/__init__.py