python-neutronclient/quantumclient/cli.py

300 lines
10 KiB
Python
Executable File

# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2012 Nicira Networks, Inc.
# Copyright 2012 Citrix Systems
#
# 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.
# @author: Somik Behera, Nicira Networks, Inc.
# @author: Brad Hall, Nicira Networks, Inc.
# @author: Salvatore Orlando, Citrix
import logging
import logging.handlers
from optparse import OptionParser
import os
import sys
from quantumclient import cli_lib
from quantumclient import Client
from quantumclient import ClientV11
from quantumclient.common import exceptions
from quantumclient.common import utils
from quantumclient import net_filters_v11
from quantumclient import port_filters_v11
# Configure logger for client - cli logger is a child of it
# NOTE(salvatore-orlando): logger name does not map to package
# this is deliberate. Simplifies logger configuration
logging.basicConfig()
LOG = logging.getLogger('quantumclient')
DEFAULT_QUANTUM_VERSION = '1.1'
FORMAT = 'json'
commands_v10 = {
"list_nets": {
"func": cli_lib.list_nets,
"args": ["tenant-id"], },
"list_nets_detail": {
"func": cli_lib.list_nets_detail,
"args": ["tenant-id"], },
"create_net": {
"func": cli_lib.create_net,
"args": ["tenant-id", "net-name"], },
"delete_net": {
"func": cli_lib.delete_net,
"args": ["tenant-id", "net-id"], },
"show_net": {
"func": cli_lib.show_net,
"args": ["tenant-id", "net-id"], },
"show_net_detail": {
"func": cli_lib.show_net_detail,
"args": ["tenant-id", "net-id"], },
"update_net": {
"func": cli_lib.update_net,
"args": ["tenant-id", "net-id", "new-name"], },
"list_ports": {
"func": cli_lib.list_ports,
"args": ["tenant-id", "net-id"], },
"list_ports_detail": {
"func": cli_lib.list_ports_detail,
"args": ["tenant-id", "net-id"], },
"create_port": {
"func": cli_lib.create_port,
"args": ["tenant-id", "net-id"], },
"delete_port": {
"func": cli_lib.delete_port,
"args": ["tenant-id", "net-id", "port-id"], },
"update_port": {
"func": cli_lib.update_port,
"args": ["tenant-id", "net-id", "port-id", "params"], },
"show_port": {
"func": cli_lib.show_port,
"args": ["tenant-id", "net-id", "port-id"], },
"show_port_detail": {
"func": cli_lib.show_port_detail,
"args": ["tenant-id", "net-id", "port-id"], },
"plug_iface": {
"func": cli_lib.plug_iface,
"args": ["tenant-id", "net-id", "port-id", "iface-id"], },
"unplug_iface": {
"func": cli_lib.unplug_iface,
"args": ["tenant-id", "net-id", "port-id"], },
"show_iface": {
"func": cli_lib.show_iface,
"args": ["tenant-id", "net-id", "port-id"], }, }
commands_v11 = commands_v10.copy()
commands_v11.update({
"list_nets": {
"func": cli_lib.list_nets_v11,
"args": ["tenant-id"],
"filters": net_filters_v11, },
"list_nets_detail": {
"func": cli_lib.list_nets_detail_v11,
"args": ["tenant-id"],
"filters": net_filters_v11, },
"list_ports": {
"func": cli_lib.list_ports_v11,
"args": ["tenant-id", "net-id"],
"filters": port_filters_v11, },
"list_ports_detail": {
"func": cli_lib.list_ports_detail_v11,
"args": ["tenant-id", "net-id"],
"filters": port_filters_v11, }, })
commands = {
'1.0': commands_v10,
'1.1': commands_v11, }
clients = {
'1.0': Client,
'1.1': ClientV11, }
def help(version):
print "\nCommands:"
cmds = commands[version]
for k in cmds.keys():
print " %s %s %s" % (
k,
" ".join(["<%s>" % y for y in cmds[k]["args"]]),
'filters' in cmds[k] and "[filterspec ...]" or "")
def print_usage(cmd, version):
cmds = commands[version]
print "Usage:\n %s %s" % (
cmd, " ".join(["<%s>" % y for y in cmds[cmd]["args"]]))
def build_args(cmd, cmdargs, arglist):
arglist_len = len(arglist)
cmdargs_len = len(cmdargs)
if arglist_len < cmdargs_len:
message = ("Not enough arguments for \"%s\" (expected: %d, got: %d)" %
(cmd, len(cmdargs), arglist_len))
raise exceptions.QuantumCLIError(message=message)
args = arglist[:cmdargs_len]
return args
def build_filters(cmd, cmd_filters, filter_list, version):
filters = {}
# Each filter is expected to be in the <key>=<value> format
for flt in filter_list:
split_filter = flt.split("=")
if len(split_filter) != 2:
message = "Invalid filter argument detected (%s)" % flt
raise exceptions.QuantumCLIError(message=message)
filter_key, filter_value = split_filter
# Ensure the filter is allowed
if not filter_key in cmd_filters:
message = "Invalid filter key (%s)" % filter_key
raise exceptions.QuantumCLIError(message=message)
filters[filter_key] = filter_value
return filters
def build_cmd(cmd, cmd_args, cmd_filters, arglist, version):
"""
Builds arguments and filters to be passed to the cli library routines
:param cmd: Command to be executed
:param cmd_args: List of arguments required by the command
:param cmd_filters: List of filters allowed by the command
:param arglist: Command line arguments (includes both arguments and
filter specifications)
:param version: API version
"""
arglist_len = len(arglist)
try:
# Parse arguments
args = build_args(cmd, cmd_args, arglist)
# Parse filters
filters = None
if cmd_filters:
# Pop consumed arguments
arglist = arglist[len(args):]
filters = build_filters(cmd, cmd_filters, arglist, version)
except exceptions.QuantumCLIError as cli_ex:
LOG.error(cli_ex.message)
print " Error in command line:%s" % cli_ex.message
print_usage(cmd, version)
return None, None
filter_len = (filters is not None) and len(filters) or 0
if len(arglist) - len(args) - filter_len > 0:
message = ("Too many arguments for \"%s\" (expected: %d, got: %d)" %
(cmd, len(cmd_args), arglist_len))
LOG.error(message)
print "Error in command line: %s " % message
print "Usage:\n %s %s" % (
cmd,
" ".join(["<%s>" % y for y in commands[version][cmd]["args"]]))
return None, None
# Append version to arguments for cli functions
args.append(version)
return args, filters
def instantiate_client(host, port, ssl, tenant, token, version):
client = clients[version](host,
port,
ssl,
tenant,
FORMAT,
auth_token=token,
version=version)
return client
def main():
usagestr = "Usage: %prog [OPTIONS] <command> [args]"
parser = OptionParser(usage=usagestr)
parser.add_option("-H", "--host", dest="host",
type="string", default="127.0.0.1",
help="ip address of api host")
parser.add_option("-p", "--port", dest="port",
type="int", default=9696, help="api poort")
parser.add_option("-s", "--ssl", dest="ssl",
action="store_true", default=False, help="use ssl")
parser.add_option("--debug", dest="debug",
action="store_true", default=False,
help="print debugging output")
parser.add_option("-f", "--logfile", dest="logfile",
type="string", default="syslog", help="log file path")
parser.add_option("-t", "--token", dest="token",
type="string", default=None, help="authentication token")
parser.add_option(
'--version',
default=utils.env('QUANTUM_VERSION', default=DEFAULT_QUANTUM_VERSION),
help='Accepts 1.1 and 1.0, defaults to env[QUANTUM_VERSION].')
options, args = parser.parse_args()
if options.debug:
LOG.setLevel(logging.DEBUG)
else:
LOG.setLevel(logging.WARN)
if options.logfile == "syslog":
LOG.addHandler(logging.handlers.SysLogHandler(address='/dev/log'))
else:
LOG.addHandler(logging.handlers.WatchedFileHandler(options.logfile))
# Set permissions on log file
os.chmod(options.logfile, 0644)
version = options.version
if not version in commands:
LOG.error("Unknown API version specified:%s", version)
parser.print_help()
sys.exit(1)
if len(args) < 1:
parser.print_help()
help(version)
sys.exit(1)
cmd = args[0]
if cmd not in commands[version].keys():
LOG.error("Unknown command: %s" % cmd)
help(version)
sys.exit(1)
# Build argument list for CLI command
# The argument list will include the version number as well
args, filters = build_cmd(cmd,
commands[version][cmd]["args"],
commands[version][cmd].get("filters", None),
args[1:],
options.version)
if not args:
sys.exit(1)
LOG.info("Executing command \"%s\" with args: %s" % (cmd, args))
client = instantiate_client(options.host,
options.port,
options.ssl,
args[0],
options.token,
options.version)
# append filters to arguments
# this will allow for using the same prototype for v10 and v11
# TODO: Use **kwargs instead of *args (keyword is better than positional)
if filters:
args.append(filters)
commands[version][cmd]["func"](client, *args)
LOG.info("Command execution completed")
sys.exit(0)
if __name__ == '__main__':
main()