diff --git a/doc/source/admin_util.rst b/doc/source/admin_util.rst index 4134ef93d7..87ef1bb13a 100644 --- a/doc/source/admin_util.rst +++ b/doc/source/admin_util.rst @@ -578,6 +578,20 @@ NSXtvd Plugin nsxadmin -r projects -o nsx-migrate-v-v3 --property project-id= --property external-net= (--property from-file=True) +NSX Policy Plugin +----------------- +- List all the neutron security groups together with their NSX Policy objects and realization state:: + + nsxadmin -r security-groups -o list + +- List all the neutron networks together with their NSX Policy objects and realization state:: + + nsxadmin -r networks -o list + +- List all the neutron routers together with their NSX Policy objects and realization state:: + + nsxadmin -r routers -o list + Upgrade Steps (NSX-T Version 1.0.0 to Version 1.1.0) ---------------------------------------------------- diff --git a/vmware_nsx/shell/admin/plugins/common/constants.py b/vmware_nsx/shell/admin/plugins/common/constants.py index f3fe2936a3..b8846426d9 100644 --- a/vmware_nsx/shell/admin/plugins/common/constants.py +++ b/vmware_nsx/shell/admin/plugins/common/constants.py @@ -17,11 +17,13 @@ NEUTRON_CONF = '/etc/neutron/neutron.conf' NSX_INI = '/etc/neutron/plugins/vmware/nsx.ini' # NSX Plugin Constants +NSXP_PLUGIN = 'vmware_nsx.plugin.NsxPolicyPlugin' NSXV3_PLUGIN = 'vmware_nsx.plugin.NsxV3Plugin' NSXV_PLUGIN = 'vmware_nsx.plugin.NsxVPlugin' NSXTVD_PLUGIN = 'vmware_nsx.plugin.NsxTVDPlugin' VMWARE_NSXV = 'vmware_nsxv' VMWARE_NSXV3 = 'vmware_nsxv3' +VMWARE_NSXP = 'vmware_nsxp' VMWARE_NSXTVD = 'vmware_nsxtvd' # Common Resource Constants diff --git a/vmware_nsx/shell/admin/plugins/nsxp/__init__.py b/vmware_nsx/shell/admin/plugins/nsxp/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/vmware_nsx/shell/admin/plugins/nsxp/resources/__init__.py b/vmware_nsx/shell/admin/plugins/nsxp/resources/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/vmware_nsx/shell/admin/plugins/nsxp/resources/networks.py b/vmware_nsx/shell/admin/plugins/nsxp/resources/networks.py new file mode 100644 index 0000000000..18c80ef085 --- /dev/null +++ b/vmware_nsx/shell/admin/plugins/nsxp/resources/networks.py @@ -0,0 +1,48 @@ +# 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 + +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 + + +@admin_utils.list_handler(constants.NETWORKS) +@admin_utils.output_header +def list_networks(resource, event, trigger, **kwargs): + """List neutron networks + + With the NSX policy resources and realization state. + """ + mappings = [] + nsxpolicy = p_utils.get_connected_nsxpolicy() + ctx = context.get_admin_context() + with p_utils.NsxPolicyPluginWrapper() as plugin: + nets = plugin.get_networks(ctx) + for net in nets: + # skip non-backend networks + if plugin._network_is_external(ctx, net['id']): + continue + segment_id = plugin._get_network_nsx_segment_id(ctx, net['id']) + status = p_utils.get_realization_info( + nsxpolicy.segment, segment_id) + mappings.append({'ID': net['id'], + 'Name': net.get('name'), + 'Project': net.get('tenant_id'), + 'NSX status': status}) + p_utils.log_info(constants.NETWORKS, + mappings, + attrs=['Project', 'Name', 'ID', 'NSX status']) + return bool(mappings) diff --git a/vmware_nsx/shell/admin/plugins/nsxp/resources/routers.py b/vmware_nsx/shell/admin/plugins/nsxp/resources/routers.py new file mode 100644 index 0000000000..c4aed53851 --- /dev/null +++ b/vmware_nsx/shell/admin/plugins/nsxp/resources/routers.py @@ -0,0 +1,44 @@ +# 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 + +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 + + +@admin_utils.list_handler(constants.ROUTERS) +@admin_utils.output_header +def list_routers(resource, event, trigger, **kwargs): + """List neutron routers + + With the NSX policy resources and realization state. + """ + mappings = [] + nsxpolicy = p_utils.get_connected_nsxpolicy() + ctx = context.get_admin_context() + with p_utils.NsxPolicyPluginWrapper() as plugin: + routers = plugin.get_routers(ctx, fields=['id', 'name', 'tenant_id']) + for rtr in routers: + status = p_utils.get_realization_info( + nsxpolicy.tier1, rtr['id']) + mappings.append({'ID': rtr['id'], + 'Name': rtr.get('name'), + 'Project': rtr.get('tenant_id'), + 'NSX status': status}) + p_utils.log_info(constants.ROUTERS, + mappings, + attrs=['Project', 'Name', 'ID', 'NSX status']) + return bool(mappings) diff --git a/vmware_nsx/shell/admin/plugins/nsxp/resources/securitygroups.py b/vmware_nsx/shell/admin/plugins/nsxp/resources/securitygroups.py new file mode 100644 index 0000000000..a06a22067a --- /dev/null +++ b/vmware_nsx/shell/admin/plugins/nsxp/resources/securitygroups.py @@ -0,0 +1,50 @@ +# 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.db import securitygroups_db +from neutron_lib import context + +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 + +neutron_client = securitygroups_db.SecurityGroupDbMixin() + + +@admin_utils.list_handler(constants.SECURITY_GROUPS) +@admin_utils.output_header +def list_security_groups(resource, event, trigger, **kwargs): + """List neutron security groups + + With the NSX policy resources and realization state. + """ + mappings = [] + nsxpolicy = p_utils.get_connected_nsxpolicy() + ctx = context.get_admin_context() + sgs = neutron_client.get_security_groups(ctx) + for sg in sgs: + domain_id = sg['tenant_id'] + map_status = p_utils.get_realization_info( + nsxpolicy.comm_map, domain_id, sg['id']) + group_status = p_utils.get_realization_info( + nsxpolicy.group, domain_id, sg['id']) + mappings.append({'ID': sg['id'], + 'Name': sg.get('name'), + 'Project': domain_id, + 'NSX Group': group_status, + 'NSX Map': map_status}) + p_utils.log_info(constants.SECURITY_GROUPS, + mappings, + attrs=['Project', 'Name', 'ID', 'NSX Group', 'NSX Map']) + return bool(mappings) diff --git a/vmware_nsx/shell/admin/plugins/nsxp/resources/utils.py b/vmware_nsx/shell/admin/plugins/nsxp/resources/utils.py new file mode 100644 index 0000000000..4025c15327 --- /dev/null +++ b/vmware_nsx/shell/admin/plugins/nsxp/resources/utils.py @@ -0,0 +1,81 @@ +# 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.db import l3_dvr_db # noqa +from neutron_lib import context +from neutron_lib.plugins import constants as const +from neutron_lib.plugins import directory +from oslo_log import log as logging + +from vmware_nsx.plugins.nsx_p import plugin +from vmware_nsx.plugins.nsx_v3 import utils as v3_utils +from vmware_nsx.shell.admin.plugins.common import formatters + +LOG = logging.getLogger(__name__) +_NSXPOLICY = None + + +def get_nsxp_client(nsx_username=None, nsx_password=None, + use_basic_auth=False): + + return get_connected_nsxpolicy(nsx_username, + nsx_password, + use_basic_auth).client + + +def get_connected_nsxpolicy(nsx_username=None, nsx_password=None, + use_basic_auth=False): + global _NSXPOLICY + + # for non-default agruments, initiate new lib + if nsx_username or use_basic_auth: + return v3_utils.get_nsxpolicy_wrapper(nsx_username, + nsx_password, + use_basic_auth) + if _NSXPOLICY is None: + _NSXPOLICY = v3_utils.get_nsxpolicy_wrapper() + return _NSXPOLICY + + +def log_info(resource, data, attrs=['display_name', 'id']): + LOG.info(formatters.output_formatter(resource, data, attrs)) + + +def get_realization_info(resource, *realization_args): + try: + nsx_info = resource.get_realization_info(*realization_args) + if not nsx_info: + info_text = "MISSING" + else: + state = nsx_info.get('state') + nsx_id = nsx_info.get('realization_specific_identifier') + info_text = "%s (ID: %s)" % (state, nsx_id) + except Exception as e: + LOG.warning("Failed to get realization info for %s(%s): %s", + resource, str(realization_args), e) + info_text = "UNKNOWN" + return info_text + + +class NsxPolicyPluginWrapper(plugin.NsxPolicyPlugin): + def __init__(self): + super(NsxPolicyPluginWrapper, self).__init__() + self.context = context.get_admin_context() + + def __enter__(self): + directory.add_plugin(const.CORE, self) + return self + + def __exit__(self, exc_type, exc_value, traceback): + directory.add_plugin(const.CORE, None) diff --git a/vmware_nsx/shell/nsxadmin.py b/vmware_nsx/shell/nsxadmin.py index b96964087d..f79db8f313 100644 --- a/vmware_nsx/shell/nsxadmin.py +++ b/vmware_nsx/shell/nsxadmin.py @@ -81,6 +81,10 @@ def _validate_resource_choice(resource, nsx_plugin): LOG.error('Supported list of NSX-TVD resources: %s', resources.nsxtvd_resources_names) sys.exit(1) + elif nsx_plugin == 'nsxp'and resource not in resources.nsxp_resources: + LOG.error('Supported list of NSX-P resources: %s', + resources.nsxp_resources_names) + sys.exit(1) def _validate_op_choice(choice, nsx_plugin): @@ -108,6 +112,14 @@ def _validate_op_choice(choice, nsx_plugin): 'resource %s', supported_resource_ops) sys.exit(1) + elif nsx_plugin == 'nsxp': + supported_resource_ops = \ + resources.nsxp_resources[cfg.CONF.resource].supported_ops + if choice not in supported_resource_ops: + LOG.error('Supported list of operations for the NSX-P ' + 'resource %s', supported_resource_ops) + sys.exit(1) + def _validate_plugin_choice(selected_plugin, nsx_plugin): if nsx_plugin == 'nsxtvd': diff --git a/vmware_nsx/shell/resources.py b/vmware_nsx/shell/resources.py index 2f786d38b5..9f8799e968 100644 --- a/vmware_nsx/shell/resources.py +++ b/vmware_nsx/shell/resources.py @@ -239,9 +239,19 @@ nsxtvd_resources = { Operations.NSX_MIGRATE_V_V3.value]), } +nsxp_resources = { + constants.SECURITY_GROUPS: Resource(constants.SECURITY_GROUPS, + [Operations.LIST.value]), + constants.NETWORKS: Resource(constants.NETWORKS, + [Operations.LIST.value]), + constants.ROUTERS: Resource(constants.ROUTERS, + [Operations.LIST.value]), +} + nsxv3_resources_names = list(nsxv3_resources.keys()) nsxv_resources_names = list(nsxv_resources.keys()) nsxtvd_resources_names = list(nsxtvd_resources.keys()) +nsxp_resources_names = list(nsxp_resources.keys()) def get_resources(plugin_dir): @@ -259,6 +269,8 @@ def get_plugin(): plugin_name = 'nsxv' elif plugin in (constants.NSXTVD_PLUGIN, constants.VMWARE_NSXTVD): plugin_name = 'nsxtvd' + elif plugin in (constants.NSXP_PLUGIN, constants.VMWARE_NSXP): + plugin_name = 'nsxp' return plugin_name diff --git a/vmware_nsx/tests/unit/shell/test_admin_utils.py b/vmware_nsx/tests/unit/shell/test_admin_utils.py index 6f6c1351a4..d98f67ed45 100644 --- a/vmware_nsx/tests/unit/shell/test_admin_utils.py +++ b/vmware_nsx/tests/unit/shell/test_admin_utils.py @@ -37,6 +37,7 @@ from vmware_nsx.shell.admin.plugins.nsxv.resources import utils as nsxv_utils from vmware_nsx.shell.admin.plugins.nsxv3.resources import utils as nsxv3_utils from vmware_nsx.shell import resources from vmware_nsx.tests import unit as vmware +from vmware_nsx.tests.unit.nsx_p import test_plugin as test_p_plugin from vmware_nsx.tests.unit.nsx_v import test_plugin as test_v_plugin from vmware_nsx.tests.unit.nsx_v3 import test_plugin as test_v3_plugin from vmware_nsxlib.v3 import core_resources @@ -311,3 +312,13 @@ class TestNsxtvdAdminUtils(AbstractTestAdminUtils): def test_nsxtv_resources(self): self._test_resources(resources.nsxtvd_resources) + + +class TestNsxpAdminUtils(AbstractTestAdminUtils, + test_p_plugin.NsxPPluginTestCaseMixin): + + def _get_plugin_name(self): + return 'nsxp' + + def test_nsxp_resources(self): + self._test_resources(resources.nsxp_resources)