From 53787d2f62557558a50f59c98c5db90b0eceae94 Mon Sep 17 00:00:00 2001 From: Steve McIntyre Date: Fri, 2 Feb 2018 17:08:04 +0000 Subject: Renamed the admin program from "admin.py" to "vland-admin" This will make packaging easier Change-Id: I840aa8e73911bcb4b02903a0202178005e2c58b3 --- Changelog | 2 + README | 6 +- admin.py | 882 ------------------------------------------------------- test/test-common | 2 +- vland-admin | 882 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ vland.py | 2 +- vland.service | 2 +- 7 files changed, 890 insertions(+), 888 deletions(-) delete mode 100755 admin.py create mode 100755 vland-admin diff --git a/Changelog b/Changelog index f147d6f..90efbc2 100644 --- a/Changelog +++ b/Changelog @@ -1,6 +1,8 @@ vland 0.7 * Added new driver to support the Mellanox SN2100 switch, using MLNX-OS + * Renamed the admin program from "admin.py" to "vland-admin" to make + packaging easier * Minor changes to the database code: + Automatic schema updates at vland startup + Add extra lock_reason field in the port table, and code to match diff --git a/README b/README index 76f5f13..e7bb828 100644 --- a/README +++ b/README @@ -84,9 +84,9 @@ permissions in the database for that user. The core VLANd code is simple to configure - see vland.cfg for an example config file. Once your copy of VLANd is running, use the -administration utility admin.py to control what it does. For now, this -is single-threaded and has *no* security. This *will* change in the -future, but for very early development has not been a priority. +administration utility "vland-admin" to control what it does. For now, +this is single-threaded and has *no* security. This *will* change in +the future, but for very early development has not been a priority. The visualisation interface has very few configuration options as yet - again, see the default vland.cfg. diff --git a/admin.py b/admin.py deleted file mode 100755 index b7ae1b7..0000000 --- a/admin.py +++ /dev/null @@ -1,882 +0,0 @@ -#! /usr/bin/python - -# Copyright 2014-2018 Linaro Limited -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, -# MA 02110-1301, USA. -# -# VLANd admin interface -# - -import os, sys -import argparse -import datetime, time - -vlandpath = os.path.abspath(os.path.normpath(os.path.dirname(sys.argv[0]))) -sys.path.insert(0, vlandpath) - -from errors import InputError, SocketError, NotFoundError, Error -from config.config import VlanConfig -from ipc.ipc import VlanIpc - -prog = "admin" -version = "0.7" -banner = "Linaro VLANd admin interface, version %s" % version -exitcode = Error.OK -TRUNK_ID_NONE = -1 - -def is_positive(text): - if text in ('1', 'y', 'Y', 't', 'T', 'True', 'true'): - return True - elif text in ('0', 'n', 'N', 'f', 'F', 'False', 'false'): - return False - else: - raise InputError("Cannot parse \"%s\" as True or False" % text) - -def dump_switch(switch): - print "switch_id:%d name:%s" % ( - int(switch['switch_id']), - switch['name']) - -def dump_port(port): - print "port_id:%d name:%s switch_id:%d locked:%s mode:%s base_vlan_id:%d current_vlan_id:%d number:%d trunk_id:%s lock_reason:%s" % ( - int(port['port_id']), - port['name'], - int(port['switch_id']), - ("yes" if port['is_locked'] is True else "no"), - ("trunk" if port['is_trunk'] is True else "access"), - int(port['base_vlan_id']), - int(port['current_vlan_id']), - int(port['number']), - 'None' if (TRUNK_ID_NONE == port['trunk_id']) else port['trunk_id'], - port['lock_reason']) - -def dump_vlan(vlan): - print "vlan_id:%d name:%s tag:%d is_base_vlan:%s, creation_time:%s" % ( - int(vlan['vlan_id']), - vlan['name'], - int(vlan['tag']), - ("yes" if vlan['is_base_vlan'] is True else "no"), - vlan['creation_time']) - -def dump_trunk(trunk): - print "trunk_id:%d creation_time:%s" % ( - int(trunk['trunk_id']), - trunk['creation_time']) - -def call_vland(msgtype, msg): - ipc = VlanIpc() - ipc.client_connect('localhost', config.vland.port) - msg['client_name'] = 'admin.py' - msg['type'] = msgtype - ipc.client_send(msg) - ret = ipc.client_recv_and_close() - if 'response' not in ret: - raise SocketError("Badly-formed response from VLANd server") - if ret['response'] == "ERROR": - raise InputError("VLANd server said \"%s\"" % ret['error']) - if ret['response'] == "NOTFOUND": - raise NotFoundError("VLANd server said \"%s\"" % ret['error']) - return ret['data'] - -config = VlanConfig(filenames=('./vland.cfg',)) - -parser = argparse.ArgumentParser() - -#################### -# System commands -#################### -sp = parser.add_subparsers(title='Sub-commands', - help="Commands", - dest='subparser_name') -p_status = sp.add_parser("status", - help="Describe current system status") -p_status.set_defaults(which = "status") -p_statistics = sp.add_parser("statistics", - help="Print some system statistics") -p_statistics.set_defaults(which = "statistics") -p_version = sp.add_parser("version", - help="Describe the version of this admin interface") -p_version.set_defaults(which = "version") -p_vland_version = sp.add_parser("vland_version", - help="Describe the version of the running VLANd") -p_vland_version.set_defaults(which = "vland_version") -p_probe_switches = sp.add_parser("probe_switches", - help="Probe all the configured switches") -p_probe_switches.set_defaults(which = "probe_switches") -p_auto_import = sp.add_parser("auto_import_switch", - help="Attempt to import a switch's configuration into the VLANd system") -p_auto_import.add_argument('--name', - required = True, - help="Import the switch named SWITCH_NAME in vland.cfg") -p_auto_import.set_defaults(which = "auto_import_switch") -p_shutdown = sp.add_parser("shutdown", - help="Shut down a running VLANd") -p_shutdown.set_defaults(which = "shutdown") - -#################### -# Switch commands -#################### -p_list_all_switches = sp.add_parser("list_all_switches", - help="List all the existing switches in the system") -p_list_all_switches.set_defaults(which = "list_all_switches") -p_create_switch = sp.add_parser("create_switch", - help = "Add a new switch to the system") -p_create_switch.set_defaults(which = "create_switch") -p_create_switch.add_argument('--name', - required = True, - help="The name of the new switch, as described in vland.cfg") -p_delete_switch = sp.add_parser("delete_switch", - help = "Remove an existing switch from the system") -p_delete_switch.set_defaults(which = "delete_switch") -p_delete_switch.add_argument('--switch_id', - required = True, - help = "The ID of the switch to remove") -p_show_switch = sp.add_parser("show_switch", - help = "Show the details of an existing switch in the system") -p_show_switch.set_defaults(which = "show_switch") -p_show_switch.add_argument('--switch_id', - required = True, - help = "The ID of the switch to show") -p_lookup_switch_by_name = sp.add_parser("lookup_switch_by_name", - help = "Lookup a switch ID by name") -p_lookup_switch_by_name.set_defaults(which = "lookup_switch_by_name") -p_lookup_switch_by_name.add_argument('--name', - required = True, - help = "The switch name to search for") - -#################### -# Ports commands -#################### -p_list_all_ports = sp.add_parser("list_all_ports", - help="List all the existing ports in the system") -p_list_all_ports.set_defaults(which = "list_all_ports") -p_create_port = sp.add_parser("create_port", - help = "Add a new port to the system") -p_create_port.set_defaults(which = "create_port") -p_create_port.add_argument('--switch_id', - required = True, - help="The ID of the switch containing the new port") -p_create_port.add_argument('--name', - required = True, - help="The name of the new port") -p_create_port.add_argument('--number', - required = True, - help="The human-friendly number for the new port") -p_delete_port = sp.add_parser("delete_port", - help = "Remove an existing port from the system") -p_delete_port.set_defaults(which = "delete_port") -p_delete_port.add_argument('--port_id', - required = True, - help = "The ID of the port to remove") -p_show_port = sp.add_parser("show_port", - help = "Show the details of an existing port in the system") -p_show_port.set_defaults(which = "show_port") -p_show_port.add_argument('--port_id', - required = True, - help = "The ID of the port to show") -p_lookup_port_by_switch_and_name = sp.add_parser("lookup_port_by_switch_and_name", - help = "Lookup a port ID by switch ID and port name") -p_lookup_port_by_switch_and_name.set_defaults(which = "lookup_port_by_switch_and_name") -p_lookup_port_by_switch_and_name.add_argument('--switch_id', - required = True, - help = "The switch ID to search for") -p_lookup_port_by_switch_and_name.add_argument('--name', - required = True, - help = "The port name to search for") -p_lookup_port_by_switch_and_number = sp.add_parser("lookup_port_by_switch_and_number", - help = "Lookup a port ID by switch ID and port number") -p_lookup_port_by_switch_and_number.set_defaults(which = "lookup_port_by_switch_and_number") -p_lookup_port_by_switch_and_number.add_argument('--switch_id', - required = True, - help = "The switch ID to search for") -p_lookup_port_by_switch_and_number.add_argument('--number', - required = True, - help = "The port number to search for") -p_lookup_ports_by_switch = sp.add_parser("lookup_ports_by_switch", - help = "Lookup port ID(s) by switch ID") -p_lookup_ports_by_switch.set_defaults(which = "lookup_ports_by_switch") -p_lookup_ports_by_switch.add_argument('--switch_id', - required = True, - help = "The switch ID to search for") -p_lookup_ports_by_current_vlan = sp.add_parser("lookup_ports_by_current_vlan", - help = "Lookup port ID(s) by current VLAN ID") -p_lookup_ports_by_current_vlan.set_defaults(which = "lookup_ports_by_current_vlan") -p_lookup_ports_by_current_vlan.add_argument('--vlan_id', - required = True, - help = "The VLAN ID to search for") -p_lookup_ports_by_base_vlan = sp.add_parser("lookup_ports_by_base_vlan", - help = "Lookup port ID(s) by base vlan ID") -p_lookup_ports_by_base_vlan.set_defaults(which = "lookup_ports_by_base_vlan") -p_lookup_ports_by_base_vlan.add_argument('--vlan_id', - required = True, - help = "The VLAN ID to search for") -p_lookup_ports_by_trunk = sp.add_parser("lookup_ports_by_trunk", - help = "Lookup port ID(s) by trunk ID") -p_lookup_ports_by_trunk.set_defaults(which = "lookup_ports_by_trunk") -p_lookup_ports_by_trunk.add_argument('--trunk_id', - required = True, - help = "The trunk ID to search for") -p_set_port_mode = sp.add_parser("set_port_mode", - help = "Set the mode of a port to 'trunk' or 'access'") -p_set_port_mode.set_defaults(which = "set_port_mode") -p_set_port_mode.add_argument('--port_id', - required = True, - help = "The ID of the port to modify") -p_set_port_mode.add_argument('--mode', - required = True, - help = "The mode to select ('trunk' or 'access')") -p_get_port_mode = sp.add_parser("get_port_mode", - help = "Get the mode of a port ('trunk' or 'access')") -p_get_port_mode.set_defaults(which = "get_port_mode") -p_get_port_mode.add_argument('--port_id', - required = True, - help = "The ID of the port to query") -p_lock_port = sp.add_parser("lock_port", - help = "Lock the settings on a port") -p_lock_port.set_defaults(which = "lock_port") -p_lock_port.add_argument('--port_id', - required = True, - help = "The ID of the port to lock") -p_lock_port.add_argument('--reason', - required = False, - help = "(Optional) The reason for locking the port") -p_unlock_port = sp.add_parser("unlock_port", - help = "Unlock the settings on a port") -p_unlock_port.set_defaults(which = "unlock_port") -p_unlock_port.add_argument('--port_id', - required = True, - help = "The ID of the port to unlock") -p_set_port_current_vlan = sp.add_parser("set_port_current_vlan", - help = "Set the current VLAN assignment for a port") -p_set_port_current_vlan.set_defaults(which = "set_port_current_vlan") -p_set_port_current_vlan.add_argument('--port_id', - required = True, - help = "The ID of the port to modify") -p_set_port_current_vlan.add_argument('--vlan_id', - required = True, - help = "The VLAN ID to be used") -p_get_port_current_vlan = sp.add_parser("get_port_current_vlan", - help = "Get the current VLAN assignment for a port") -p_get_port_current_vlan.set_defaults(which = "get_port_current_vlan") -p_get_port_current_vlan.add_argument('--port_id', - required = True, - help = "The ID of the port to query") -p_set_port_base_vlan = sp.add_parser("set_port_base_vlan", - help = "Set the base VLAN assignment for a port") -p_set_port_base_vlan.set_defaults(which = "set_port_base_vlan") -p_set_port_base_vlan.add_argument('--port_id', - required = True, - help = "The ID of the port to modify") -p_set_port_base_vlan.add_argument('--vlan_id', - required = True, - help = "The VLAN ID to be used") -p_get_port_base_vlan = sp.add_parser("get_port_base_vlan", - help = "Get the base VLAN assignment for a port") -p_get_port_base_vlan.set_defaults(which = "get_port_base_vlan") -p_get_port_base_vlan.add_argument('--port_id', - required = True, - help = "The ID of the port to query") -p_restore_port_to_base_vlan = sp.add_parser("restore_port_to_base_vlan", - help = "Reset a port back to its base VLAN") -p_restore_port_to_base_vlan.set_defaults(which = "restore_port_to_base_vlan") -p_restore_port_to_base_vlan.add_argument('--port_id', - required = True, - help = "The ID of the port to modify") - -#################### -# VLAN commands -#################### -p_list_all_vlans = sp.add_parser("list_all_vlans", - help="List all the existing VLANs in the system") -p_list_all_vlans.set_defaults(which = "list_all_vlans") -p_create_vlan = sp.add_parser("create_vlan", - help = "Add a new VLAN to the system") -p_create_vlan.set_defaults(which = "create_vlan") -p_create_vlan.add_argument('--name', - required = True, - help="The name of the new VLAN") -p_create_vlan.add_argument('--tag', - required = True, - help="The tag for the new VLAN (-1 to automatically select)") -p_create_vlan.add_argument('--is_base_vlan', - required = True, - help="Is the new VLAN a base VLAN (true/false)") -p_delete_vlan = sp.add_parser("delete_vlan", - help = "Remove an existing VLAN from the system") -p_delete_vlan.set_defaults(which = "delete_vlan") -p_delete_vlan.add_argument('--vlan_id', - required = True, - help = "The ID of the VLAN to remove") -p_show_vlan = sp.add_parser("show_vlan", - help = "Show the details of an existing VLAN in the system") -p_show_vlan.set_defaults(which = "show_vlan") -p_show_vlan.add_argument('--vlan_id', - required = True, - help = "The ID of the VLAN to show") -p_lookup_vlan_by_tag = sp.add_parser("lookup_vlan_by_tag", - help = "Find the VLAN ID of an existing VLAN in the system") -p_lookup_vlan_by_tag.set_defaults(which = "lookup_vlan_by_tag") -p_lookup_vlan_by_tag.add_argument('--tag', - required = True, - help = "The VLAN tag to search for") -p_show_vlan_tag = sp.add_parser("show_vlan_tag", - help = "Print the VLAN tag of an existing VLAN in the system") -p_show_vlan_tag.set_defaults(which = "show_vlan_tag") -p_show_vlan_tag.add_argument('--vlan_id', - required = True, - help = "The VLAN ID to search for") - -#################### -# Trunk commands -#################### -p_list_all_trunks = sp.add_parser("list_all_trunks", - help="List all the existing trunks in the system") -p_list_all_trunks.set_defaults(which = "list_all_trunks") -p_create_trunk = sp.add_parser("create_trunk", - help = "Add a new trunk to the system, linking two ports") -p_create_trunk.set_defaults(which = "create_trunk") -p_create_trunk.add_argument('--port_id1', - required = True, - help="The ID of the first port to be used") -p_create_trunk.add_argument('--port_id2', - required = True, - help="The ID of the second port to be used") -p_delete_trunk = sp.add_parser("delete_trunk", - help = "Remove an existing trunk from the system") -p_delete_trunk.set_defaults(which = "delete_trunk") -p_delete_trunk.add_argument('--trunk_id', - required = True, - help = "The ID of the trunk to remove") -p_show_trunk = sp.add_parser("show_trunk", - help = "Show the details of an existing trunk in the system") -p_show_trunk.set_defaults(which = "show_trunk") -p_show_trunk.add_argument('--trunk_id', - required = True, - help = "The ID of the trunk to show") - -args = parser.parse_args() - -# Now work out what to do -if args.which == 'status': - try: - print 'Config:' - print ' knows about %d switch(es)' % len(config.switches) - default_vlan_id = call_vland('db_query', - {'command':'db.get_vlan_id_by_tag', - 'data': - {'tag': config.vland.default_vlan_tag}}) - print 'The default vlan tag (%d) is vlan ID %d' % (config.vland.default_vlan_tag, default_vlan_id) - stat = call_vland('daemon_query', {'command':'daemon.status', 'data': None}) - print 'VLANd is running %s' % stat['running'] - lastmod = datetime.datetime.strptime(stat['last_modified'], '%Y-%m-%dT%H:%M:%S.%f') - print 'DB Last modified %s' % lastmod.strftime('%Y-%m-%d %H:%M:%S %Z') - print 'DB via VLANd:' - switches = call_vland('db_query', {'command':'db.all_switches', 'data':None}) - print ' knows about %d switch(es)' % len(switches) - ports = call_vland('db_query', {'command':'db.all_ports', 'data':None}) - print ' knows about %d port(s)' % len(ports) - vlans = call_vland('db_query', {'command':'db.all_vlans', 'data':None}) - print ' DB knows about %d vlan(s)' % len(vlans) - except (InputError, NotFoundError): - exitcode = Error.FAILED -elif args.which == 'shutdown': - try: - print 'Asking VLANd to shutdown' - shutdown = call_vland('daemon_query', - {'command':'daemon.shutdown', - 'data': None}) - for field in shutdown: - print '%s: %s' % (field, shutdown[field]) - except (InputError, NotFoundError): - exitcode = Error.FAILED -elif args.which == 'vland_version': - try: - ver = call_vland('daemon_query', {'command':'daemon.version', 'data': None}) - print 'VLANd version %s' % ver['version'] - except (InputError, NotFoundError): - exitcode = Error.FAILED -elif args.which == 'statistics': - try: - stats = call_vland('daemon_query', {'command':'daemon.statistics', 'data': None}) - print 'VLANd uptime: %d seconds' % stats['uptime'] - except (InputError, NotFoundError): - exitcode = Error.FAILED -elif args.which == 'version': - print 'VLANd admin interface version %s' % version -elif args.which == 'auto_import_switch': - print 'Attempting to import switch %s' % args.name - if args.name not in config.switches: - raise InputError("Can't find switch %s in config" % args.name) - try: - imp = call_vland('vlan_update', - {'command':'api.auto_import_switch', - 'data': - {'switch': args.name}}) - print 'VLANd imported switch %s successfully: new switch_id %d, %d new ports, %d new VLANs' % (args.name, imp['switch_id'], imp['num_ports_added'], imp['num_vlans_added']) - except (InputError, NotFoundError): - print 'Import failed - see log for details' - exitcode = Error.FAILED -elif args.which == 'probe_switches': - print 'Asking VLANd to probe all the configured switches' - try: - probe = call_vland('daemon_query', - {'command':'daemon.probe_switches', - 'data': None}) - for field in probe: - print '%s: %s' % (field, probe[field]) - except (InputError, NotFoundError): - print 'Probe failed - see log for details' - exitcode = Error.FAILED -elif args.which == 'list_all_switches': - try: - result = call_vland('db_query', {'command':'db.all_switches', 'data':None}) - for line in result: - dump_switch(line) - except (InputError, NotFoundError): - exitcode = Error.FAILED -elif args.which == 'list_all_ports': - try: - result = call_vland('db_query', {'command':'db.all_ports', 'data':None}) - for line in result: - dump_port(line) - except (InputError, NotFoundError): - exitcode = Error.FAILED -elif args.which == 'list_all_vlans': - try: - result = call_vland('db_query', {'command':'db.all_vlans', 'data':None}) - for line in result: - dump_vlan(line) - except (InputError, NotFoundError): - exitcode = Error.FAILED -elif args.which == 'list_all_trunks': - try: - result = call_vland('db_query', {'command':'db.all_trunks', 'data':None}) - for line in result: - dump_trunk(line) - except (InputError, NotFoundError): - exitcode = Error.FAILED -elif args.which == 'create_switch': - try: - switch_id = call_vland('db_update', - {'command':'db.create_switch', - 'data': - {'name':args.name}}) - print 'Created switch_id %d' % switch_id - except InputError as inst: - print 'Failed: %s' % inst - exitcode = Error.FAILED -elif args.which == 'create_port': - try: - port_id = call_vland('db_update', - {'command':'db.create_port', - 'data': - {'switch_id': args.switch_id, - 'name': args.name, - 'number': args.number}}) - print 'Created port_id %d' % port_id - except InputError as inst: - print 'Failed: %s' % inst - exitcode = Error.FAILED - except NotFoundError as inst: - print 'Failed: %s' % inst - exitcode = Error.NOTFOUND -elif args.which == 'create_vlan': - try: - (vlan_id, vlan_tag) = call_vland('vlan_update', - {'command':'api.create_vlan', - 'data': - {'name': args.name, - 'tag': args.tag, - 'is_base_vlan': is_positive(args.is_base_vlan)}}) - print 'Created VLAN tag %d as vlan_id %d' % (vlan_tag, vlan_id) - except InputError as inst: - print 'Failed: %s' % inst - exitcode = Error.FAILED - except NotFoundError as inst: - print 'Failed: %s' % inst - exitcode = Error.NOTFOUND -elif args.which == 'create_trunk': - try: - trunk_id = call_vland('db_update', - {'command':'db.create_trunk', - 'data': - {'port_id1': args.port_id1, - 'port_id2': args.port_id2}}) - print 'Created trunk_id %d' % trunk_id - except InputError as inst: - print 'Failed: %s' % inst - exitcode = Error.FAILED - except NotFoundError as inst: - print 'Failed: %s' % inst - exitcode = Error.NOTFOUND -elif args.which == 'delete_switch': - try: - switch_id = call_vland('db_update', - {'command':'db.delete_switch', - 'data': {'switch_id': args.switch_id}}) - print 'Deleted switch_id %s' % switch_id - except InputError as inst: - print 'Failed: %s' % inst - exitcode = Error.FAILED - except NotFoundError as inst: - print 'Failed: %s' % inst - exitcode = Error.NOTFOUND -elif args.which == 'delete_port': - try: - port_id = call_vland('db_update', - {'command':'db.delete_port', - 'data': {'port_id': args.port_id}}) - print 'Deleted port_id %s' % port_id - except InputError as inst: - print 'Failed: %s' % inst - exitcode = Error.FAILED - except NotFoundError as inst: - print 'Failed: %s' % inst - exitcode = Error.NOTFOUND -elif args.which == 'delete_vlan': - try: - vlan_id = call_vland('vlan_update', - {'command':'api.delete_vlan', - 'data': {'vlan_id': args.vlan_id}}) - print 'Deleted vlan_id %d' % vlan_id - except InputError as inst: - print 'Failed: %s' % inst - exitcode = Error.FAILED - except NotFoundError as inst: - print 'Failed: %s' % inst - exitcode = Error.NOTFOUND -elif args.which == 'delete_trunk': - try: - trunk_id = call_vland('db_update', - {'command':'db.delete_trunk', - 'data': {'trunk_id': args.trunk_id}}) - print 'Deleted trunk_id %s' % trunk_id - except InputError as inst: - print 'Failed: %s' % inst - exitcode = Error.FAILED - except NotFoundError as inst: - print 'Failed: %s' % inst - exitcode = Error.NOTFOUND -elif args.which == 'lookup_switch_by_name': - try: - switch_id = call_vland('db_query', - {'command':'db.get_switch_id_by_name', - 'data':{'name':args.name}}) - if switch_id is not None: - print '%d' % switch_id - else: - print 'No switch found for name %s' % args.name - exitcode = Error.NOTFOUND - except InputError as inst: - print 'Failed: %s' % inst - exitcode = Error.FAILED -elif args.which == 'show_switch': - try: - this_switch = call_vland('db_query', - {'command':'db.get_switch_by_id', - 'data': - {'switch_id': args.switch_id}}) - if this_switch is not None: - dump_switch(this_switch) - else: - print 'No switch found for switch_id %s' % args.switch_id - except InputError as inst: - print 'Failed: %s' % inst - exitcode = Error.FAILED -elif args.which == 'show_port': - try: - this_port = call_vland('db_query', - {'command':'db.get_port_by_id', - 'data': - {'port_id': args.port_id}}) - if this_port is not None: - dump_port(this_port) - else: - print 'No port found for port_id %s' % args.port_id - exitcode = Error.NOTFOUND - except InputError as inst: - print 'Failed: %s' % inst - exitcode = Error.FAILED -elif args.which == 'lookup_port_by_switch_and_name': - try: - p = call_vland('db_query', - {'command':'db.get_port_by_switch_and_name', - 'data': - {'switch_id': args.switch_id, - 'name': args.name}}) - if p is not None: - print p - else: - print 'No port found for switch_id %s, name %s' % (args.switch_id, args.name) - exitcode = Error.NOTFOUND - except InputError as inst: - print 'Failed: %s' % inst -elif args.which == 'lookup_port_by_switch_and_number': - try: - p = call_vland('db_query', - {'command':'db.get_port_by_switch_and_number', - 'data': - {'switch_id': args.switch_id, - 'number': args.number}}) - if p is not None: - print p - else: - print 'No port found for switch_id %s, port number %s' % (args.switch_id, args.number) - except InputError as inst: - print 'Failed: %s' % inst - exitcode = Error.FAILED -elif args.which == 'lookup_ports_by_switch': - try: - p = call_vland('db_query', - {'command':'db.get_ports_by_switch', - 'data': - {'switch_id': args.switch_id}}) - if p is not None: - for port_id in p: - print port_id - else: - print 'No ports found for switch_id %s' % args.switch_id - exitcode = Error.NOTFOUND - except InputError as inst: - print 'Failed: %s' % inst - exitcode = Error.FAILED -elif args.which == 'lookup_ports_by_current_vlan': - try: - p = call_vland('db_query', - {'command':'db.get_ports_by_current_vlan', - 'data': - {'vlan_id': args.vlan_id}}) - if p is not None: - for port_id in p: - print port_id - else: - print 'No ports found for current vlan_id %s' % args.vlan_id - exitcode = Error.NOTFOUND - except InputError as inst: - print 'Failed: %s' % inst - exitcode = Error.FAILED -elif args.which == 'lookup_ports_by_base_vlan': - try: - p = call_vland('db_query', - {'command':'db.get_ports_by_base_vlan', - 'data': - {'vlan_id': args.vlan_id}}) - if p is not None: - for port_id in p: - print port_id - else: - print 'No ports found for base vlan_id %s' % args.vlan_id - exitcode = Error.NOTFOUND - except InputError as inst: - print 'Failed: %s' % inst - exitcode = Error.FAILED -elif args.which == 'lookup_ports_by_trunk': - try: - p = call_vland('db_query', - {'command':'db.get_ports_by_trunk', - 'data': - {'trunk_id': args.trunk_id}}) - if p is not None: - for port_id in p: - print port_id - else: - print 'No ports found for trunk_id %s' % args.trunk_id - exitcode = Error.NOTFOUND - except InputError as inst: - print 'Failed: %s' % inst - exitcode = Error.FAILED -elif args.which == 'set_port_mode': - try: - port_id = call_vland('vlan_update', - {'command':'api.set_port_mode', - 'data': - {'port_id': args.port_id, - 'mode': args.mode}}) - print "Updated mode for port_id %d" % port_id - except InputError as inst: - print 'Failed: %s' % inst - exitcode = Error.FAILED - except NotFoundError as inst: - print 'Failed: %s' % inst - exitcode = Error.NOTFOUND -elif args.which == 'lock_port': - try: - port_id = call_vland('db_update', - {'command':'db.set_port_is_locked', - 'data': - {'port_id': args.port_id, - 'is_locked': True, - 'lock_reason': args.reason}}) - print "Locked port_id %d" % port_id - except InputError as inst: - print 'Failed: %s' % inst - exitcode = Error.FAILED - except NotFoundError as inst: - print 'Failed: %s' % inst - exitcode = Error.NOTFOUND -elif args.which == 'unlock_port': - try: - port_id = call_vland('db_update', - {'command':'db.set_port_is_locked', - 'data': - {'port_id': args.port_id, - 'is_locked': False, - 'lock_reason': ""}}) - print "Unlocked port_id %d" % port_id - except InputError as inst: - print 'Failed: %s' % inst - exitcode = Error.FAILED - except NotFoundError as inst: - print 'Failed: %s' % inst - exitcode = Error.NOTFOUND -elif args.which == 'set_port_current_vlan': - try: - port_id = call_vland('vlan_update', - {'command':'api.set_current_vlan', - 'data': - {'port_id': args.port_id, - 'vlan_id': args.vlan_id}}) - print "Set current VLAN on port_id %d" % port_id - except InputError as inst: - print 'Failed: %s' % inst - exitcode = Error.FAILED - except NotFoundError as inst: - print 'Failed: %s' % inst - exitcode = Error.NOTFOUND -elif args.which == 'get_port_current_vlan': - try: - vlan_id = call_vland('db_query', - {'command':'db.get_current_vlan_id_by_port', - 'data': - {'port_id': args.port_id}}) - if vlan_id is not None: - print vlan_id - else: - print "No current_vlan_id found for port_id %s" % args.port_id - except InputError as inst: - print 'Failed: %s' % inst - exitcode = Error.FAILED - except NotFoundError as inst: - print 'Failed: %s' % inst - exitcode = Error.NOTFOUND -elif args.which == 'set_port_base_vlan': - try: - port_id = call_vland('db_update', - {'command':'db.set_base_vlan', - 'data': - {'port_id': args.port_id, - 'base_vlan_id': args.vlan_id}}) - print "Set base VLAN on port_id %d" % port_id - except InputError as inst: - print 'Failed: %s' % inst - exitcode = Error.FAILED - except NotFoundError as inst: - print 'Failed: %s' % inst - exitcode = Error.NOTFOUND -elif args.which == 'get_port_base_vlan': - try: - vlan_id = call_vland('db_query', - {'command':'db.get_base_vlan_id_by_port', - 'data': - {'port_id': args.port_id}}) - if vlan_id is not None: - print vlan_id - else: - print "No base_vlan_id found for port_id %d" % port_id - except InputError as inst: - print 'Failed: %s' % inst - exitcode = Error.FAILED - except NotFoundError as inst: - print 'Failed: %s' % inst - exitcode = Error.NOTFOUND -elif args.which == 'restore_port_to_base_vlan': - try: - port_id = call_vland('vlan_update', - {'command': 'api.restore_base_vlan', - 'data': - {'port_id': args.port_id}}) - print "Restored port_id %d back to base VLAN" % port_id - except InputError as inst: - print 'Failed: %s' % inst - exitcode = Error.FAILED - except NotFoundError as inst: - print 'Failed: %s' % inst - exitcode = Error.NOTFOUND -elif args.which == 'show_vlan': - try: - v = call_vland('db_query', - {'command':'db.get_vlan_by_id', - 'data': - {'vlan_id': args.vlan_id}}) - if v is not None: - dump_vlan(v) - else: - print 'No VLAN found for vlan_id %s' % args.vlan_id - except InputError as inst: - print 'Failed: %s' % inst - exitcode = Error.FAILED - except NotFoundError as inst: - print 'Failed: %s' % inst - exitcode = Error.NOTFOUND -elif args.which == 'lookup_vlan_by_tag': - try: - vlan_id = call_vland('db_query', - {'command':'db.get_vlan_id_by_tag', - 'data': - {'tag': args.tag}}) - if vlan_id is not None: - print vlan_id - else: - print 'No VLAN found for vlan tag %s' % args.tag - exitcode = Error.NOTFOUND - except InputError as inst: - print 'Failed: %s' % inst - exitcode = Error.FAILED -elif args.which == 'show_vlan_tag': - try: - vlan_tag = call_vland('db_query', - {'command':'db.get_vlan_tag_by_id', - 'data': - {'vlan_id': args.vlan_id}}) - if vlan_tag is not None: - print vlan_tag - else: - print 'No VLAN found for vlan id %s' % args.vlan_id - exitcode = Error.NOTFOUND - except InputError as inst: - print 'Failed: %s' % inst - exitcode = Error.FAILED -elif args.which == 'show_trunk': - try: - this_trunk = call_vland('db_query', - {'command':'db.get_trunk_by_id', - 'data': - {'trunk_id': args.trunk_id}}) - if this_trunk is not None: - dump_trunk(this_trunk) - else: - print 'No port found for port_id %s' % args.trunk_id - except InputError as inst: - print 'Failed: %s' % inst - print 'Failed: %s' % inst - exitcode = Error.FAILED - except NotFoundError as inst: - print 'Failed: %s' % inst - exitcode = Error.NOTFOUND -else: - print 'No recognised command given. Try -h for help' - -sys.exit(exitcode) diff --git a/test/test-common b/test/test-common index ddc7986..cdc50d3 100755 --- a/test/test-common +++ b/test/test-common @@ -70,7 +70,7 @@ vvlog () { # Run a vland admin command, and optionally log both the full text of # the command and its output run_admin_command () { - ADMIN="python $TOPDIR/admin.py" + ADMIN="python $TOPDIR/vland-admin" vlog "Running \"$ADMIN $@\"" LAST_COMMAND="$@" RESULT=$($ADMIN $@) diff --git a/vland-admin b/vland-admin new file mode 100755 index 0000000..96a7cfc --- /dev/null +++ b/vland-admin @@ -0,0 +1,882 @@ +#! /usr/bin/python + +# Copyright 2014-2018 Linaro Limited +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301, USA. +# +# VLANd admin interface +# + +import os, sys +import argparse +import datetime, time + +vlandpath = os.path.abspath(os.path.normpath(os.path.dirname(sys.argv[0]))) +sys.path.insert(0, vlandpath) + +from errors import InputError, SocketError, NotFoundError, Error +from config.config import VlanConfig +from ipc.ipc import VlanIpc + +prog = "vland-admin" +version = "0.7" +banner = "Linaro VLANd admin interface, version %s" % version +exitcode = Error.OK +TRUNK_ID_NONE = -1 + +def is_positive(text): + if text in ('1', 'y', 'Y', 't', 'T', 'True', 'true'): + return True + elif text in ('0', 'n', 'N', 'f', 'F', 'False', 'false'): + return False + else: + raise InputError("Cannot parse \"%s\" as True or False" % text) + +def dump_switch(switch): + print "switch_id:%d name:%s" % ( + int(switch['switch_id']), + switch['name']) + +def dump_port(port): + print "port_id:%d name:%s switch_id:%d locked:%s mode:%s base_vlan_id:%d current_vlan_id:%d number:%d trunk_id:%s lock_reason:%s" % ( + int(port['port_id']), + port['name'], + int(port['switch_id']), + ("yes" if port['is_locked'] is True else "no"), + ("trunk" if port['is_trunk'] is True else "access"), + int(port['base_vlan_id']), + int(port['current_vlan_id']), + int(port['number']), + 'None' if (TRUNK_ID_NONE == port['trunk_id']) else port['trunk_id'], + port['lock_reason']) + +def dump_vlan(vlan): + print "vlan_id:%d name:%s tag:%d is_base_vlan:%s, creation_time:%s" % ( + int(vlan['vlan_id']), + vlan['name'], + int(vlan['tag']), + ("yes" if vlan['is_base_vlan'] is True else "no"), + vlan['creation_time']) + +def dump_trunk(trunk): + print "trunk_id:%d creation_time:%s" % ( + int(trunk['trunk_id']), + trunk['creation_time']) + +def call_vland(msgtype, msg): + ipc = VlanIpc() + ipc.client_connect('localhost', config.vland.port) + msg['client_name'] = 'vland-admin' + msg['type'] = msgtype + ipc.client_send(msg) + ret = ipc.client_recv_and_close() + if 'response' not in ret: + raise SocketError("Badly-formed response from VLANd server") + if ret['response'] == "ERROR": + raise InputError("VLANd server said \"%s\"" % ret['error']) + if ret['response'] == "NOTFOUND": + raise NotFoundError("VLANd server said \"%s\"" % ret['error']) + return ret['data'] + +config = VlanConfig(filenames=('./vland.cfg',)) + +parser = argparse.ArgumentParser() + +#################### +# System commands +#################### +sp = parser.add_subparsers(title='Sub-commands', + help="Commands", + dest='subparser_name') +p_status = sp.add_parser("status", + help="Describe current system status") +p_status.set_defaults(which = "status") +p_statistics = sp.add_parser("statistics", + help="Print some system statistics") +p_statistics.set_defaults(which = "statistics") +p_version = sp.add_parser("version", + help="Describe the version of this admin interface") +p_version.set_defaults(which = "version") +p_vland_version = sp.add_parser("vland_version", + help="Describe the version of the running VLANd") +p_vland_version.set_defaults(which = "vland_version") +p_probe_switches = sp.add_parser("probe_switches", + help="Probe all the configured switches") +p_probe_switches.set_defaults(which = "probe_switches") +p_auto_import = sp.add_parser("auto_import_switch", + help="Attempt to import a switch's configuration into the VLANd system") +p_auto_import.add_argument('--name', + required = True, + help="Import the switch named SWITCH_NAME in vland.cfg") +p_auto_import.set_defaults(which = "auto_import_switch") +p_shutdown = sp.add_parser("shutdown", + help="Shut down a running VLANd") +p_shutdown.set_defaults(which = "shutdown") + +#################### +# Switch commands +#################### +p_list_all_switches = sp.add_parser("list_all_switches", + help="List all the existing switches in the system") +p_list_all_switches.set_defaults(which = "list_all_switches") +p_create_switch = sp.add_parser("create_switch", + help = "Add a new switch to the system") +p_create_switch.set_defaults(which = "create_switch") +p_create_switch.add_argument('--name', + required = True, + help="The name of the new switch, as described in vland.cfg") +p_delete_switch = sp.add_parser("delete_switch", + help = "Remove an existing switch from the system") +p_delete_switch.set_defaults(which = "delete_switch") +p_delete_switch.add_argument('--switch_id', + required = True, + help = "The ID of the switch to remove") +p_show_switch = sp.add_parser("show_switch", + help = "Show the details of an existing switch in the system") +p_show_switch.set_defaults(which = "show_switch") +p_show_switch.add_argument('--switch_id', + required = True, + help = "The ID of the switch to show") +p_lookup_switch_by_name = sp.add_parser("lookup_switch_by_name", + help = "Lookup a switch ID by name") +p_lookup_switch_by_name.set_defaults(which = "lookup_switch_by_name") +p_lookup_switch_by_name.add_argument('--name', + required = True, + help = "The switch name to search for") + +#################### +# Ports commands +#################### +p_list_all_ports = sp.add_parser("list_all_ports", + help="List all the existing ports in the system") +p_list_all_ports.set_defaults(which = "list_all_ports") +p_create_port = sp.add_parser("create_port", + help = "Add a new port to the system") +p_create_port.set_defaults(which = "create_port") +p_create_port.add_argument('--switch_id', + required = True, + help="The ID of the switch containing the new port") +p_create_port.add_argument('--name', + required = True, + help="The name of the new port") +p_create_port.add_argument('--number', + required = True, + help="The human-friendly number for the new port") +p_delete_port = sp.add_parser("delete_port", + help = "Remove an existing port from the system") +p_delete_port.set_defaults(which = "delete_port") +p_delete_port.add_argument('--port_id', + required = True, + help = "The ID of the port to remove") +p_show_port = sp.add_parser("show_port", + help = "Show the details of an existing port in the system") +p_show_port.set_defaults(which = "show_port") +p_show_port.add_argument('--port_id', + required = True, + help = "The ID of the port to show") +p_lookup_port_by_switch_and_name = sp.add_parser("lookup_port_by_switch_and_name", + help = "Lookup a port ID by switch ID and port name") +p_lookup_port_by_switch_and_name.set_defaults(which = "lookup_port_by_switch_and_name") +p_lookup_port_by_switch_and_name.add_argument('--switch_id', + required = True, + help = "The switch ID to search for") +p_lookup_port_by_switch_and_name.add_argument('--name', + required = True, + help = "The port name to search for") +p_lookup_port_by_switch_and_number = sp.add_parser("lookup_port_by_switch_and_number", + help = "Lookup a port ID by switch ID and port number") +p_lookup_port_by_switch_and_number.set_defaults(which = "lookup_port_by_switch_and_number") +p_lookup_port_by_switch_and_number.add_argument('--switch_id', + required = True, + help = "The switch ID to search for") +p_lookup_port_by_switch_and_number.add_argument('--number', + required = True, + help = "The port number to search for") +p_lookup_ports_by_switch = sp.add_parser("lookup_ports_by_switch", + help = "Lookup port ID(s) by switch ID") +p_lookup_ports_by_switch.set_defaults(which = "lookup_ports_by_switch") +p_lookup_ports_by_switch.add_argument('--switch_id', + required = True, + help = "The switch ID to search for") +p_lookup_ports_by_current_vlan = sp.add_parser("lookup_ports_by_current_vlan", + help = "Lookup port ID(s) by current VLAN ID") +p_lookup_ports_by_current_vlan.set_defaults(which = "lookup_ports_by_current_vlan") +p_lookup_ports_by_current_vlan.add_argument('--vlan_id', + required = True, + help = "The VLAN ID to search for") +p_lookup_ports_by_base_vlan = sp.add_parser("lookup_ports_by_base_vlan", + help = "Lookup port ID(s) by base vlan ID") +p_lookup_ports_by_base_vlan.set_defaults(which = "lookup_ports_by_base_vlan") +p_lookup_ports_by_base_vlan.add_argument('--vlan_id', + required = True, + help = "The VLAN ID to search for") +p_lookup_ports_by_trunk = sp.add_parser("lookup_ports_by_trunk", + help = "Lookup port ID(s) by trunk ID") +p_lookup_ports_by_trunk.set_defaults(which = "lookup_ports_by_trunk") +p_lookup_ports_by_trunk.add_argument('--trunk_id', + required = True, + help = "The trunk ID to search for") +p_set_port_mode = sp.add_parser("set_port_mode", + help = "Set the mode of a port to 'trunk' or 'access'") +p_set_port_mode.set_defaults(which = "set_port_mode") +p_set_port_mode.add_argument('--port_id', + required = True, + help = "The ID of the port to modify") +p_set_port_mode.add_argument('--mode', + required = True, + help = "The mode to select ('trunk' or 'access')") +p_get_port_mode = sp.add_parser("get_port_mode", + help = "Get the mode of a port ('trunk' or 'access')") +p_get_port_mode.set_defaults(which = "get_port_mode") +p_get_port_mode.add_argument('--port_id', + required = True, + help = "The ID of the port to query") +p_lock_port = sp.add_parser("lock_port", + help = "Lock the settings on a port") +p_lock_port.set_defaults(which = "lock_port") +p_lock_port.add_argument('--port_id', + required = True, + help = "The ID of the port to lock") +p_lock_port.add_argument('--reason', + required = False, + help = "(Optional) The reason for locking the port") +p_unlock_port = sp.add_parser("unlock_port", + help = "Unlock the settings on a port") +p_unlock_port.set_defaults(which = "unlock_port") +p_unlock_port.add_argument('--port_id', + required = True, + help = "The ID of the port to unlock") +p_set_port_current_vlan = sp.add_parser("set_port_current_vlan", + help = "Set the current VLAN assignment for a port") +p_set_port_current_vlan.set_defaults(which = "set_port_current_vlan") +p_set_port_current_vlan.add_argument('--port_id', + required = True, + help = "The ID of the port to modify") +p_set_port_current_vlan.add_argument('--vlan_id', + required = True, + help = "The VLAN ID to be used") +p_get_port_current_vlan = sp.add_parser("get_port_current_vlan", + help = "Get the current VLAN assignment for a port") +p_get_port_current_vlan.set_defaults(which = "get_port_current_vlan") +p_get_port_current_vlan.add_argument('--port_id', + required = True, + help = "The ID of the port to query") +p_set_port_base_vlan = sp.add_parser("set_port_base_vlan", + help = "Set the base VLAN assignment for a port") +p_set_port_base_vlan.set_defaults(which = "set_port_base_vlan") +p_set_port_base_vlan.add_argument('--port_id', + required = True, + help = "The ID of the port to modify") +p_set_port_base_vlan.add_argument('--vlan_id', + required = True, + help = "The VLAN ID to be used") +p_get_port_base_vlan = sp.add_parser("get_port_base_vlan", + help = "Get the base VLAN assignment for a port") +p_get_port_base_vlan.set_defaults(which = "get_port_base_vlan") +p_get_port_base_vlan.add_argument('--port_id', + required = True, + help = "The ID of the port to query") +p_restore_port_to_base_vlan = sp.add_parser("restore_port_to_base_vlan", + help = "Reset a port back to its base VLAN") +p_restore_port_to_base_vlan.set_defaults(which = "restore_port_to_base_vlan") +p_restore_port_to_base_vlan.add_argument('--port_id', + required = True, + help = "The ID of the port to modify") + +#################### +# VLAN commands +#################### +p_list_all_vlans = sp.add_parser("list_all_vlans", + help="List all the existing VLANs in the system") +p_list_all_vlans.set_defaults(which = "list_all_vlans") +p_create_vlan = sp.add_parser("create_vlan", + help = "Add a new VLAN to the system") +p_create_vlan.set_defaults(which = "create_vlan") +p_create_vlan.add_argument('--name', + required = True, + help="The name of the new VLAN") +p_create_vlan.add_argument('--tag', + required = True, + help="The tag for the new VLAN (-1 to automatically select)") +p_create_vlan.add_argument('--is_base_vlan', + required = True, + help="Is the new VLAN a base VLAN (true/false)") +p_delete_vlan = sp.add_parser("delete_vlan", + help = "Remove an existing VLAN from the system") +p_delete_vlan.set_defaults(which = "delete_vlan") +p_delete_vlan.add_argument('--vlan_id', + required = True, + help = "The ID of the VLAN to remove") +p_show_vlan = sp.add_parser("show_vlan", + help = "Show the details of an existing VLAN in the system") +p_show_vlan.set_defaults(which = "show_vlan") +p_show_vlan.add_argument('--vlan_id', + required = True, + help = "The ID of the VLAN to show") +p_lookup_vlan_by_tag = sp.add_parser("lookup_vlan_by_tag", + help = "Find the VLAN ID of an existing VLAN in the system") +p_lookup_vlan_by_tag.set_defaults(which = "lookup_vlan_by_tag") +p_lookup_vlan_by_tag.add_argument('--tag', + required = True, + help = "The VLAN tag to search for") +p_show_vlan_tag = sp.add_parser("show_vlan_tag", + help = "Print the VLAN tag of an existing VLAN in the system") +p_show_vlan_tag.set_defaults(which = "show_vlan_tag") +p_show_vlan_tag.add_argument('--vlan_id', + required = True, + help = "The VLAN ID to search for") + +#################### +# Trunk commands +#################### +p_list_all_trunks = sp.add_parser("list_all_trunks", + help="List all the existing trunks in the system") +p_list_all_trunks.set_defaults(which = "list_all_trunks") +p_create_trunk = sp.add_parser("create_trunk", + help = "Add a new trunk to the system, linking two ports") +p_create_trunk.set_defaults(which = "create_trunk") +p_create_trunk.add_argument('--port_id1', + required = True, + help="The ID of the first port to be used") +p_create_trunk.add_argument('--port_id2', + required = True, + help="The ID of the second port to be used") +p_delete_trunk = sp.add_parser("delete_trunk", + help = "Remove an existing trunk from the system") +p_delete_trunk.set_defaults(which = "delete_trunk") +p_delete_trunk.add_argument('--trunk_id', + required = True, + help = "The ID of the trunk to remove") +p_show_trunk = sp.add_parser("show_trunk", + help = "Show the details of an existing trunk in the system") +p_show_trunk.set_defaults(which = "show_trunk") +p_show_trunk.add_argument('--trunk_id', + required = True, + help = "The ID of the trunk to show") + +args = parser.parse_args() + +# Now work out what to do +if args.which == 'status': + try: + print 'Config:' + print ' knows about %d switch(es)' % len(config.switches) + default_vlan_id = call_vland('db_query', + {'command':'db.get_vlan_id_by_tag', + 'data': + {'tag': config.vland.default_vlan_tag}}) + print 'The default vlan tag (%d) is vlan ID %d' % (config.vland.default_vlan_tag, default_vlan_id) + stat = call_vland('daemon_query', {'command':'daemon.status', 'data': None}) + print 'VLANd is running %s' % stat['running'] + lastmod = datetime.datetime.strptime(stat['last_modified'], '%Y-%m-%dT%H:%M:%S.%f') + print 'DB Last modified %s' % lastmod.strftime('%Y-%m-%d %H:%M:%S %Z') + print 'DB via VLANd:' + switches = call_vland('db_query', {'command':'db.all_switches', 'data':None}) + print ' knows about %d switch(es)' % len(switches) + ports = call_vland('db_query', {'command':'db.all_ports', 'data':None}) + print ' knows about %d port(s)' % len(ports) + vlans = call_vland('db_query', {'command':'db.all_vlans', 'data':None}) + print ' DB knows about %d vlan(s)' % len(vlans) + except (InputError, NotFoundError): + exitcode = Error.FAILED +elif args.which == 'shutdown': + try: + print 'Asking VLANd to shutdown' + shutdown = call_vland('daemon_query', + {'command':'daemon.shutdown', + 'data': None}) + for field in shutdown: + print '%s: %s' % (field, shutdown[field]) + except (InputError, NotFoundError): + exitcode = Error.FAILED +elif args.which == 'vland_version': + try: + ver = call_vland('daemon_query', {'command':'daemon.version', 'data': None}) + print 'VLANd version %s' % ver['version'] + except (InputError, NotFoundError): + exitcode = Error.FAILED +elif args.which == 'statistics': + try: + stats = call_vland('daemon_query', {'command':'daemon.statistics', 'data': None}) + print 'VLANd uptime: %d seconds' % stats['uptime'] + except (InputError, NotFoundError): + exitcode = Error.FAILED +elif args.which == 'version': + print 'VLANd admin interface version %s' % version +elif args.which == 'auto_import_switch': + print 'Attempting to import switch %s' % args.name + if args.name not in config.switches: + raise InputError("Can't find switch %s in config" % args.name) + try: + imp = call_vland('vlan_update', + {'command':'api.auto_import_switch', + 'data': + {'switch': args.name}}) + print 'VLANd imported switch %s successfully: new switch_id %d, %d new ports, %d new VLANs' % (args.name, imp['switch_id'], imp['num_ports_added'], imp['num_vlans_added']) + except (InputError, NotFoundError): + print 'Import failed - see log for details' + exitcode = Error.FAILED +elif args.which == 'probe_switches': + print 'Asking VLANd to probe all the configured switches' + try: + probe = call_vland('daemon_query', + {'command':'daemon.probe_switches', + 'data': None}) + for field in probe: + print '%s: %s' % (field, probe[field]) + except (InputError, NotFoundError): + print 'Probe failed - see log for details' + exitcode = Error.FAILED +elif args.which == 'list_all_switches': + try: + result = call_vland('db_query', {'command':'db.all_switches', 'data':None}) + for line in result: + dump_switch(line) + except (InputError, NotFoundError): + exitcode = Error.FAILED +elif args.which == 'list_all_ports': + try: + result = call_vland('db_query', {'command':'db.all_ports', 'data':None}) + for line in result: + dump_port(line) + except (InputError, NotFoundError): + exitcode = Error.FAILED +elif args.which == 'list_all_vlans': + try: + result = call_vland('db_query', {'command':'db.all_vlans', 'data':None}) + for line in result: + dump_vlan(line) + except (InputError, NotFoundError): + exitcode = Error.FAILED +elif args.which == 'list_all_trunks': + try: + result = call_vland('db_query', {'command':'db.all_trunks', 'data':None}) + for line in result: + dump_trunk(line) + except (InputError, NotFoundError): + exitcode = Error.FAILED +elif args.which == 'create_switch': + try: + switch_id = call_vland('db_update', + {'command':'db.create_switch', + 'data': + {'name':args.name}}) + print 'Created switch_id %d' % switch_id + except InputError as inst: + print 'Failed: %s' % inst + exitcode = Error.FAILED +elif args.which == 'create_port': + try: + port_id = call_vland('db_update', + {'command':'db.create_port', + 'data': + {'switch_id': args.switch_id, + 'name': args.name, + 'number': args.number}}) + print 'Created port_id %d' % port_id + except InputError as inst: + print 'Failed: %s' % inst + exitcode = Error.FAILED + except NotFoundError as inst: + print 'Failed: %s' % inst + exitcode = Error.NOTFOUND +elif args.which == 'create_vlan': + try: + (vlan_id, vlan_tag) = call_vland('vlan_update', + {'command':'api.create_vlan', + 'data': + {'name': args.name, + 'tag': args.tag, + 'is_base_vlan': is_positive(args.is_base_vlan)}}) + print 'Created VLAN tag %d as vlan_id %d' % (vlan_tag, vlan_id) + except InputError as inst: + print 'Failed: %s' % inst + exitcode = Error.FAILED + except NotFoundError as inst: + print 'Failed: %s' % inst + exitcode = Error.NOTFOUND +elif args.which == 'create_trunk': + try: + trunk_id = call_vland('db_update', + {'command':'db.create_trunk', + 'data': + {'port_id1': args.port_id1, + 'port_id2': args.port_id2}}) + print 'Created trunk_id %d' % trunk_id + except InputError as inst: + print 'Failed: %s' % inst + exitcode = Error.FAILED + except NotFoundError as inst: + print 'Failed: %s' % inst + exitcode = Error.NOTFOUND +elif args.which == 'delete_switch': + try: + switch_id = call_vland('db_update', + {'command':'db.delete_switch', + 'data': {'switch_id': args.switch_id}}) + print 'Deleted switch_id %s' % switch_id + except InputError as inst: + print 'Failed: %s' % inst + exitcode = Error.FAILED + except NotFoundError as inst: + print 'Failed: %s' % inst + exitcode = Error.NOTFOUND +elif args.which == 'delete_port': + try: + port_id = call_vland('db_update', + {'command':'db.delete_port', + 'data': {'port_id': args.port_id}}) + print 'Deleted port_id %s' % port_id + except InputError as inst: + print 'Failed: %s' % inst + exitcode = Error.FAILED + except NotFoundError as inst: + print 'Failed: %s' % inst + exitcode = Error.NOTFOUND +elif args.which == 'delete_vlan': + try: + vlan_id = call_vland('vlan_update', + {'command':'api.delete_vlan', + 'data': {'vlan_id': args.vlan_id}}) + print 'Deleted vlan_id %d' % vlan_id + except InputError as inst: + print 'Failed: %s' % inst + exitcode = Error.FAILED + except NotFoundError as inst: + print 'Failed: %s' % inst + exitcode = Error.NOTFOUND +elif args.which == 'delete_trunk': + try: + trunk_id = call_vland('db_update', + {'command':'db.delete_trunk', + 'data': {'trunk_id': args.trunk_id}}) + print 'Deleted trunk_id %s' % trunk_id + except InputError as inst: + print 'Failed: %s' % inst + exitcode = Error.FAILED + except NotFoundError as inst: + print 'Failed: %s' % inst + exitcode = Error.NOTFOUND +elif args.which == 'lookup_switch_by_name': + try: + switch_id = call_vland('db_query', + {'command':'db.get_switch_id_by_name', + 'data':{'name':args.name}}) + if switch_id is not None: + print '%d' % switch_id + else: + print 'No switch found for name %s' % args.name + exitcode = Error.NOTFOUND + except InputError as inst: + print 'Failed: %s' % inst + exitcode = Error.FAILED +elif args.which == 'show_switch': + try: + this_switch = call_vland('db_query', + {'command':'db.get_switch_by_id', + 'data': + {'switch_id': args.switch_id}}) + if this_switch is not None: + dump_switch(this_switch) + else: + print 'No switch found for switch_id %s' % args.switch_id + except InputError as inst: + print 'Failed: %s' % inst + exitcode = Error.FAILED +elif args.which == 'show_port': + try: + this_port = call_vland('db_query', + {'command':'db.get_port_by_id', + 'data': + {'port_id': args.port_id}}) + if this_port is not None: + dump_port(this_port) + else: + print 'No port found for port_id %s' % args.port_id + exitcode = Error.NOTFOUND + except InputError as inst: + print 'Failed: %s' % inst + exitcode = Error.FAILED +elif args.which == 'lookup_port_by_switch_and_name': + try: + p = call_vland('db_query', + {'command':'db.get_port_by_switch_and_name', + 'data': + {'switch_id': args.switch_id, + 'name': args.name}}) + if p is not None: + print p + else: + print 'No port found for switch_id %s, name %s' % (args.switch_id, args.name) + exitcode = Error.NOTFOUND + except InputError as inst: + print 'Failed: %s' % inst +elif args.which == 'lookup_port_by_switch_and_number': + try: + p = call_vland('db_query', + {'command':'db.get_port_by_switch_and_number', + 'data': + {'switch_id': args.switch_id, + 'number': args.number}}) + if p is not None: + print p + else: + print 'No port found for switch_id %s, port number %s' % (args.switch_id, args.number) + except InputError as inst: + print 'Failed: %s' % inst + exitcode = Error.FAILED +elif args.which == 'lookup_ports_by_switch': + try: + p = call_vland('db_query', + {'command':'db.get_ports_by_switch', + 'data': + {'switch_id': args.switch_id}}) + if p is not None: + for port_id in p: + print port_id + else: + print 'No ports found for switch_id %s' % args.switch_id + exitcode = Error.NOTFOUND + except InputError as inst: + print 'Failed: %s' % inst + exitcode = Error.FAILED +elif args.which == 'lookup_ports_by_current_vlan': + try: + p = call_vland('db_query', + {'command':'db.get_ports_by_current_vlan', + 'data': + {'vlan_id': args.vlan_id}}) + if p is not None: + for port_id in p: + print port_id + else: + print 'No ports found for current vlan_id %s' % args.vlan_id + exitcode = Error.NOTFOUND + except InputError as inst: + print 'Failed: %s' % inst + exitcode = Error.FAILED +elif args.which == 'lookup_ports_by_base_vlan': + try: + p = call_vland('db_query', + {'command':'db.get_ports_by_base_vlan', + 'data': + {'vlan_id': args.vlan_id}}) + if p is not None: + for port_id in p: + print port_id + else: + print 'No ports found for base vlan_id %s' % args.vlan_id + exitcode = Error.NOTFOUND + except InputError as inst: + print 'Failed: %s' % inst + exitcode = Error.FAILED +elif args.which == 'lookup_ports_by_trunk': + try: + p = call_vland('db_query', + {'command':'db.get_ports_by_trunk', + 'data': + {'trunk_id': args.trunk_id}}) + if p is not None: + for port_id in p: + print port_id + else: + print 'No ports found for trunk_id %s' % args.trunk_id + exitcode = Error.NOTFOUND + except InputError as inst: + print 'Failed: %s' % inst + exitcode = Error.FAILED +elif args.which == 'set_port_mode': + try: + port_id = call_vland('vlan_update', + {'command':'api.set_port_mode', + 'data': + {'port_id': args.port_id, + 'mode': args.mode}}) + print "Updated mode for port_id %d" % port_id + except InputError as inst: + print 'Failed: %s' % inst + exitcode = Error.FAILED + except NotFoundError as inst: + print 'Failed: %s' % inst + exitcode = Error.NOTFOUND +elif args.which == 'lock_port': + try: + port_id = call_vland('db_update', + {'command':'db.set_port_is_locked', + 'data': + {'port_id': args.port_id, + 'is_locked': True, + 'lock_reason': args.reason}}) + print "Locked port_id %d" % port_id + except InputError as inst: + print 'Failed: %s' % inst + exitcode = Error.FAILED + except NotFoundError as inst: + print 'Failed: %s' % inst + exitcode = Error.NOTFOUND +elif args.which == 'unlock_port': + try: + port_id = call_vland('db_update', + {'command':'db.set_port_is_locked', + 'data': + {'port_id': args.port_id, + 'is_locked': False, + 'lock_reason': ""}}) + print "Unlocked port_id %d" % port_id + except InputError as inst: + print 'Failed: %s' % inst + exitcode = Error.FAILED + except NotFoundError as inst: + print 'Failed: %s' % inst + exitcode = Error.NOTFOUND +elif args.which == 'set_port_current_vlan': + try: + port_id = call_vland('vlan_update', + {'command':'api.set_current_vlan', + 'data': + {'port_id': args.port_id, + 'vlan_id': args.vlan_id}}) + print "Set current VLAN on port_id %d" % port_id + except InputError as inst: + print 'Failed: %s' % inst + exitcode = Error.FAILED + except NotFoundError as inst: + print 'Failed: %s' % inst + exitcode = Error.NOTFOUND +elif args.which == 'get_port_current_vlan': + try: + vlan_id = call_vland('db_query', + {'command':'db.get_current_vlan_id_by_port', + 'data': + {'port_id': args.port_id}}) + if vlan_id is not None: + print vlan_id + else: + print "No current_vlan_id found for port_id %s" % args.port_id + except InputError as inst: + print 'Failed: %s' % inst + exitcode = Error.FAILED + except NotFoundError as inst: + print 'Failed: %s' % inst + exitcode = Error.NOTFOUND +elif args.which == 'set_port_base_vlan': + try: + port_id = call_vland('db_update', + {'command':'db.set_base_vlan', + 'data': + {'port_id': args.port_id, + 'base_vlan_id': args.vlan_id}}) + print "Set base VLAN on port_id %d" % port_id + except InputError as inst: + print 'Failed: %s' % inst + exitcode = Error.FAILED + except NotFoundError as inst: + print 'Failed: %s' % inst + exitcode = Error.NOTFOUND +elif args.which == 'get_port_base_vlan': + try: + vlan_id = call_vland('db_query', + {'command':'db.get_base_vlan_id_by_port', + 'data': + {'port_id': args.port_id}}) + if vlan_id is not None: + print vlan_id + else: + print "No base_vlan_id found for port_id %d" % port_id + except InputError as inst: + print 'Failed: %s' % inst + exitcode = Error.FAILED + except NotFoundError as inst: + print 'Failed: %s' % inst + exitcode = Error.NOTFOUND +elif args.which == 'restore_port_to_base_vlan': + try: + port_id = call_vland('vlan_update', + {'command': 'api.restore_base_vlan', + 'data': + {'port_id': args.port_id}}) + print "Restored port_id %d back to base VLAN" % port_id + except InputError as inst: + print 'Failed: %s' % inst + exitcode = Error.FAILED + except NotFoundError as inst: + print 'Failed: %s' % inst + exitcode = Error.NOTFOUND +elif args.which == 'show_vlan': + try: + v = call_vland('db_query', + {'command':'db.get_vlan_by_id', + 'data': + {'vlan_id': args.vlan_id}}) + if v is not None: + dump_vlan(v) + else: + print 'No VLAN found for vlan_id %s' % args.vlan_id + except InputError as inst: + print 'Failed: %s' % inst + exitcode = Error.FAILED + except NotFoundError as inst: + print 'Failed: %s' % inst + exitcode = Error.NOTFOUND +elif args.which == 'lookup_vlan_by_tag': + try: + vlan_id = call_vland('db_query', + {'command':'db.get_vlan_id_by_tag', + 'data': + {'tag': args.tag}}) + if vlan_id is not None: + print vlan_id + else: + print 'No VLAN found for vlan tag %s' % args.tag + exitcode = Error.NOTFOUND + except InputError as inst: + print 'Failed: %s' % inst + exitcode = Error.FAILED +elif args.which == 'show_vlan_tag': + try: + vlan_tag = call_vland('db_query', + {'command':'db.get_vlan_tag_by_id', + 'data': + {'vlan_id': args.vlan_id}}) + if vlan_tag is not None: + print vlan_tag + else: + print 'No VLAN found for vlan id %s' % args.vlan_id + exitcode = Error.NOTFOUND + except InputError as inst: + print 'Failed: %s' % inst + exitcode = Error.FAILED +elif args.which == 'show_trunk': + try: + this_trunk = call_vland('db_query', + {'command':'db.get_trunk_by_id', + 'data': + {'trunk_id': args.trunk_id}}) + if this_trunk is not None: + dump_trunk(this_trunk) + else: + print 'No port found for port_id %s' % args.trunk_id + except InputError as inst: + print 'Failed: %s' % inst + print 'Failed: %s' % inst + exitcode = Error.FAILED + except NotFoundError as inst: + print 'Failed: %s' % inst + exitcode = Error.NOTFOUND +else: + print 'No recognised command given. Try -h for help' + +sys.exit(exitcode) diff --git a/vland.py b/vland.py index d5ee2ff..633e10f 100755 --- a/vland.py +++ b/vland.py @@ -101,7 +101,7 @@ if len(switches) != len(state.config.switches): print 'You have configured access details for %d switch(es), ' % len(state.config.switches) print 'but have %d switch(es) registered in your database.' % len(switches) print 'You must fix this difference for VLANd to work sensibly.' - print 'HINT: Running admin.py auto_import_switch --name ' + print 'HINT: Running vland-admin auto_import_switch --name ' print 'for each of your switches may help!' print diff --git a/vland.service b/vland.service index 7609743..83397c9 100644 --- a/vland.service +++ b/vland.service @@ -7,7 +7,7 @@ Requires=postgresql.service [Service] Type=simple ExecStart=/home/vland/vland/vland.py -ExecStop=/home/vland/vland/admin.py shutdown +ExecStop=/home/vland/vland/vland-admin shutdown WorkingDirectory=/home/vland/vland User=vland -- cgit v1.2.3