From 1be081d6e7a5d8347225b520eb8ff850f02f9507 Mon Sep 17 00:00:00 2001 From: asarfaty Date: Tue, 14 Jan 2020 10:43:57 +0200 Subject: [PATCH] NSX|P: Support segment & port admin state Before NSX 3.0 the passthrough api was used to update the admin state. With NSX 3.0 it can be updated using the policy api. In addition, adding a new admin utility to update this field when upgrading to NSX 3.0 Change-Id: I4020c07db0f595b1f46014a409a585188c88454e --- doc/source/admin_util.rst | 4 ++ vmware_nsx/common/utils.py | 5 ++ vmware_nsx/plugins/nsx_p/plugin.py | 62 +++++++++++++------ .../admin/plugins/nsxp/resources/networks.py | 39 ++++++++++++ vmware_nsx/shell/resources.py | 4 +- 5 files changed, 93 insertions(+), 21 deletions(-) diff --git a/doc/source/admin_util.rst b/doc/source/admin_util.rst index 047e0be9b2..a8463305b8 100644 --- a/doc/source/admin_util.rst +++ b/doc/source/admin_util.rst @@ -615,6 +615,10 @@ NSX Policy Plugin nsxadmin -r networks -o list +- Sync admin state of networks and ports (Once upgraded to NSX 3.0 which supports policy admin state):: + + nsxadmin -r networks -o nsx-update-state + - List all the neutron routers together with their NSX Policy objects and realization state:: nsxadmin -r routers -o list diff --git a/vmware_nsx/common/utils.py b/vmware_nsx/common/utils.py index fe69e7809d..22f7deb96f 100644 --- a/vmware_nsx/common/utils.py +++ b/vmware_nsx/common/utils.py @@ -100,6 +100,11 @@ def is_nsx_version_2_5_0(nsx_version): version.LooseVersion(v3_const.NSX_VERSION_2_5_0)) +def is_nsx_version_3_0_0(nsx_version): + return (version.LooseVersion(nsx_version) >= + version.LooseVersion(v3_const.NSX_VERSION_3_0_0)) + + def is_nsxv_version_6_2(nsx_version): return (version.LooseVersion(nsx_version) >= version.LooseVersion('6.2')) diff --git a/vmware_nsx/plugins/nsx_p/plugin.py b/vmware_nsx/plugins/nsx_p/plugin.py index a89e0ff98c..f51086181b 100644 --- a/vmware_nsx/plugins/nsx_p/plugin.py +++ b/vmware_nsx/plugins/nsx_p/plugin.py @@ -628,13 +628,20 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base): 'transport_zone_id': provider_data['physical_net'], 'tags': tags} + if (not admin_state and + self.nsxpolicy.feature_supported( + nsxlib_consts.FEATURE_NSX_POLICY_ADMIN_STATE)): + kwargs['admin_state'] = admin_state + if az.use_policy_md: kwargs['metadata_proxy_id'] = az._native_md_proxy_uuid self.nsxpolicy.segment.create_or_overwrite( net_name, **kwargs) - if not admin_state and cfg.CONF.nsx_p.allow_passthrough: + if (not admin_state and cfg.CONF.nsx_p.allow_passthrough and + not self.nsxpolicy.feature_supported( + nsxlib_consts.FEATURE_NSX_POLICY_ADMIN_STATE)): # This api uses the passthrough api self.nsxpolicy.segment.set_admin_state( net_data['id'], admin_state) @@ -878,14 +885,25 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base): # Update the backend segment if (not extern_net and not is_nsx_net and - ('name' in net_data or 'description' in net_data)): + ('name' in net_data or 'description' in net_data or + 'admin_state_up' in net_data)): net_name = utils.get_name_and_uuid( updated_net['name'] or 'network', network_id) + + kwargs = {'name': net_name, + 'description': updated_net.get('description', '')} + + if 'admin_state_up' in net_data: + if (self.nsxpolicy.feature_supported( + nsxlib_consts.FEATURE_NSX_POLICY_ADMIN_STATE)): + kwargs['admin_state'] = net_data['admin_state_up'] + elif cfg.CONF.nsx_p.allow_passthrough: + # Update admin state using the passthrough api + self.nsxpolicy.segment.set_admin_state( + network_id, net_data['admin_state_up']) + try: - self.nsxpolicy.segment.update( - network_id, - name=net_name, - description=updated_net.get('description', '')) + self.nsxpolicy.segment.update(network_id, **kwargs) except nsx_lib_exc.ManagerError: LOG.exception("Unable to update NSX backend, rolling " "back changes on neutron") @@ -897,13 +915,6 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base): super(NsxPolicyPlugin, self).update_network( context, network_id, {'network': original_net}) - if (not extern_net and not is_nsx_net and - 'admin_state_up' in net_data and - cfg.CONF.nsx_p.allow_passthrough): - # Update admin state using the passthrough api - self.nsxpolicy.segment.set_admin_state( - network_id, net_data['admin_state_up']) - return updated_net def _update_slaac_on_router(self, context, router_id, @@ -1077,15 +1088,23 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base): else: tags.extend(external_tags) + # Prepare the args for the segment port creation + kwargs = {'port_id': port_data['id'], + 'description': port_data.get('description', ''), + 'address_bindings': address_bindings, + 'tags': tags} + if vif_id: + kwargs['vif_id'] = vif_id + + if (self.nsxpolicy.feature_supported( + nsxlib_consts.FEATURE_NSX_POLICY_ADMIN_STATE) and + 'admin_state_up' in port_data): + kwargs['admin_state'] = port_data['admin_state_up'] + segment_id = self._get_network_nsx_segment_id( context, port_data['network_id']) self.nsxpolicy.segment_port.create_or_overwrite( - name, segment_id, - port_id=port_data['id'], - description=port_data.get('description', ''), - address_bindings=address_bindings, - vif_id=vif_id, - tags=tags) + name, segment_id, **kwargs) # add the security profiles to the port if is_psec_on: @@ -1124,7 +1143,10 @@ class NsxPolicyPlugin(nsx_plugin_common.NsxPluginV3Base): # Update port admin status using passthrough api, only if it changed # or new port with disabled admin state - if cfg.CONF.nsx_p.allow_passthrough and 'admin_state_up' in port_data: + if (not self.nsxpolicy.feature_supported( + nsxlib_consts.FEATURE_NSX_POLICY_ADMIN_STATE) and + cfg.CONF.nsx_p.allow_passthrough and + 'admin_state_up' in port_data): new_state = port_data['admin_state_up'] if ((is_create and new_state is False) or (is_update and diff --git a/vmware_nsx/shell/admin/plugins/nsxp/resources/networks.py b/vmware_nsx/shell/admin/plugins/nsxp/resources/networks.py index 18c80ef085..1cd942a5c0 100644 --- a/vmware_nsx/shell/admin/plugins/nsxp/resources/networks.py +++ b/vmware_nsx/shell/admin/plugins/nsxp/resources/networks.py @@ -12,11 +12,17 @@ # License for the specific language governing permissions and limitations # under the License. +from neutron_lib.callbacks import registry from neutron_lib import context +from oslo_log import log as logging from vmware_nsx.shell.admin.plugins.common import constants from vmware_nsx.shell.admin.plugins.common import utils as admin_utils from vmware_nsx.shell.admin.plugins.nsxp.resources import utils as p_utils +import vmware_nsx.shell.resources as shell +from vmware_nsxlib.v3 import nsx_constants + +LOG = logging.getLogger(__name__) @admin_utils.list_handler(constants.NETWORKS) @@ -46,3 +52,36 @@ def list_networks(resource, event, trigger, **kwargs): mappings, attrs=['Project', 'Name', 'ID', 'NSX status']) return bool(mappings) + + +@admin_utils.output_header +def update_admin_state(resource, event, trigger, **kwargs): + """Upon upgrade to NSX3 update policy segments & ports + So that the neutron admin state will match the policy one + """ + nsxpolicy = p_utils.get_connected_nsxpolicy() + if not nsxpolicy.feature_supported( + nsx_constants.FEATURE_NSX_POLICY_ADMIN_STATE): + LOG.error("This utility is not available for NSX version %s", + nsxpolicy.get_version()) + return + + ctx = context.get_admin_context() + with p_utils.NsxPolicyPluginWrapper() as plugin: + # Inconsistencies can happen only if the neutron state is Down + filters = {'admin_state_up': [False]} + nets = plugin.get_networks(ctx, filters=filters) + for net in nets: + seg_id = plugin._get_network_nsx_segment_id(ctx, net['id']) + nsxpolicy.segment.set_admin_state(seg_id, False) + + ports = plugin.get_ports(ctx, filters=filters) + for port in ports: + seg_id = plugin._get_network_nsx_segment_id( + ctx, port['network_id']) + nsxpolicy.segment_port.set_admin_state(seg_id, port['id'], False) + + +registry.subscribe(update_admin_state, + constants.NETWORKS, + shell.Operations.NSX_UPDATE_STATE.value) diff --git a/vmware_nsx/shell/resources.py b/vmware_nsx/shell/resources.py index 87ce66f243..7b0b5d02a6 100644 --- a/vmware_nsx/shell/resources.py +++ b/vmware_nsx/shell/resources.py @@ -52,6 +52,7 @@ class Operations(enum.Enum): NSX_UPDATE_SECRET = 'nsx-update-secret' NSX_UPDATE_RULES = 'nsx-update-rules' NSX_UPDATE_DHCP_RELAY = 'nsx-update-dhcp-relay' + NSX_UPDATE_STATE = 'nsx-update-state' NSX_ENABLE_STANDBY_RELOCATION = 'nsx-enable-standby-relocation' NSX_UPDATE_IP = 'nsx-update-ip' NSX_RECREATE = 'nsx-recreate' @@ -256,7 +257,8 @@ nsxp_resources = { constants.SECURITY_GROUPS: Resource(constants.SECURITY_GROUPS, [Operations.LIST.value]), constants.NETWORKS: Resource(constants.NETWORKS, - [Operations.LIST.value]), + [Operations.LIST.value, + Operations.NSX_UPDATE_STATE.value]), constants.ROUTERS: Resource(constants.ROUTERS, [Operations.LIST.value]), constants.CERTIFICATE: Resource(constants.CERTIFICATE,