bp/quantum-client-1.1
- Adds supports for 1.1 API - Handles new error codes - Support filters for 1.1 API Addressing Dan's comments Change-Id: I230657de1621ddf08573bbeaceeb26cafbee1a00
This commit is contained in:
parent
880cde716e
commit
f6d5087698
quantum
@ -25,19 +25,104 @@ from quantum.common import exceptions
|
||||
from quantum.common.serializer import Serializer
|
||||
|
||||
LOG = logging.getLogger('quantum.client')
|
||||
EXCEPTIONS = {
|
||||
400: exceptions.BadInputError,
|
||||
401: exceptions.NotAuthorized,
|
||||
420: exceptions.NetworkNotFound,
|
||||
421: exceptions.NetworkInUse,
|
||||
430: exceptions.PortNotFound,
|
||||
431: exceptions.StateInvalid,
|
||||
432: exceptions.PortInUseClient,
|
||||
440: exceptions.AlreadyAttachedClient,
|
||||
501: exceptions.NotImplementedError}
|
||||
AUTH_TOKEN_HEADER = "X-Auth-Token"
|
||||
|
||||
|
||||
def exception_handler_v10(status_code, error_content):
|
||||
""" Exception handler for API v1.0 client
|
||||
|
||||
This routine generates the appropriate
|
||||
Quantum exception according to the contents of the
|
||||
response body
|
||||
|
||||
:param status_code: HTTP error status code
|
||||
:param error_content: deserialized body of error response
|
||||
"""
|
||||
|
||||
quantum_error_types = {
|
||||
420: 'networkNotFound',
|
||||
421: 'networkInUse',
|
||||
430: 'portNotFound',
|
||||
431: 'requestedStateInvalid',
|
||||
432: 'portInUse',
|
||||
440: 'alreadyAttached'
|
||||
}
|
||||
|
||||
quantum_errors = {
|
||||
400: exceptions.BadInputError,
|
||||
401: exceptions.NotAuthorized,
|
||||
404: exceptions.NotFound,
|
||||
420: exceptions.NetworkNotFoundClient,
|
||||
421: exceptions.NetworkInUseClient,
|
||||
430: exceptions.PortNotFoundClient,
|
||||
431: exceptions.StateInvalidClient,
|
||||
432: exceptions.PortInUseClient,
|
||||
440: exceptions.AlreadyAttachedClient,
|
||||
501: NotImplementedError
|
||||
}
|
||||
|
||||
# Find real error type
|
||||
error_type = None
|
||||
if isinstance(error_content, dict):
|
||||
error_type = quantum_error_types.get(status_code)
|
||||
if error_type:
|
||||
error_dict = error_content[error_type]
|
||||
error_message = error_dict['message'] + "\n" +\
|
||||
error_dict['detail']
|
||||
else:
|
||||
error_message = error_content
|
||||
# raise the appropriate error!
|
||||
ex = quantum_errors[status_code](message=error_message)
|
||||
ex.args = ([dict(status_code=status_code,
|
||||
message=error_message)],)
|
||||
raise ex
|
||||
|
||||
|
||||
def exception_handler_v11(status_code, error_content):
|
||||
""" Exception handler for API v1.1 client
|
||||
|
||||
This routine generates the appropriate
|
||||
Quantum exception according to the contents of the
|
||||
response body
|
||||
|
||||
:param status_code: HTTP error status code
|
||||
:param error_content: deserialized body of error response
|
||||
"""
|
||||
|
||||
quantum_errors = {
|
||||
'NetworkNotFound': exceptions.NetworkNotFoundClient,
|
||||
'NetworkInUse': exceptions.NetworkInUseClient,
|
||||
'PortNotFound': exceptions.PortNotFoundClient,
|
||||
'RequestedStateInvalid': exceptions.StateInvalidClient,
|
||||
'PortInUse': exceptions.PortInUseClient,
|
||||
'AlreadyAttached': exceptions.AlreadyAttachedClient,
|
||||
}
|
||||
|
||||
error_dict = None
|
||||
if isinstance(error_content, dict):
|
||||
error_dict = error_content.get('QuantumError')
|
||||
# Find real error type
|
||||
if error_dict:
|
||||
# If QuantumError key is found, it will definitely contain
|
||||
# a 'message' and 'type' keys
|
||||
error_type = error_dict['type']
|
||||
error_message = (error_dict['message'] + "\n" +
|
||||
error_dict['detail'])
|
||||
# raise the appropriate error!
|
||||
ex = quantum_errors[error_type](message=error_message)
|
||||
ex.args = ([dict(status_code=status_code,
|
||||
message=error_message)],)
|
||||
raise ex
|
||||
# If we end up here the exception was not a quantum error
|
||||
raise exceptions.QuantumClientException(status_code + "-" + error_content)
|
||||
|
||||
|
||||
EXCEPTION_HANDLERS = {
|
||||
'1.0': exception_handler_v10,
|
||||
'1.1': exception_handler_v11
|
||||
}
|
||||
|
||||
|
||||
class ApiCall(object):
|
||||
"""A Decorator to add support for format and tenant overriding"""
|
||||
def __init__(self, function):
|
||||
@ -86,7 +171,8 @@ class Client(object):
|
||||
def __init__(self, host="127.0.0.1", port=9696, use_ssl=False, tenant=None,
|
||||
format="xml", testingStub=None, key_file=None, cert_file=None,
|
||||
auth_token=None, logger=None,
|
||||
action_prefix="/v1.0/tenants/{tenant_id}"):
|
||||
version="1.1",
|
||||
uri_prefix="/tenants/{tenant_id}"):
|
||||
"""
|
||||
Creates a new client to some service.
|
||||
|
||||
@ -113,7 +199,24 @@ class Client(object):
|
||||
self.cert_file = cert_file
|
||||
self.logger = logger
|
||||
self.auth_token = auth_token
|
||||
self.action_prefix = action_prefix
|
||||
self.version = version
|
||||
self.action_prefix = "/v%s%s" % (version, uri_prefix)
|
||||
|
||||
def _handle_fault_response(self, status_code, response_body):
|
||||
# Create exception with HTTP status code and message
|
||||
error_message = response_body
|
||||
LOG.debug("Server returned error: %s", status_code)
|
||||
LOG.debug("Error message: %s", error_message)
|
||||
# Add deserialized error message to exception arguments
|
||||
try:
|
||||
des_error_body = Serializer().deserialize(error_message,
|
||||
self.content_type())
|
||||
except:
|
||||
# If unable to deserialized body it is probably not a
|
||||
# Quantum error
|
||||
des_error_body = {'message': error_message}
|
||||
# Raise the appropriate exception
|
||||
EXCEPTION_HANDLERS[self.version](status_code, des_error_body)
|
||||
|
||||
def get_connection_type(self):
|
||||
"""
|
||||
@ -138,7 +241,7 @@ class Client(object):
|
||||
return conn.getresponse()
|
||||
|
||||
def do_request(self, method, action, body=None,
|
||||
headers=None, params=None, exception_args={}):
|
||||
headers=None, params=None):
|
||||
"""
|
||||
Connects to the server and issues a request.
|
||||
Returns the result data, or raises an appropriate exception if
|
||||
@ -155,7 +258,6 @@ class Client(object):
|
||||
# Ensure we have a tenant id
|
||||
if not self.tenant:
|
||||
raise Exception("Tenant ID not set")
|
||||
|
||||
# Add format and tenant_id
|
||||
action += ".%s" % self.format
|
||||
action = self.action_prefix + action
|
||||
@ -165,7 +267,6 @@ class Client(object):
|
||||
action += '?' + urllib.urlencode(params)
|
||||
if body:
|
||||
body = self.serialize(body)
|
||||
|
||||
try:
|
||||
connection_type = self.get_connection_type()
|
||||
headers = headers or {"Content-Type":
|
||||
@ -176,7 +277,6 @@ class Client(object):
|
||||
# Open connection and send request, handling SSL certs
|
||||
certs = {'key_file': self.key_file, 'cert_file': self.cert_file}
|
||||
certs = dict((x, certs[x]) for x in certs if certs[x] != None)
|
||||
|
||||
if self.use_ssl and len(certs):
|
||||
conn = connection_type(self.host, self.port, **certs)
|
||||
else:
|
||||
@ -184,7 +284,6 @@ class Client(object):
|
||||
res = self._send_request(conn, method, action, body, headers)
|
||||
status_code = self.get_status_code(res)
|
||||
data = res.read()
|
||||
|
||||
if self.logger:
|
||||
self.logger.debug("Quantum Client Reply (code = %s) :\n %s" \
|
||||
% (str(status_code), data))
|
||||
@ -194,17 +293,7 @@ class Client(object):
|
||||
httplib.NO_CONTENT):
|
||||
return self.deserialize(data, status_code)
|
||||
else:
|
||||
error_message = res.read()
|
||||
LOG.debug("Server returned error: %s", status_code)
|
||||
LOG.debug("Error message: %s", error_message)
|
||||
# Create exception with HTTP status code and message
|
||||
if res.status in EXCEPTIONS:
|
||||
raise EXCEPTIONS[res.status](**exception_args)
|
||||
# Add error code and message to exception arguments
|
||||
ex = Exception("Server returned error: %s" % status_code)
|
||||
ex.args = ([dict(status_code=status_code,
|
||||
message=error_message)],)
|
||||
raise ex
|
||||
self._handle_fault_response(status_code, data)
|
||||
except (socket.error, IOError), e:
|
||||
msg = "Unable to connect to server. Got error: %s" % e
|
||||
LOG.exception(msg)
|
||||
@ -263,8 +352,7 @@ class Client(object):
|
||||
"""
|
||||
Fetches the details of a certain network
|
||||
"""
|
||||
return self.do_request("GET", self.network_path % (network),
|
||||
exception_args={"net_id": network})
|
||||
return self.do_request("GET", self.network_path % (network))
|
||||
|
||||
@ApiCall
|
||||
def create_network(self, body=None):
|
||||
@ -278,16 +366,14 @@ class Client(object):
|
||||
"""
|
||||
Updates a network
|
||||
"""
|
||||
return self.do_request("PUT", self.network_path % (network), body=body,
|
||||
exception_args={"net_id": network})
|
||||
return self.do_request("PUT", self.network_path % (network), body=body)
|
||||
|
||||
@ApiCall
|
||||
def delete_network(self, network):
|
||||
"""
|
||||
Deletes the specified network
|
||||
"""
|
||||
return self.do_request("DELETE", self.network_path % (network),
|
||||
exception_args={"net_id": network})
|
||||
return self.do_request("DELETE", self.network_path % (network))
|
||||
|
||||
@ApiCall
|
||||
def list_ports(self, network):
|
||||
@ -301,24 +387,21 @@ class Client(object):
|
||||
"""
|
||||
Fetches the details of a certain port
|
||||
"""
|
||||
return self.do_request("GET", self.port_path % (network, port),
|
||||
exception_args={"net_id": network, "port_id": port})
|
||||
return self.do_request("GET", self.port_path % (network, port))
|
||||
|
||||
@ApiCall
|
||||
def create_port(self, network, body=None):
|
||||
"""
|
||||
Creates a new port on a given network
|
||||
"""
|
||||
return self.do_request("POST", self.ports_path % (network), body=body,
|
||||
exception_args={"net_id": network})
|
||||
return self.do_request("POST", self.ports_path % (network), body=body)
|
||||
|
||||
@ApiCall
|
||||
def delete_port(self, network, port):
|
||||
"""
|
||||
Deletes the specified port from a network
|
||||
"""
|
||||
return self.do_request("DELETE", self.port_path % (network, port),
|
||||
exception_args={"net_id": network, "port_id": port})
|
||||
return self.do_request("DELETE", self.port_path % (network, port))
|
||||
|
||||
@ApiCall
|
||||
def update_port(self, network, port, body=None):
|
||||
@ -326,17 +409,14 @@ class Client(object):
|
||||
Sets the attributes of the specified port
|
||||
"""
|
||||
return self.do_request("PUT",
|
||||
self.port_path % (network, port), body=body,
|
||||
exception_args={"net_id": network,
|
||||
"port_id": port})
|
||||
self.port_path % (network, port), body=body)
|
||||
|
||||
@ApiCall
|
||||
def show_port_attachment(self, network, port):
|
||||
"""
|
||||
Fetches the attachment-id associated with the specified port
|
||||
"""
|
||||
return self.do_request("GET", self.attachment_path % (network, port),
|
||||
exception_args={"net_id": network, "port_id": port})
|
||||
return self.do_request("GET", self.attachment_path % (network, port))
|
||||
|
||||
@ApiCall
|
||||
def attach_resource(self, network, port, body=None):
|
||||
@ -344,10 +424,7 @@ class Client(object):
|
||||
Sets the attachment-id of the specified port
|
||||
"""
|
||||
return self.do_request("PUT",
|
||||
self.attachment_path % (network, port), body=body,
|
||||
exception_args={"net_id": network,
|
||||
"port_id": port,
|
||||
"attach_id": str(body)})
|
||||
self.attachment_path % (network, port), body=body)
|
||||
|
||||
@ApiCall
|
||||
def detach_resource(self, network, port):
|
||||
@ -355,5 +432,28 @@ class Client(object):
|
||||
Removes the attachment-id of the specified port
|
||||
"""
|
||||
return self.do_request("DELETE",
|
||||
self.attachment_path % (network, port),
|
||||
exception_args={"net_id": network, "port_id": port})
|
||||
self.attachment_path % (network, port))
|
||||
|
||||
|
||||
class ClientV11(Client):
|
||||
"""
|
||||
This class overiddes some methods of the Client class in order to deal with
|
||||
features specific to API v1.1 such as filters
|
||||
"""
|
||||
|
||||
@ApiCall
|
||||
def list_networks(self, **filters):
|
||||
"""
|
||||
Fetches a list of all networks for a tenant
|
||||
"""
|
||||
# Pass filters in "params" argument to do_request
|
||||
return self.do_request("GET", self.networks_path, params=filters)
|
||||
|
||||
@ApiCall
|
||||
def list_ports(self, network, **filters):
|
||||
"""
|
||||
Fetches a list of ports on a given network
|
||||
"""
|
||||
# Pass filters in "params" argument to do_request
|
||||
return self.do_request("GET", self.ports_path % (network),
|
||||
params=filters)
|
||||
|
@ -1,7 +1,7 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright 2011 Nicira Networks, Inc.
|
||||
# Copyright 2011 Citrix Systems
|
||||
# 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
|
||||
@ -26,6 +26,7 @@ import sys
|
||||
|
||||
from optparse import OptionParser
|
||||
|
||||
from quantum.common import exceptions
|
||||
|
||||
possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]),
|
||||
os.pardir,
|
||||
@ -37,13 +38,16 @@ gettext.install('quantum', unicode=1)
|
||||
|
||||
from quantum.client import cli_lib
|
||||
from quantum.client import Client
|
||||
from quantum.client import ClientV11
|
||||
from quantum.common import utils
|
||||
|
||||
#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
|
||||
LOG = logging.getLogger('quantum')
|
||||
DEFAULT_QUANTUM_VERSION = '1.1'
|
||||
FORMAT = 'json'
|
||||
commands = {
|
||||
commands_v10 = {
|
||||
"list_nets": {
|
||||
"func": cli_lib.list_nets,
|
||||
"args": ["tenant-id"]},
|
||||
@ -81,36 +85,122 @@ commands = {
|
||||
"func": cli_lib.unplug_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": ["name", "op-status", "port-op-status", "port-state",
|
||||
"has-attachment", "attachment", "port"]},
|
||||
"list_ports": {
|
||||
"func": cli_lib.list_ports_v11,
|
||||
"args": ["tenant-id", "net-id"],
|
||||
"filters": ["name", "op-status", "has-attachment", "attachment"]},
|
||||
})
|
||||
commands = {
|
||||
'1.0': commands_v10,
|
||||
'1.1': commands_v11
|
||||
}
|
||||
clients = {
|
||||
'1.0': Client,
|
||||
'1.1': ClientV11
|
||||
}
|
||||
|
||||
def help():
|
||||
|
||||
def help(version):
|
||||
print "\nCommands:"
|
||||
for k in commands.keys():
|
||||
print " %s %s" % (k,
|
||||
" ".join(["<%s>" % y for y in commands[k]["args"]]))
|
||||
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):
|
||||
args = []
|
||||
orig_arglist = arglist[:]
|
||||
try:
|
||||
for x in cmdargs:
|
||||
args.append(arglist[0])
|
||||
del arglist[0]
|
||||
except:
|
||||
LOG.error("Not enough arguments for \"%s\" (expected: %d, got: %d)" % (
|
||||
cmd, len(cmdargs), len(orig_arglist)))
|
||||
print "Usage:\n %s %s" % (cmd,
|
||||
" ".join(["<%s>" % y for y in commands[cmd]["args"]]))
|
||||
return None
|
||||
if len(arglist) > 0:
|
||||
LOG.error("Too many arguments for \"%s\" (expected: %d, got: %d)" % (
|
||||
cmd, len(cmdargs), len(orig_arglist)))
|
||||
print "Usage:\n %s %s" % (cmd,
|
||||
" ".join(["<%s>" % y for y in commands[cmd]["args"]]))
|
||||
return None
|
||||
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)
|
||||
@ -126,13 +216,15 @@ def main():
|
||||
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.verbose:
|
||||
LOG.setLevel(logging.DEBUG)
|
||||
else:
|
||||
LOG.setLevel(logging.WARN)
|
||||
#logging.handlers.WatchedFileHandler
|
||||
|
||||
if options.logfile == "syslog":
|
||||
LOG.addHandler(logging.handlers.SysLogHandler(address='/dev/log'))
|
||||
@ -141,29 +233,45 @@ def main():
|
||||
# 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)
|
||||
print "Unknown API version: %s" % version
|
||||
|
||||
if len(args) < 1:
|
||||
parser.print_help()
|
||||
help()
|
||||
help(version)
|
||||
sys.exit(1)
|
||||
|
||||
cmd = args[0]
|
||||
if cmd not in commands.keys():
|
||||
if cmd not in commands[version].keys():
|
||||
LOG.error("Unknown command: %s" % cmd)
|
||||
help()
|
||||
help(version)
|
||||
sys.exit(1)
|
||||
|
||||
args = build_args(cmd, commands[cmd]["args"], args[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 = Client(options.host, options.port, options.ssl,
|
||||
args[0], FORMAT,
|
||||
auth_token=options.token)
|
||||
commands[cmd]["func"](client, *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()
|
||||
|
@ -91,7 +91,7 @@ class CmdOutputTemplate(OutputTemplate):
|
||||
Extends OutputTemplate loading a different template for each command.
|
||||
"""
|
||||
|
||||
_templates = {
|
||||
_templates_v10 = {
|
||||
"list_nets": "Virtual Networks for Tenant %(tenant_id)s\n" +
|
||||
"%(networks|\tNetwork ID: %(id)s)s",
|
||||
"show_net": "Network ID: %(network.id)s\n" +
|
||||
@ -130,13 +130,31 @@ class CmdOutputTemplate(OutputTemplate):
|
||||
"on Virtual Network: %(network_id)s\n" +
|
||||
"for Tenant: %(tenant_id)s"}
|
||||
|
||||
def __init__(self, cmd, data):
|
||||
super(CmdOutputTemplate, self).__init__(self._templates[cmd], data)
|
||||
_templates_v11 = _templates_v10.copy()
|
||||
_templates_v11.update({
|
||||
"show_net": "Network ID: %(network.id)s\n" +
|
||||
"network Name: %(network.name)s\n" +
|
||||
"operational Status: %(network.op-status)s",
|
||||
"show_port": "Logical Port ID: %(port.id)s\n" +
|
||||
"administrative state: %(port.state)s\n" +
|
||||
"operational status: %(port.op-status)s\n" +
|
||||
"interface: %(port.attachment)s\n" +
|
||||
"on Virtual Network: %(network_id)s\n" +
|
||||
"for Tenant: %(tenant_id)s",
|
||||
})
|
||||
|
||||
_templates = {
|
||||
'1.0': _templates_v10,
|
||||
'1.1': _templates_v11
|
||||
}
|
||||
|
||||
def __init__(self, cmd, data, version):
|
||||
super(CmdOutputTemplate, self).__init__(
|
||||
self._templates[version][cmd], data)
|
||||
|
||||
|
||||
def _handle_exception(ex):
|
||||
LOG.exception(sys.exc_info())
|
||||
print "Exception:%s - %s" % (sys.exc_info()[0], sys.exc_info()[1])
|
||||
status_code = None
|
||||
message = None
|
||||
# Retrieve dict at 1st element of tuple at last argument
|
||||
@ -149,67 +167,94 @@ def _handle_exception(ex):
|
||||
LOG.exception(msg_1 + "-" + msg_2)
|
||||
print msg_1
|
||||
print msg_2
|
||||
else:
|
||||
print "An unexpected exception occured:%s (%s)" % (sys.exc_info()[1],
|
||||
sys.exc_info()[0])
|
||||
|
||||
|
||||
def prepare_output(cmd, tenant_id, response):
|
||||
LOG.debug("Preparing output for response:%s", response)
|
||||
def prepare_output(cmd, tenant_id, response, version):
|
||||
LOG.debug("Preparing output for response:%s, version:%s"
|
||||
% (response, version))
|
||||
response['tenant_id'] = tenant_id
|
||||
output = str(CmdOutputTemplate(cmd, response))
|
||||
output = str(CmdOutputTemplate(cmd, response, version))
|
||||
LOG.debug("Finished preparing output for command:%s", cmd)
|
||||
return output
|
||||
|
||||
|
||||
def list_nets(client, *args):
|
||||
tenant_id = args[0]
|
||||
res = client.list_networks()
|
||||
LOG.debug("Operation 'list_networks' executed.")
|
||||
output = prepare_output("list_nets", tenant_id, res)
|
||||
print output
|
||||
tenant_id, version = args
|
||||
try:
|
||||
res = client.list_networks()
|
||||
LOG.debug("Operation 'list_networks' executed.")
|
||||
output = prepare_output("list_nets", tenant_id, res, version)
|
||||
print output
|
||||
except Exception as ex:
|
||||
_handle_exception(ex)
|
||||
|
||||
|
||||
def list_nets_v11(client, *args):
|
||||
filters = {}
|
||||
tenant_id, version = args[:2]
|
||||
if len(args) > 2:
|
||||
filters = args[2]
|
||||
try:
|
||||
res = client.list_networks(**filters)
|
||||
LOG.debug("Operation 'list_networks' executed.")
|
||||
output = prepare_output("list_nets", tenant_id, res, version)
|
||||
print output
|
||||
except Exception as ex:
|
||||
_handle_exception(ex)
|
||||
|
||||
|
||||
def create_net(client, *args):
|
||||
tenant_id, name = args
|
||||
tenant_id, name, version = args
|
||||
data = {'network': {'name': name}}
|
||||
new_net_id = None
|
||||
try:
|
||||
res = client.create_network(data)
|
||||
new_net_id = res["network"]["id"]
|
||||
LOG.debug("Operation 'create_network' executed.")
|
||||
output = prepare_output("create_net", tenant_id,
|
||||
dict(network_id=new_net_id))
|
||||
output = prepare_output("create_net",
|
||||
tenant_id,
|
||||
dict(network_id=new_net_id),
|
||||
version)
|
||||
print output
|
||||
except Exception as ex:
|
||||
_handle_exception(ex)
|
||||
|
||||
|
||||
def delete_net(client, *args):
|
||||
tenant_id, network_id = args
|
||||
tenant_id, network_id, version = args
|
||||
try:
|
||||
client.delete_network(network_id)
|
||||
LOG.debug("Operation 'delete_network' executed.")
|
||||
output = prepare_output("delete_net", tenant_id,
|
||||
dict(network_id=network_id))
|
||||
output = prepare_output("delete_net",
|
||||
tenant_id,
|
||||
dict(network_id=network_id),
|
||||
version)
|
||||
print output
|
||||
except Exception as ex:
|
||||
_handle_exception(ex)
|
||||
|
||||
|
||||
def show_net(client, *args):
|
||||
tenant_id, network_id = args
|
||||
tenant_id, network_id, version = args
|
||||
try:
|
||||
#NOTE(salvatore-orlando) changed for returning exclusively
|
||||
# output for GET /networks/{net-id} API operation
|
||||
res = client.show_network_details(network_id)["network"]
|
||||
LOG.debug("Operation 'show_network_details' executed.")
|
||||
output = prepare_output("show_net", tenant_id,
|
||||
dict(network=res))
|
||||
output = prepare_output("show_net",
|
||||
tenant_id,
|
||||
dict(network=res),
|
||||
version)
|
||||
print output
|
||||
except Exception as ex:
|
||||
_handle_exception(ex)
|
||||
|
||||
|
||||
def update_net(client, *args):
|
||||
tenant_id, network_id, param_data = args
|
||||
tenant_id, network_id, param_data, version = args
|
||||
data = {'network': {}}
|
||||
for kv in param_data.split(","):
|
||||
k, v = kv.split("=")
|
||||
@ -219,47 +264,67 @@ def update_net(client, *args):
|
||||
client.update_network(network_id, data)
|
||||
LOG.debug("Operation 'update_network' executed.")
|
||||
# Response has no body. Use data for populating output
|
||||
output = prepare_output("update_net", tenant_id, data)
|
||||
output = prepare_output("update_net", tenant_id, data, version)
|
||||
print output
|
||||
except Exception as ex:
|
||||
_handle_exception(ex)
|
||||
|
||||
|
||||
def list_ports(client, *args):
|
||||
tenant_id, network_id = args
|
||||
tenant_id, network_id, version = args
|
||||
try:
|
||||
ports = client.list_ports(network_id)
|
||||
LOG.debug("Operation 'list_ports' executed.")
|
||||
data = ports
|
||||
data['network_id'] = network_id
|
||||
output = prepare_output("list_ports", tenant_id, data)
|
||||
output = prepare_output("list_ports", tenant_id, data, version)
|
||||
print output
|
||||
except Exception as ex:
|
||||
_handle_exception(ex)
|
||||
|
||||
|
||||
def list_ports_v11(client, *args):
|
||||
filters = {}
|
||||
tenant_id, network_id, version = args[:3]
|
||||
if len(args) > 3:
|
||||
filters = args[3]
|
||||
try:
|
||||
ports = client.list_ports(network_id, **filters)
|
||||
LOG.debug("Operation 'list_ports' executed.")
|
||||
data = ports
|
||||
data['network_id'] = network_id
|
||||
output = prepare_output("list_ports", tenant_id, data, version)
|
||||
print output
|
||||
except Exception as ex:
|
||||
_handle_exception(ex)
|
||||
|
||||
|
||||
def create_port(client, *args):
|
||||
tenant_id, network_id = args
|
||||
tenant_id, network_id, version = args
|
||||
try:
|
||||
res = client.create_port(network_id)
|
||||
LOG.debug("Operation 'create_port' executed.")
|
||||
new_port_id = res["port"]["id"]
|
||||
output = prepare_output("create_port", tenant_id,
|
||||
output = prepare_output("create_port",
|
||||
tenant_id,
|
||||
dict(network_id=network_id,
|
||||
port_id=new_port_id))
|
||||
port_id=new_port_id),
|
||||
version)
|
||||
print output
|
||||
except Exception as ex:
|
||||
_handle_exception(ex)
|
||||
|
||||
|
||||
def delete_port(client, *args):
|
||||
tenant_id, network_id, port_id = args
|
||||
tenant_id, network_id, port_id, version = args
|
||||
try:
|
||||
client.delete_port(network_id, port_id)
|
||||
LOG.debug("Operation 'delete_port' executed.")
|
||||
output = prepare_output("delete_port", tenant_id,
|
||||
output = prepare_output("delete_port",
|
||||
tenant_id,
|
||||
dict(network_id=network_id,
|
||||
port_id=port_id))
|
||||
port_id=port_id),
|
||||
version)
|
||||
print output
|
||||
except Exception as ex:
|
||||
_handle_exception(ex)
|
||||
@ -267,7 +332,7 @@ def delete_port(client, *args):
|
||||
|
||||
|
||||
def show_port(client, *args):
|
||||
tenant_id, network_id, port_id = args
|
||||
tenant_id, network_id, port_id, version = args
|
||||
try:
|
||||
port = client.show_port_details(network_id, port_id)["port"]
|
||||
LOG.debug("Operation 'list_port_details' executed.")
|
||||
@ -280,16 +345,18 @@ def show_port(client, *args):
|
||||
port['attachment'] = attach['id']
|
||||
else:
|
||||
port['attachment'] = '<none>'
|
||||
output = prepare_output("show_port", tenant_id,
|
||||
output = prepare_output("show_port",
|
||||
tenant_id,
|
||||
dict(network_id=network_id,
|
||||
port=port))
|
||||
port=port),
|
||||
version)
|
||||
print output
|
||||
except Exception as ex:
|
||||
_handle_exception(ex)
|
||||
|
||||
|
||||
def update_port(client, *args):
|
||||
tenant_id, network_id, port_id, param_data = args
|
||||
tenant_id, network_id, port_id, param_data, version = args
|
||||
data = {'port': {}}
|
||||
for kv in param_data.split(","):
|
||||
k, v = kv.split("=")
|
||||
@ -300,14 +367,14 @@ def update_port(client, *args):
|
||||
client.update_port(network_id, port_id, data)
|
||||
LOG.debug("Operation 'udpate_port' executed.")
|
||||
# Response has no body. Use data for populating output
|
||||
output = prepare_output("update_port", tenant_id, data)
|
||||
output = prepare_output("update_port", tenant_id, data, version)
|
||||
print output
|
||||
except Exception as ex:
|
||||
_handle_exception(ex)
|
||||
|
||||
|
||||
def plug_iface(client, *args):
|
||||
tenant_id, network_id, port_id, attachment = args
|
||||
tenant_id, network_id, port_id, attachment, version = args
|
||||
try:
|
||||
data = {'attachment': {'id': '%s' % attachment}}
|
||||
client.attach_resource(network_id, port_id, data)
|
||||
@ -315,20 +382,23 @@ def plug_iface(client, *args):
|
||||
output = prepare_output("plug_iface", tenant_id,
|
||||
dict(network_id=network_id,
|
||||
port_id=port_id,
|
||||
attachment=attachment))
|
||||
attachment=attachment),
|
||||
version)
|
||||
print output
|
||||
except Exception as ex:
|
||||
_handle_exception(ex)
|
||||
|
||||
|
||||
def unplug_iface(client, *args):
|
||||
tenant_id, network_id, port_id = args
|
||||
tenant_id, network_id, port_id, version = args
|
||||
try:
|
||||
client.detach_resource(network_id, port_id)
|
||||
LOG.debug("Operation 'detach_resource' executed.")
|
||||
output = prepare_output("unplug_iface", tenant_id,
|
||||
output = prepare_output("unplug_iface",
|
||||
tenant_id,
|
||||
dict(network_id=network_id,
|
||||
port_id=port_id))
|
||||
port_id=port_id),
|
||||
version)
|
||||
print output
|
||||
except Exception as ex:
|
||||
_handle_exception(ex)
|
||||
|
@ -33,6 +33,7 @@ from quantum.db import api as db
|
||||
from quantum.tests.unit.client_tools import stubs as client_stubs
|
||||
|
||||
LOG = logging.getLogger('quantum.tests.test_cli')
|
||||
API_VERSION = "1.1"
|
||||
FORMAT = 'json'
|
||||
|
||||
|
||||
@ -49,9 +50,12 @@ class CLITest(unittest.TestCase):
|
||||
self.tenant_id = "test_tenant"
|
||||
self.network_name_1 = "test_network_1"
|
||||
self.network_name_2 = "test_network_2"
|
||||
self.version = API_VERSION
|
||||
# Prepare client and plugin manager
|
||||
self.client = Client(tenant=self.tenant_id, format=FORMAT,
|
||||
testingStub=client_stubs.FakeHTTPConnection)
|
||||
self.client = Client(tenant=self.tenant_id,
|
||||
format=FORMAT,
|
||||
testingStub=client_stubs.FakeHTTPConnection,
|
||||
version=self.version)
|
||||
# Redirect stdout
|
||||
self.fake_stdout = client_stubs.FakeStdout()
|
||||
sys.stdout = self.fake_stdout
|
||||
@ -64,10 +68,13 @@ class CLITest(unittest.TestCase):
|
||||
def _verify_list_networks(self):
|
||||
# Verification - get raw result from db
|
||||
nw_list = db.network_list(self.tenant_id)
|
||||
networks = [dict(id=nw.uuid, name=nw.name) for nw in nw_list]
|
||||
networks = [{'id': nw.uuid, 'name': nw.name}
|
||||
for nw in nw_list]
|
||||
# Fill CLI template
|
||||
output = cli.prepare_output('list_nets', self.tenant_id,
|
||||
dict(networks=networks))
|
||||
output = cli.prepare_output('list_nets',
|
||||
self.tenant_id,
|
||||
dict(networks=networks),
|
||||
self.version)
|
||||
# Verify!
|
||||
# Must add newline at the end to match effect of print call
|
||||
self.assertEquals(self.fake_stdout.make_string(), output + '\n')
|
||||
@ -79,8 +86,10 @@ class CLITest(unittest.TestCase):
|
||||
self.fail("No network created")
|
||||
network_id = nw_list[0].uuid
|
||||
# Fill CLI template
|
||||
output = cli.prepare_output('create_net', self.tenant_id,
|
||||
dict(network_id=network_id))
|
||||
output = cli.prepare_output('create_net',
|
||||
self.tenant_id,
|
||||
dict(network_id=network_id),
|
||||
self.version)
|
||||
# Verify!
|
||||
# Must add newline at the end to match effect of print call
|
||||
self.assertEquals(self.fake_stdout.make_string(), output + '\n')
|
||||
@ -91,8 +100,10 @@ class CLITest(unittest.TestCase):
|
||||
if len(nw_list) != 0:
|
||||
self.fail("DB should not contain any network")
|
||||
# Fill CLI template
|
||||
output = cli.prepare_output('delete_net', self.tenant_id,
|
||||
dict(network_id=network_id))
|
||||
output = cli.prepare_output('delete_net',
|
||||
self.tenant_id,
|
||||
dict(network_id=network_id),
|
||||
self.version)
|
||||
# Verify!
|
||||
# Must add newline at the end to match effect of print call
|
||||
self.assertEquals(self.fake_stdout.make_string(), output + '\n')
|
||||
@ -101,10 +112,13 @@ class CLITest(unittest.TestCase):
|
||||
# Verification - get raw result from db
|
||||
nw_list = db.network_list(self.tenant_id)
|
||||
network_data = {'id': nw_list[0].uuid,
|
||||
'name': nw_list[0].name}
|
||||
'name': nw_list[0].name,
|
||||
'op-status': nw_list[0].op_status}
|
||||
# Fill CLI template
|
||||
output = cli.prepare_output('update_net', self.tenant_id,
|
||||
dict(network=network_data))
|
||||
output = cli.prepare_output('update_net',
|
||||
self.tenant_id,
|
||||
dict(network=network_data),
|
||||
self.version)
|
||||
# Verify!
|
||||
# Must add newline at the end to match effect of print call
|
||||
self.assertEquals(self.fake_stdout.make_string(), output + '\n')
|
||||
@ -112,10 +126,14 @@ class CLITest(unittest.TestCase):
|
||||
def _verify_show_network(self):
|
||||
# Verification - get raw result from db
|
||||
nw = db.network_list(self.tenant_id)[0]
|
||||
network = dict(id=nw.uuid, name=nw.name)
|
||||
network = {'id': nw.uuid,
|
||||
'name': nw.name,
|
||||
'op-status': nw.op_status}
|
||||
# Fill CLI template
|
||||
output = cli.prepare_output('show_net', self.tenant_id,
|
||||
dict(network=network))
|
||||
output = cli.prepare_output('show_net',
|
||||
self.tenant_id,
|
||||
dict(network=network),
|
||||
self.version)
|
||||
# Verify!
|
||||
# Must add newline at the end to match effect of print call
|
||||
self.assertEquals(self.fake_stdout.make_string(), output + '\n')
|
||||
@ -126,9 +144,11 @@ class CLITest(unittest.TestCase):
|
||||
ports = [dict(id=port.uuid, state=port.state)
|
||||
for port in port_list]
|
||||
# Fill CLI template
|
||||
output = cli.prepare_output('list_ports', self.tenant_id,
|
||||
output = cli.prepare_output('list_ports',
|
||||
self.tenant_id,
|
||||
dict(network_id=network_id,
|
||||
ports=ports))
|
||||
ports=ports),
|
||||
self.version)
|
||||
# Verify!
|
||||
# Must add newline at the end to match effect of print call
|
||||
self.assertEquals(self.fake_stdout.make_string(), output + '\n')
|
||||
@ -140,9 +160,11 @@ class CLITest(unittest.TestCase):
|
||||
self.fail("No port created")
|
||||
port_id = port_list[0].uuid
|
||||
# Fill CLI template
|
||||
output = cli.prepare_output('create_port', self.tenant_id,
|
||||
output = cli.prepare_output('create_port',
|
||||
self.tenant_id,
|
||||
dict(network_id=network_id,
|
||||
port_id=port_id))
|
||||
port_id=port_id),
|
||||
self.version)
|
||||
# Verify!
|
||||
# Must add newline at the end to match effect of print call
|
||||
self.assertEquals(self.fake_stdout.make_string(), output + '\n')
|
||||
@ -153,9 +175,11 @@ class CLITest(unittest.TestCase):
|
||||
if len(port_list) != 0:
|
||||
self.fail("DB should not contain any port")
|
||||
# Fill CLI template
|
||||
output = cli.prepare_output('delete_port', self.tenant_id,
|
||||
output = cli.prepare_output('delete_port',
|
||||
self.tenant_id,
|
||||
dict(network_id=network_id,
|
||||
port_id=port_id))
|
||||
port_id=port_id),
|
||||
self.version)
|
||||
# Verify!
|
||||
# Must add newline at the end to match effect of print call
|
||||
self.assertEquals(self.fake_stdout.make_string(), output + '\n')
|
||||
@ -163,11 +187,15 @@ class CLITest(unittest.TestCase):
|
||||
def _verify_update_port(self, network_id, port_id):
|
||||
# Verification - get raw result from db
|
||||
port = db.port_get(port_id, network_id)
|
||||
port_data = {'id': port.uuid, 'state': port.state}
|
||||
port_data = {'id': port.uuid,
|
||||
'state': port.state,
|
||||
'op-status': port.op_status}
|
||||
# Fill CLI template
|
||||
output = cli.prepare_output('update_port', self.tenant_id,
|
||||
output = cli.prepare_output('update_port',
|
||||
self.tenant_id,
|
||||
dict(network_id=network_id,
|
||||
port=port_data))
|
||||
port=port_data),
|
||||
self.version)
|
||||
# Verify!
|
||||
# Must add newline at the end to match effect of print call
|
||||
self.assertEquals(self.fake_stdout.make_string(), output + '\n')
|
||||
@ -177,15 +205,19 @@ class CLITest(unittest.TestCase):
|
||||
# TODO(salvatore-orlando): Must resolve this issue with
|
||||
# attachment in separate bug fix.
|
||||
port = db.port_get(port_id, network_id)
|
||||
port_data = {'id': port.uuid, 'state': port.state,
|
||||
'attachment': "<none>"}
|
||||
port_data = {'id': port.uuid,
|
||||
'state': port.state,
|
||||
'attachment': "<none>",
|
||||
'op-status': port.op_status}
|
||||
if port.interface_id is not None:
|
||||
port_data['attachment'] = port.interface_id
|
||||
|
||||
# Fill CLI template
|
||||
output = cli.prepare_output('show_port', self.tenant_id,
|
||||
output = cli.prepare_output('show_port',
|
||||
self.tenant_id,
|
||||
dict(network_id=network_id,
|
||||
port=port_data))
|
||||
port=port_data),
|
||||
self.version)
|
||||
# Verify!
|
||||
# Must add newline at the end to match effect of print call
|
||||
self.assertEquals(self.fake_stdout.make_string(), output + '\n')
|
||||
@ -194,10 +226,12 @@ class CLITest(unittest.TestCase):
|
||||
# Verification - get raw result from db
|
||||
port = db.port_get(port_id, network_id)
|
||||
# Fill CLI template
|
||||
output = cli.prepare_output("plug_iface", self.tenant_id,
|
||||
output = cli.prepare_output("plug_iface",
|
||||
self.tenant_id,
|
||||
dict(network_id=network_id,
|
||||
port_id=port['uuid'],
|
||||
attachment=port['interface_id']))
|
||||
attachment=port['interface_id']),
|
||||
self.version)
|
||||
# Verify!
|
||||
# Must add newline at the end to match effect of print call
|
||||
self.assertEquals(self.fake_stdout.make_string(), output + '\n')
|
||||
@ -206,9 +240,11 @@ class CLITest(unittest.TestCase):
|
||||
# Verification - get raw result from db
|
||||
port = db.port_get(port_id, network_id)
|
||||
# Fill CLI template
|
||||
output = cli.prepare_output("unplug_iface", self.tenant_id,
|
||||
output = cli.prepare_output("unplug_iface",
|
||||
self.tenant_id,
|
||||
dict(network_id=network_id,
|
||||
port_id=port['uuid']))
|
||||
port_id=port['uuid']),
|
||||
self.version)
|
||||
# Verify!
|
||||
# Must add newline at the end to match effect of print call
|
||||
self.assertEquals(self.fake_stdout.make_string(), output + '\n')
|
||||
@ -219,7 +255,9 @@ class CLITest(unittest.TestCase):
|
||||
db.network_create(self.tenant_id, self.network_name_1)
|
||||
db.network_create(self.tenant_id, self.network_name_2)
|
||||
|
||||
cli.list_nets(self.client, self.tenant_id)
|
||||
cli.list_nets(self.client,
|
||||
self.tenant_id,
|
||||
self.version)
|
||||
except:
|
||||
LOG.exception("Exception caught: %s", sys.exc_info())
|
||||
self.fail("test_list_networks failed due to an exception")
|
||||
@ -230,7 +268,10 @@ class CLITest(unittest.TestCase):
|
||||
|
||||
def test_create_network(self):
|
||||
try:
|
||||
cli.create_net(self.client, self.tenant_id, "test")
|
||||
cli.create_net(self.client,
|
||||
self.tenant_id,
|
||||
"test",
|
||||
self.version)
|
||||
except:
|
||||
LOG.exception("Exception caught: %s", sys.exc_info())
|
||||
self.fail("test_create_network failed due to an exception")
|
||||
@ -243,7 +284,10 @@ class CLITest(unittest.TestCase):
|
||||
try:
|
||||
db.network_create(self.tenant_id, self.network_name_1)
|
||||
network_id = db.network_list(self.tenant_id)[0]['uuid']
|
||||
cli.delete_net(self.client, self.tenant_id, network_id)
|
||||
cli.delete_net(self.client,
|
||||
self.tenant_id,
|
||||
network_id,
|
||||
self.version)
|
||||
except:
|
||||
LOG.exception("Exception caught: %s", sys.exc_info())
|
||||
self.fail("test_delete_network failed due to an exception")
|
||||
@ -256,7 +300,10 @@ class CLITest(unittest.TestCase):
|
||||
try:
|
||||
# Load some data into the datbase
|
||||
net = db.network_create(self.tenant_id, self.network_name_1)
|
||||
cli.show_net(self.client, self.tenant_id, net['uuid'])
|
||||
cli.show_net(self.client,
|
||||
self.tenant_id,
|
||||
net['uuid'],
|
||||
self.version)
|
||||
except:
|
||||
LOG.exception("Exception caught: %s", sys.exc_info())
|
||||
self.fail("test_detail_network failed due to an exception")
|
||||
@ -269,8 +316,11 @@ class CLITest(unittest.TestCase):
|
||||
try:
|
||||
net = db.network_create(self.tenant_id, self.network_name_1)
|
||||
network_id = net['uuid']
|
||||
cli.update_net(self.client, self.tenant_id,
|
||||
network_id, 'name=%s' % self.network_name_2)
|
||||
cli.update_net(self.client,
|
||||
self.tenant_id,
|
||||
network_id,
|
||||
'name=%s' % self.network_name_2,
|
||||
self.version)
|
||||
except:
|
||||
LOG.exception("Exception caught: %s", sys.exc_info())
|
||||
self.fail("test_update_network failed due to an exception")
|
||||
@ -286,7 +336,10 @@ class CLITest(unittest.TestCase):
|
||||
network_id = net['uuid']
|
||||
db.port_create(network_id)
|
||||
db.port_create(network_id)
|
||||
cli.list_ports(self.client, self.tenant_id, network_id)
|
||||
cli.list_ports(self.client,
|
||||
self.tenant_id,
|
||||
network_id,
|
||||
self.version)
|
||||
except:
|
||||
LOG.exception("Exception caught: %s", sys.exc_info())
|
||||
self.fail("test_list_ports failed due to an exception")
|
||||
@ -301,7 +354,10 @@ class CLITest(unittest.TestCase):
|
||||
# Pre-populate data for testing using db api
|
||||
net = db.network_create(self.tenant_id, self.network_name_1)
|
||||
network_id = net['uuid']
|
||||
cli.create_port(self.client, self.tenant_id, network_id)
|
||||
cli.create_port(self.client,
|
||||
self.tenant_id,
|
||||
network_id,
|
||||
self.version)
|
||||
except:
|
||||
LOG.exception("Exception caught: %s", sys.exc_info())
|
||||
self.fail("test_create_port failed due to an exception")
|
||||
@ -319,7 +375,11 @@ class CLITest(unittest.TestCase):
|
||||
network_id = net['uuid']
|
||||
port = db.port_create(network_id)
|
||||
port_id = port['uuid']
|
||||
cli.delete_port(self.client, self.tenant_id, network_id, port_id)
|
||||
cli.delete_port(self.client,
|
||||
self.tenant_id,
|
||||
network_id,
|
||||
port_id,
|
||||
self.version)
|
||||
except:
|
||||
LOG.exception("Exception caught: %s", sys.exc_info())
|
||||
self.fail("test_delete_port failed due to an exception")
|
||||
@ -335,8 +395,12 @@ class CLITest(unittest.TestCase):
|
||||
port = db.port_create(network_id)
|
||||
port_id = port['uuid']
|
||||
# Default state is DOWN - change to ACTIVE.
|
||||
cli.update_port(self.client, self.tenant_id, network_id,
|
||||
port_id, 'state=ACTIVE')
|
||||
cli.update_port(self.client,
|
||||
self.tenant_id,
|
||||
network_id,
|
||||
port_id,
|
||||
'state=ACTIVE',
|
||||
self.version)
|
||||
except:
|
||||
LOG.exception("Exception caught: %s", sys.exc_info())
|
||||
self.fail("test_update_port failed due to an exception")
|
||||
@ -354,7 +418,11 @@ class CLITest(unittest.TestCase):
|
||||
network_id = net['uuid']
|
||||
port = db.port_create(network_id)
|
||||
port_id = port['uuid']
|
||||
cli.show_port(self.client, self.tenant_id, network_id, port_id)
|
||||
cli.show_port(self.client,
|
||||
self.tenant_id,
|
||||
network_id,
|
||||
port_id,
|
||||
self.version)
|
||||
except:
|
||||
LOG.exception("Exception caught: %s", sys.exc_info())
|
||||
self.fail("test_show_port_no_attach failed due to an exception")
|
||||
@ -374,7 +442,11 @@ class CLITest(unittest.TestCase):
|
||||
port = db.port_create(network_id)
|
||||
port_id = port['uuid']
|
||||
db.port_set_attachment(port_id, network_id, iface_id)
|
||||
cli.show_port(self.client, self.tenant_id, network_id, port_id)
|
||||
cli.show_port(self.client,
|
||||
self.tenant_id,
|
||||
network_id,
|
||||
port_id,
|
||||
self.version)
|
||||
except:
|
||||
LOG.exception("Exception caught: %s", sys.exc_info())
|
||||
self.fail("test_show_port_with_attach failed due to an exception")
|
||||
@ -392,8 +464,12 @@ class CLITest(unittest.TestCase):
|
||||
network_id = net['uuid']
|
||||
port = db.port_create(net['uuid'])
|
||||
port_id = port['uuid']
|
||||
cli.plug_iface(self.client, self.tenant_id, network_id,
|
||||
port_id, "test_iface_id")
|
||||
cli.plug_iface(self.client,
|
||||
self.tenant_id,
|
||||
network_id,
|
||||
port_id,
|
||||
"test_iface_id",
|
||||
self.version)
|
||||
except:
|
||||
LOG.exception("Exception caught: %s", sys.exc_info())
|
||||
self.fail("test_plug_iface failed due to an exception")
|
||||
@ -412,7 +488,11 @@ class CLITest(unittest.TestCase):
|
||||
port = db.port_create(net['uuid'])
|
||||
port_id = port['uuid']
|
||||
db.port_set_attachment(port_id, network_id, "test_iface_id")
|
||||
cli.unplug_iface(self.client, self.tenant_id, network_id, port_id)
|
||||
cli.unplug_iface(self.client,
|
||||
self.tenant_id,
|
||||
network_id,
|
||||
port_id,
|
||||
self.version)
|
||||
except:
|
||||
LOG.exception("Exception caught: %s", sys.exc_info())
|
||||
self.fail("test_plug_iface failed due to an exception")
|
||||
|
@ -49,30 +49,6 @@ class QuantumException(Exception):
|
||||
return self._error_string
|
||||
|
||||
|
||||
class ProcessExecutionError(IOError):
|
||||
def __init__(self, stdout=None, stderr=None, exit_code=None, cmd=None,
|
||||
description=None):
|
||||
if description is None:
|
||||
description = "Unexpected error while running command."
|
||||
if exit_code is None:
|
||||
exit_code = '-'
|
||||
message = "%s\nCommand: %s\nExit code: %s\nStdout: %r\nStderr: %r" % (
|
||||
description, cmd, exit_code, stdout, stderr)
|
||||
IOError.__init__(self, message)
|
||||
|
||||
|
||||
class Error(Exception):
|
||||
def __init__(self, message=None):
|
||||
super(Error, self).__init__(message)
|
||||
|
||||
|
||||
class ApiError(Error):
|
||||
def __init__(self, message='Unknown', code='Unknown'):
|
||||
self.message = message
|
||||
self.code = code
|
||||
super(ApiError, self).__init__('%s: %s' % (code, message))
|
||||
|
||||
|
||||
class NotFound(QuantumException):
|
||||
pass
|
||||
|
||||
@ -111,34 +87,87 @@ class AlreadyAttached(QuantumException):
|
||||
"already plugged into port %(att_port_id)s")
|
||||
|
||||
|
||||
# NOTE: on the client side, we often do not know all of the information
|
||||
# that is known on the server, thus, we create separate exception for
|
||||
# those scenarios
|
||||
class PortInUseClient(QuantumException):
|
||||
message = _("Unable to complete operation on port %(port_id)s " \
|
||||
"for network %(net_id)s. An attachment " \
|
||||
"is plugged into the logical port.")
|
||||
class QuantumClientException(QuantumException):
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self.message = kwargs.get('message', "")
|
||||
super(QuantumClientException, self).__init__(**kwargs)
|
||||
|
||||
|
||||
class AlreadyAttachedClient(QuantumException):
|
||||
message = _("Unable to plug the attachment %(att_id)s into port " \
|
||||
"%(port_id)s for network %(net_id)s. The attachment is " \
|
||||
"already plugged into another port.")
|
||||
# NOTE: on the client side, we use different exception types in order
|
||||
# to allow client library users to handle server exceptions in try...except
|
||||
# blocks. The actual error message is the one generated on the server side
|
||||
class NetworkNotFoundClient(QuantumClientException):
|
||||
pass
|
||||
|
||||
|
||||
class MalformedRequestBody(QuantumException):
|
||||
message = _("Malformed request body: %(reason)s")
|
||||
class PortNotFoundClient(QuantumClientException):
|
||||
pass
|
||||
|
||||
|
||||
class MalformedResponseBody(QuantumException):
|
||||
message = _("Malformed response body: %(reason)s")
|
||||
|
||||
|
||||
class Duplicate(Error):
|
||||
class StateInvalidClient(QuantumClientException):
|
||||
pass
|
||||
|
||||
|
||||
class NotAuthorized(Error):
|
||||
class NetworkInUseClient(QuantumClientException):
|
||||
pass
|
||||
|
||||
|
||||
class PortInUseClient(QuantumClientException):
|
||||
pass
|
||||
|
||||
|
||||
class AlreadyAttachedClient(QuantumClientException):
|
||||
pass
|
||||
|
||||
|
||||
class NotAuthorized(QuantumClientException):
|
||||
pass
|
||||
|
||||
|
||||
class QuantumCLIError(QuantumClientException):
|
||||
""" Exception raised when command line parsing fails """
|
||||
pass
|
||||
|
||||
|
||||
class BadInputError(Exception):
|
||||
"""Error resulting from a client sending bad input to a server"""
|
||||
pass
|
||||
|
||||
|
||||
class ProcessExecutionError(IOError):
|
||||
def __init__(self, stdout=None, stderr=None, exit_code=None, cmd=None,
|
||||
description=None):
|
||||
if description is None:
|
||||
description = "Unexpected error while running command."
|
||||
if exit_code is None:
|
||||
exit_code = '-'
|
||||
message = "%s\nCommand: %s\nExit code: %s\nStdout: %r\nStderr: %r" % (
|
||||
description, cmd, exit_code, stdout, stderr)
|
||||
IOError.__init__(self, message)
|
||||
|
||||
|
||||
class Error(Exception):
|
||||
def __init__(self, message=None):
|
||||
super(Error, self).__init__(message)
|
||||
|
||||
|
||||
class ApiError(Error):
|
||||
def __init__(self, message='Unknown', code='Unknown'):
|
||||
self.message = message
|
||||
self.code = code
|
||||
super(ApiError, self).__init__('%s: %s' % (code, message))
|
||||
|
||||
|
||||
class MalformedRequestBody(QuantumException):
|
||||
message = _("Malformed request body: %(reason)s")
|
||||
|
||||
|
||||
class Duplicate(Error):
|
||||
pass
|
||||
|
||||
|
||||
@ -154,11 +183,6 @@ class InvalidContentType(Invalid):
|
||||
message = _("Invalid content type %(content_type)s.")
|
||||
|
||||
|
||||
class BadInputError(Exception):
|
||||
"""Error resulting from a client sending bad input to a server"""
|
||||
pass
|
||||
|
||||
|
||||
class MissingArgumentError(Error):
|
||||
pass
|
||||
|
||||
|
@ -22,7 +22,6 @@
|
||||
|
||||
import ConfigParser
|
||||
import datetime
|
||||
import exceptions as exception
|
||||
import inspect
|
||||
import logging
|
||||
import os
|
||||
@ -44,6 +43,18 @@ from quantum.common import exceptions as exception
|
||||
from quantum.common.exceptions import ProcessExecutionError
|
||||
|
||||
|
||||
def env(*vars, **kwargs):
|
||||
"""
|
||||
returns the first environment variable set
|
||||
if none are non-empty, defaults to '' or keyword arg default
|
||||
"""
|
||||
for v in vars:
|
||||
value = os.environ.get(v)
|
||||
if value:
|
||||
return value
|
||||
return kwargs.get('default', '')
|
||||
|
||||
|
||||
def import_class(import_str):
|
||||
"""Returns a class from a string including module and class."""
|
||||
mod_str, _sep, class_str = import_str.rpartition('.')
|
||||
|
Loading…
x
Reference in New Issue
Block a user