NSX-Admin: Support syslog configuration for edges

Add syslog configuration support for edges to nsxadmin utility.
Syslog config on edge consists of 2 syslog server IPs and protocol.
Syslog config can only be updated as one bundle (no way to update
protocol only)
to show syslog config:
    nsxadmin -o nsx-list -r edges --verbose
to update syslog config:
    nsxadmin -o nsx-update -r edges -p edge-id=<edge id>
    -p syslog-server=<ip> -p syslog-server2=<ip>
    -p syslog-proto=tcp|udp
to delete syslog config:
    nsxadmin -o nsx-update -r edges -p edge-id=<edge id>
    -p syslog-server=none

Change-Id: I26a29d7fdce6a835b4771b890c9973753ec92d79
This commit is contained in:
Anna Khmelnitsky 2016-11-25 08:51:08 -08:00
parent 2a281aecce
commit 2be66a0240
8 changed files with 140 additions and 6 deletions

View File

@ -16,6 +16,10 @@ Edges
nsxadmin -r edges -o nsx-list
- List backend NSX edges with more details::
nsxadmin -r edges -o nsx-list --verbose
- Neutron list::
nsxadmin -r edges -o neutron-list
@ -36,6 +40,14 @@ Edges
nsxadmin -r edges -o nsx-update --property edge-id=edge-55 --property highavailability=<True/False>
- Update syslog config on edge (syslog-proto and syslog-server2 are optional)::
nsxadmin -o nsx-update -r edges -p edge-id=edge-55 --property syslog-server=<server ip> --property syslog-server2=<server ip> --property syslog-proto=<tcp|udp>
- Delete syslog config on edge::
nsxadmin -o nsx-update -r edges -p edge-id=edge-55 --property syslog-server=none
Orphaned Edges
~~~~~~~~~~~~~~

View File

@ -238,6 +238,18 @@ class Vcns(object):
uri = URI_PREFIX
return self.do_request(HTTP_GET, uri, decode=True)
def get_edge_syslog(self, edge_id):
uri = "%s/%s/syslog/config" % (URI_PREFIX, edge_id)
return self.do_request(HTTP_GET, uri, decode=True)
def update_edge_syslog(self, edge_id, config):
uri = "%s/%s/syslog/config" % (URI_PREFIX, edge_id)
return self.do_request(HTTP_PUT, uri, config)
def delete_edge_syslog(self, edge_id):
uri = "%s/%s/syslog/config" % (URI_PREFIX, edge_id)
return self.do_request(HTTP_DELETE, uri)
def get_edge_interfaces(self, edge_id):
uri = "%s/%s/interfaces" % (URI_PREFIX, edge_id)
return self.do_request(HTTP_GET, uri, decode=True)

View File

@ -15,6 +15,7 @@
import logging
import pprint
import textwrap
from vmware_nsx.shell.admin.plugins.common import constants
from vmware_nsx.shell.admin.plugins.common import formatters
@ -39,9 +40,24 @@ nsxv = utils.get_nsxv_client()
@admin_utils.output_header
def nsx_list_edges(resource, event, trigger, **kwargs):
"""List edges from NSXv backend"""
headers = ['id', 'name', 'type', 'size']
edges = utils.get_nsxv_backend_edges()
LOG.info(formatters.output_formatter(constants.EDGES, edges,
['id', 'name', 'type', 'size']))
if (kwargs.get('verbose')):
headers += ['syslog']
extend_edge_info(edges)
LOG.info(formatters.output_formatter(constants.EDGES, edges, headers))
def extend_edge_info(edges):
"""Add syslog info to each edge in list"""
for edge in edges:
# for the table to remain human readable, we need to
# wrap long edge names
edge['name'] = textwrap.fill(edge['name'], 25)
edge['syslog'] = utils.get_edge_syslog_info(edge['id'])
def get_router_edge_bindings():
@ -171,6 +187,41 @@ def change_edge_ha(ha, edge_id):
LOG.error(_LE("%s"), str(e))
def change_edge_syslog(properties):
request = {
'featureType': 'syslog',
'serverAddresses': {'ipAddress': [], 'type': 'IpAddressesDto'}}
request['protocol'] = properties.get('syslog-proto', 'tcp')
if request['protocol'] not in ['tcp', 'udp']:
LOG.error(_LE("Property value error: syslog-proto must be tcp/udp"))
return
if properties.get('syslog-server'):
request['serverAddresses']['ipAddress'].append(
properties.get('syslog-server'))
if properties.get('syslog-server2'):
request['serverAddresses']['ipAddress'].append(
properties.get('syslog-server2'))
edge_id = properties.get('edge-id')
try:
nsxv.update_edge_syslog(edge_id, request)
except nsxv_exceptions.ResourceNotFound as e:
LOG.error(_LE("Edge %s not found"), edge_id)
except exceptions.NeutronException as e:
LOG.error(_LE("%s"), str(e))
def delete_edge_syslog(edge_id):
try:
nsxv.delete_edge_syslog(edge_id)
except nsxv_exceptions.ResourceNotFound as e:
LOG.error(_LE("Edge %s not found"), edge_id)
except exceptions.NeutronException as e:
LOG.error(_LE("%s"), str(e))
def change_edge_appliance_size(properties):
size = properties.get('size')
if size not in nsxv_constants.ALLOWED_EDGE_SIZES:
@ -234,7 +285,10 @@ def nsx_update_edge(resource, event, trigger, **kwargs):
usage_msg = _LE("Need to specify edge-id parameter and "
"attribute to update. Add --property edge-id=<edge-id> "
"and --property highavailability=<True/False> or "
"--property size=<size> or --property appliances=True")
"--property size=<size> or --property appliances=True. "
"For syslog, add --property syslog-server=<ip>|none and "
"(optional) --property syslog-server2=<ip> and/or "
"(optional) --property syslog-proto=[tcp/udp]")
if not kwargs.get('property'):
LOG.error(usage_msg)
return
@ -253,6 +307,11 @@ def nsx_update_edge(resource, event, trigger, **kwargs):
elif (properties.get('appliances') and
properties.get('appliances').lower() == "true"):
change_edge_appliance(properties['edge-id'])
elif properties.get('syslog-server'):
if (properties.get('syslog-server').lower() == "none"):
delete_edge_syslog(properties['edge-id'])
else:
change_edge_syslog(properties)
else:
# no attribute was specified
LOG.error(usage_msg)

View File

@ -68,3 +68,21 @@ def get_nsxv_backend_edges():
}
backend_edges.append(edge_data)
return backend_edges
def get_edge_syslog_info(edge_id):
"""Get syslog information for specific edge id"""
nsxv = get_nsxv_client()
syslog_info = nsxv.get_edge_syslog(edge_id)[1]
if not syslog_info['enabled']:
return 'Disabled'
output = ""
if 'protocol' in syslog_info:
output += syslog_info['protocol']
if 'serverAddresses' in syslog_info:
for server_address in syslog_info['serverAddresses']['ipAddress']:
output += "\n" + server_address
return output

View File

@ -49,7 +49,6 @@ LOG = logging.getLogger(__name__)
def _init_cfg():
cfg.CONF.register_cli_opts(resources.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
@ -58,6 +57,9 @@ def _init_cfg():
cfg.CONF.unregister_opts(_options.logging_cli_opts)
cfg.CONF.unregister_opts(neutron_common_config.core_cli_opts)
# register must come after above unregister to avoid duplicates
cfg.CONF.register_cli_opts(resources.cli_opts)
# Init the neutron config
neutron_config.init(args=['--config-file', constants.NEUTRON_CONF,
'--config-file', constants.NSX_INI])
@ -111,7 +113,8 @@ def main(argv=sys.argv[1:]):
_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)
force=cfg.CONF.force, property=cfg.CONF.property,
verbose=cfg.CONF.verbose)
if __name__ == "__main__":

View File

@ -197,7 +197,11 @@ cli_opts = [cfg.StrOpt('fmt',
cfg.MultiStrOpt('property',
short='p',
help='Key-value pair containing the information '
'to be updated. For ex: key=value.')
'to be updated. For ex: key=value.'),
cfg.BoolOpt('verbose',
short='v',
default=False,
help='Triggers detailed output for some commands')
]

View File

@ -1169,6 +1169,30 @@ class FakeVcns(object):
response = ''
return (header, response)
def get_edge_syslog(self, edge_id):
header = {
'status': 200,
}
response = {
'protocol': 'tcp',
'serverAddresses': {'ipAddress': ['1.1.1.1']}
}
return (header, response)
def update_edge_syslog(self, edge_id, config):
header = {
'status': 204
}
response = ''
return (header, response)
def delete_edge_syslog(self, edge_id):
header = {
'status': 204
}
response = ''
return (header, response)
def change_edge_appliance_size(self, edge_id, size):
header = {
'status': 204

View File

@ -19,6 +19,7 @@ import mock
import six
from oslo_config import cfg
from oslo_log import _options
from oslo_utils import uuidutils
from neutron.callbacks import registry
@ -45,6 +46,7 @@ BASE_CONF_PATH = vmware.get_fake_conf('neutron.conf.test')
class AbstractTestAdminUtils(base.BaseTestCase):
def setUp(self):
cfg.CONF.unregister_opts(_options.common_cli_opts)
cfg.CONF.register_cli_opts(resources.cli_opts)
super(AbstractTestAdminUtils, self).setUp()