vmware-nsx/tools/python_nsxadmin/admin/shell.py

220 lines
7.5 KiB
Python

# Copyright 2015 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.
"""
Purpose of this script is to build a framework which can be leveraged
to build utilities to help the on-field ops in system debugging.
TODO: Use Cliff https://pypi.python.org/pypi/cliff
TODO: Define commands instead of -r -o like get-security-groups,
delete-security-groups, nsx neutron nsxv3 can be options
TODO: Add support for other resources, ports, logical switches etc.
TODO: Autocomplete command line args
"""
import enum
import glob
import importlib
import logging
import os
import requests
import sys
from neutron.callbacks import registry
from neutron.common import config as neutron_config
from vmware_nsx._i18n import _LE, _LI
from vmware_nsx.common import config # noqa
from oslo_config import cfg
from oslo_log import _options
from tools.python_nsxadmin.admin.plugins.common import constants
from tools.python_nsxadmin.admin import version
# Suppress the Insecure request warning
requests.packages.urllib3.disable_warnings()
LOG = logging.getLogger(__name__)
class Operations(enum.Enum):
LIST = 'list'
CLEAN = 'clean'
NEUTRON_LIST = 'neutron-list'
NEUTRON_CLEAN = 'neutron-clean'
NEUTRON_UPDATE = 'neutron-update'
NSX_LIST = 'nsx-list'
NSX_CLEAN = 'nsx-clean'
NSX_UPDATE = 'nsx-update'
ops = [op.value for op in Operations]
class Resource(object):
def __init__(self, name, ops):
self.name = name
self.supported_ops = ops
# Add supported NSX-V3 resources in this dictionary
nsxv3_resources = {
constants.SECURITY_GROUPS: Resource(constants.SECURITY_GROUPS, ops)
}
# Add supported NSX-V resources in this dictionary
nsxv_resources = {
constants.EDGES: Resource(constants.EDGES, [Operations.LIST.value,
Operations.CLEAN.value,
Operations.NSX_UPDATE.value]),
constants.SPOOFGUARD_POLICY: Resource(constants.SPOOFGUARD_POLICY,
[Operations.LIST.value]),
constants.DHCP_BINDING: Resource(constants.DHCP_BINDING,
[Operations.LIST.value,
Operations.NSX_UPDATE.value]),
}
nsxv3_resources_names = map(lambda res: res.name, nsxv3_resources.itervalues())
nsxv_resources_names = map(lambda res: res.name, nsxv_resources.itervalues())
def _get_plugin():
plugin = cfg.CONF.core_plugin
plugin_name = ''
if plugin == constants.NSXV3_PLUGIN:
plugin_name = 'nsxv3'
elif plugin == constants.NSXV_PLUGIN:
plugin_name = 'nsxv'
return plugin_name
def _get_plugin_dir():
plugin_dir = 'tools/python_nsxadmin/admin/plugins'
return '{}/{}/resources'.format(plugin_dir, _get_plugin())
def _get_resources():
modules = glob.glob(_get_plugin_dir() + "/*.py")
return map(lambda module: os.path.splitext(os.path.basename(module))[0],
modules)
cli_opts = [cfg.StrOpt('neutron-conf',
default='/etc/neutron/neutron.conf',
help='Neutron configuration file'),
cfg.StrOpt('nsx-conf',
default='/etc/neutron/plugins/vmware/nsx.ini',
help='NSX configuration file'),
cfg.StrOpt('fmt',
short='f',
default='psql',
choices=['psql', 'json'],
help='Supported output formats: json, psql'),
cfg.StrOpt('resource',
short='r',
choices=nsxv_resources_names + nsxv3_resources_names,
help='Supported list of resources: NSX-V3: %s '
'NSX-V: %s' % (', '.join(nsxv3_resources_names),
', '.join(nsxv_resources_names))),
cfg.StrOpt('operation',
short='o',
help='Supported list of operations: {}'
.format(', '.join(ops))),
cfg.BoolOpt('force',
default=False,
help='Enables \'force\' mode. No confirmations will '
'be made before deletions.'),
cfg.MultiStrOpt('property',
short='p',
help='Key-value pair containing the information '
'to be updated. For ex: key=value.')
]
def _init_resource_plugin():
resources = _get_resources()
for resource in resources:
if resource != '__init__':
importlib.import_module("." + resource,
_get_plugin_dir().replace("/", "."))
def _init_cfg():
cfg.CONF.register_cli_opts(cli_opts)
# NOTE(gangila): neutron.common.config registers some options by default
# which are then shown in the help message. We don't need them
# so we unregister these options
cfg.CONF.unregister_opts(_options.common_cli_opts)
cfg.CONF.unregister_opts(_options.logging_cli_opts)
cfg.CONF.unregister_opts(neutron_config.core_cli_opts)
cfg.CONF(args=sys.argv[1:], project='NSX',
prog='Admin Utility',
version=version.__version__,
usage='nsxadmin -r <resources> -o <operation>',
default_config_files=[cfg.CONF.neutron_conf,
cfg.CONF.nsx_conf])
def _validate_resource_choice(resource, nsx_plugin):
if nsx_plugin == 'nsxv' and resource not in nsxv_resources:
LOG.error(_LE('Supported list of NSX-V resources: %s'),
nsxv_resources_names)
sys.exit(1)
elif nsx_plugin == 'nsxv3'and resource not in nsxv3_resources:
LOG.error(_LE('Supported list of NSX-V3 resources: %s'),
nsxv3_resources_names)
sys.exit(1)
def _validate_op_choice(choice, nsx_plugin):
if nsx_plugin == 'nsxv':
supported_resource_ops = \
nsxv_resources[cfg.CONF.resource].supported_ops
if choice not in supported_resource_ops:
LOG.error(_LE('Supported list of operations for the NSX-V '
'resource %s'), supported_resource_ops)
sys.exit(1)
elif nsx_plugin == 'nsxv3':
supported_resource_ops = \
nsxv3_resources[cfg.CONF.resource].supported_ops
if choice not in supported_resource_ops:
LOG.error(_LE('Supported list of operations for the NSX-V3 '
'resource %s'), supported_resource_ops)
sys.exit(1)
def main(argv=sys.argv[1:]):
_init_cfg()
_init_resource_plugin()
nsx_plugin_in_use = _get_plugin()
LOG.info(_LI('NSX Plugin in use: %s'), nsx_plugin_in_use)
_validate_resource_choice(cfg.CONF.resource, nsx_plugin_in_use)
_validate_op_choice(cfg.CONF.operation, nsx_plugin_in_use)
registry.notify(cfg.CONF.resource, cfg.CONF.operation, 'nsxadmin',
force=cfg.CONF.force, property=cfg.CONF.property)
if __name__ == "__main__":
sys.exit(main(sys.argv[1:]))