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
|
from quantum.common.serializer import Serializer
|
||||||
|
|
||||||
LOG = logging.getLogger('quantum.client')
|
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"
|
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):
|
class ApiCall(object):
|
||||||
"""A Decorator to add support for format and tenant overriding"""
|
"""A Decorator to add support for format and tenant overriding"""
|
||||||
def __init__(self, function):
|
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,
|
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,
|
format="xml", testingStub=None, key_file=None, cert_file=None,
|
||||||
auth_token=None, logger=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.
|
Creates a new client to some service.
|
||||||
|
|
||||||
@ -113,7 +199,24 @@ class Client(object):
|
|||||||
self.cert_file = cert_file
|
self.cert_file = cert_file
|
||||||
self.logger = logger
|
self.logger = logger
|
||||||
self.auth_token = auth_token
|
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):
|
def get_connection_type(self):
|
||||||
"""
|
"""
|
||||||
@ -138,7 +241,7 @@ class Client(object):
|
|||||||
return conn.getresponse()
|
return conn.getresponse()
|
||||||
|
|
||||||
def do_request(self, method, action, body=None,
|
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.
|
Connects to the server and issues a request.
|
||||||
Returns the result data, or raises an appropriate exception if
|
Returns the result data, or raises an appropriate exception if
|
||||||
@ -155,7 +258,6 @@ class Client(object):
|
|||||||
# Ensure we have a tenant id
|
# Ensure we have a tenant id
|
||||||
if not self.tenant:
|
if not self.tenant:
|
||||||
raise Exception("Tenant ID not set")
|
raise Exception("Tenant ID not set")
|
||||||
|
|
||||||
# Add format and tenant_id
|
# Add format and tenant_id
|
||||||
action += ".%s" % self.format
|
action += ".%s" % self.format
|
||||||
action = self.action_prefix + action
|
action = self.action_prefix + action
|
||||||
@ -165,7 +267,6 @@ class Client(object):
|
|||||||
action += '?' + urllib.urlencode(params)
|
action += '?' + urllib.urlencode(params)
|
||||||
if body:
|
if body:
|
||||||
body = self.serialize(body)
|
body = self.serialize(body)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
connection_type = self.get_connection_type()
|
connection_type = self.get_connection_type()
|
||||||
headers = headers or {"Content-Type":
|
headers = headers or {"Content-Type":
|
||||||
@ -176,7 +277,6 @@ class Client(object):
|
|||||||
# Open connection and send request, handling SSL certs
|
# Open connection and send request, handling SSL certs
|
||||||
certs = {'key_file': self.key_file, 'cert_file': self.cert_file}
|
certs = {'key_file': self.key_file, 'cert_file': self.cert_file}
|
||||||
certs = dict((x, certs[x]) for x in certs if certs[x] != None)
|
certs = dict((x, certs[x]) for x in certs if certs[x] != None)
|
||||||
|
|
||||||
if self.use_ssl and len(certs):
|
if self.use_ssl and len(certs):
|
||||||
conn = connection_type(self.host, self.port, **certs)
|
conn = connection_type(self.host, self.port, **certs)
|
||||||
else:
|
else:
|
||||||
@ -184,7 +284,6 @@ class Client(object):
|
|||||||
res = self._send_request(conn, method, action, body, headers)
|
res = self._send_request(conn, method, action, body, headers)
|
||||||
status_code = self.get_status_code(res)
|
status_code = self.get_status_code(res)
|
||||||
data = res.read()
|
data = res.read()
|
||||||
|
|
||||||
if self.logger:
|
if self.logger:
|
||||||
self.logger.debug("Quantum Client Reply (code = %s) :\n %s" \
|
self.logger.debug("Quantum Client Reply (code = %s) :\n %s" \
|
||||||
% (str(status_code), data))
|
% (str(status_code), data))
|
||||||
@ -194,17 +293,7 @@ class Client(object):
|
|||||||
httplib.NO_CONTENT):
|
httplib.NO_CONTENT):
|
||||||
return self.deserialize(data, status_code)
|
return self.deserialize(data, status_code)
|
||||||
else:
|
else:
|
||||||
error_message = res.read()
|
self._handle_fault_response(status_code, data)
|
||||||
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
|
|
||||||
except (socket.error, IOError), e:
|
except (socket.error, IOError), e:
|
||||||
msg = "Unable to connect to server. Got error: %s" % e
|
msg = "Unable to connect to server. Got error: %s" % e
|
||||||
LOG.exception(msg)
|
LOG.exception(msg)
|
||||||
@ -263,8 +352,7 @@ class Client(object):
|
|||||||
"""
|
"""
|
||||||
Fetches the details of a certain network
|
Fetches the details of a certain network
|
||||||
"""
|
"""
|
||||||
return self.do_request("GET", self.network_path % (network),
|
return self.do_request("GET", self.network_path % (network))
|
||||||
exception_args={"net_id": network})
|
|
||||||
|
|
||||||
@ApiCall
|
@ApiCall
|
||||||
def create_network(self, body=None):
|
def create_network(self, body=None):
|
||||||
@ -278,16 +366,14 @@ class Client(object):
|
|||||||
"""
|
"""
|
||||||
Updates a network
|
Updates a network
|
||||||
"""
|
"""
|
||||||
return self.do_request("PUT", self.network_path % (network), body=body,
|
return self.do_request("PUT", self.network_path % (network), body=body)
|
||||||
exception_args={"net_id": network})
|
|
||||||
|
|
||||||
@ApiCall
|
@ApiCall
|
||||||
def delete_network(self, network):
|
def delete_network(self, network):
|
||||||
"""
|
"""
|
||||||
Deletes the specified network
|
Deletes the specified network
|
||||||
"""
|
"""
|
||||||
return self.do_request("DELETE", self.network_path % (network),
|
return self.do_request("DELETE", self.network_path % (network))
|
||||||
exception_args={"net_id": network})
|
|
||||||
|
|
||||||
@ApiCall
|
@ApiCall
|
||||||
def list_ports(self, network):
|
def list_ports(self, network):
|
||||||
@ -301,24 +387,21 @@ class Client(object):
|
|||||||
"""
|
"""
|
||||||
Fetches the details of a certain port
|
Fetches the details of a certain port
|
||||||
"""
|
"""
|
||||||
return self.do_request("GET", self.port_path % (network, port),
|
return self.do_request("GET", self.port_path % (network, port))
|
||||||
exception_args={"net_id": network, "port_id": port})
|
|
||||||
|
|
||||||
@ApiCall
|
@ApiCall
|
||||||
def create_port(self, network, body=None):
|
def create_port(self, network, body=None):
|
||||||
"""
|
"""
|
||||||
Creates a new port on a given network
|
Creates a new port on a given network
|
||||||
"""
|
"""
|
||||||
return self.do_request("POST", self.ports_path % (network), body=body,
|
return self.do_request("POST", self.ports_path % (network), body=body)
|
||||||
exception_args={"net_id": network})
|
|
||||||
|
|
||||||
@ApiCall
|
@ApiCall
|
||||||
def delete_port(self, network, port):
|
def delete_port(self, network, port):
|
||||||
"""
|
"""
|
||||||
Deletes the specified port from a network
|
Deletes the specified port from a network
|
||||||
"""
|
"""
|
||||||
return self.do_request("DELETE", self.port_path % (network, port),
|
return self.do_request("DELETE", self.port_path % (network, port))
|
||||||
exception_args={"net_id": network, "port_id": port})
|
|
||||||
|
|
||||||
@ApiCall
|
@ApiCall
|
||||||
def update_port(self, network, port, body=None):
|
def update_port(self, network, port, body=None):
|
||||||
@ -326,17 +409,14 @@ class Client(object):
|
|||||||
Sets the attributes of the specified port
|
Sets the attributes of the specified port
|
||||||
"""
|
"""
|
||||||
return self.do_request("PUT",
|
return self.do_request("PUT",
|
||||||
self.port_path % (network, port), body=body,
|
self.port_path % (network, port), body=body)
|
||||||
exception_args={"net_id": network,
|
|
||||||
"port_id": port})
|
|
||||||
|
|
||||||
@ApiCall
|
@ApiCall
|
||||||
def show_port_attachment(self, network, port):
|
def show_port_attachment(self, network, port):
|
||||||
"""
|
"""
|
||||||
Fetches the attachment-id associated with the specified port
|
Fetches the attachment-id associated with the specified port
|
||||||
"""
|
"""
|
||||||
return self.do_request("GET", self.attachment_path % (network, port),
|
return self.do_request("GET", self.attachment_path % (network, port))
|
||||||
exception_args={"net_id": network, "port_id": port})
|
|
||||||
|
|
||||||
@ApiCall
|
@ApiCall
|
||||||
def attach_resource(self, network, port, body=None):
|
def attach_resource(self, network, port, body=None):
|
||||||
@ -344,10 +424,7 @@ class Client(object):
|
|||||||
Sets the attachment-id of the specified port
|
Sets the attachment-id of the specified port
|
||||||
"""
|
"""
|
||||||
return self.do_request("PUT",
|
return self.do_request("PUT",
|
||||||
self.attachment_path % (network, port), body=body,
|
self.attachment_path % (network, port), body=body)
|
||||||
exception_args={"net_id": network,
|
|
||||||
"port_id": port,
|
|
||||||
"attach_id": str(body)})
|
|
||||||
|
|
||||||
@ApiCall
|
@ApiCall
|
||||||
def detach_resource(self, network, port):
|
def detach_resource(self, network, port):
|
||||||
@ -355,5 +432,28 @@ class Client(object):
|
|||||||
Removes the attachment-id of the specified port
|
Removes the attachment-id of the specified port
|
||||||
"""
|
"""
|
||||||
return self.do_request("DELETE",
|
return self.do_request("DELETE",
|
||||||
self.attachment_path % (network, port),
|
self.attachment_path % (network, port))
|
||||||
exception_args={"net_id": network, "port_id": 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
|
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||||
|
|
||||||
# Copyright 2011 Nicira Networks, Inc.
|
# Copyright 2012 Nicira Networks, Inc.
|
||||||
# Copyright 2011 Citrix Systems
|
# Copyright 2012 Citrix Systems
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# 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
|
# not use this file except in compliance with the License. You may obtain
|
||||||
@ -26,6 +26,7 @@ import sys
|
|||||||
|
|
||||||
from optparse import OptionParser
|
from optparse import OptionParser
|
||||||
|
|
||||||
|
from quantum.common import exceptions
|
||||||
|
|
||||||
possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]),
|
possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]),
|
||||||
os.pardir,
|
os.pardir,
|
||||||
@ -37,13 +38,16 @@ gettext.install('quantum', unicode=1)
|
|||||||
|
|
||||||
from quantum.client import cli_lib
|
from quantum.client import cli_lib
|
||||||
from quantum.client import Client
|
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
|
#Configure logger for client - cli logger is a child of it
|
||||||
#NOTE(salvatore-orlando): logger name does not map to package
|
#NOTE(salvatore-orlando): logger name does not map to package
|
||||||
#this is deliberate. Simplifies logger configuration
|
#this is deliberate. Simplifies logger configuration
|
||||||
LOG = logging.getLogger('quantum')
|
LOG = logging.getLogger('quantum')
|
||||||
|
DEFAULT_QUANTUM_VERSION = '1.1'
|
||||||
FORMAT = 'json'
|
FORMAT = 'json'
|
||||||
commands = {
|
commands_v10 = {
|
||||||
"list_nets": {
|
"list_nets": {
|
||||||
"func": cli_lib.list_nets,
|
"func": cli_lib.list_nets,
|
||||||
"args": ["tenant-id"]},
|
"args": ["tenant-id"]},
|
||||||
@ -81,36 +85,122 @@ commands = {
|
|||||||
"func": cli_lib.unplug_iface,
|
"func": cli_lib.unplug_iface,
|
||||||
"args": ["tenant-id", "net-id", "port-id"]}, }
|
"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:"
|
print "\nCommands:"
|
||||||
for k in commands.keys():
|
cmds = commands[version]
|
||||||
print " %s %s" % (k,
|
for k in cmds.keys():
|
||||||
" ".join(["<%s>" % y for y in commands[k]["args"]]))
|
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):
|
def build_args(cmd, cmdargs, arglist):
|
||||||
args = []
|
arglist_len = len(arglist)
|
||||||
orig_arglist = arglist[:]
|
cmdargs_len = len(cmdargs)
|
||||||
try:
|
if arglist_len < cmdargs_len:
|
||||||
for x in cmdargs:
|
message = "Not enough arguments for \"%s\" (expected: %d, got: %d)"\
|
||||||
args.append(arglist[0])
|
% (cmd, len(cmdargs), arglist_len)
|
||||||
del arglist[0]
|
raise exceptions.QuantumCLIError(message=message)
|
||||||
except:
|
args = arglist[:cmdargs_len]
|
||||||
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
|
|
||||||
return args
|
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():
|
def main():
|
||||||
usagestr = "Usage: %prog [OPTIONS] <command> [args]"
|
usagestr = "Usage: %prog [OPTIONS] <command> [args]"
|
||||||
parser = OptionParser(usage=usagestr)
|
parser = OptionParser(usage=usagestr)
|
||||||
@ -126,13 +216,15 @@ def main():
|
|||||||
type="string", default="syslog", help="log file path")
|
type="string", default="syslog", help="log file path")
|
||||||
parser.add_option("-t", "--token", dest="token",
|
parser.add_option("-t", "--token", dest="token",
|
||||||
type="string", default=None, help="authentication 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()
|
options, args = parser.parse_args()
|
||||||
|
|
||||||
if options.verbose:
|
if options.verbose:
|
||||||
LOG.setLevel(logging.DEBUG)
|
LOG.setLevel(logging.DEBUG)
|
||||||
else:
|
else:
|
||||||
LOG.setLevel(logging.WARN)
|
LOG.setLevel(logging.WARN)
|
||||||
#logging.handlers.WatchedFileHandler
|
|
||||||
|
|
||||||
if options.logfile == "syslog":
|
if options.logfile == "syslog":
|
||||||
LOG.addHandler(logging.handlers.SysLogHandler(address='/dev/log'))
|
LOG.addHandler(logging.handlers.SysLogHandler(address='/dev/log'))
|
||||||
@ -141,29 +233,45 @@ def main():
|
|||||||
# Set permissions on log file
|
# Set permissions on log file
|
||||||
os.chmod(options.logfile, 0644)
|
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:
|
if len(args) < 1:
|
||||||
parser.print_help()
|
parser.print_help()
|
||||||
help()
|
help(version)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
cmd = args[0]
|
cmd = args[0]
|
||||||
if cmd not in commands.keys():
|
if cmd not in commands[version].keys():
|
||||||
LOG.error("Unknown command: %s" % cmd)
|
LOG.error("Unknown command: %s" % cmd)
|
||||||
help()
|
help(version)
|
||||||
sys.exit(1)
|
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:
|
if not args:
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
LOG.info("Executing command \"%s\" with args: %s" % (cmd, args))
|
LOG.info("Executing command \"%s\" with args: %s" % (cmd, args))
|
||||||
|
|
||||||
client = Client(options.host, options.port, options.ssl,
|
client = instantiate_client(options.host,
|
||||||
args[0], FORMAT,
|
options.port,
|
||||||
auth_token=options.token)
|
options.ssl,
|
||||||
commands[cmd]["func"](client, *args)
|
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")
|
LOG.info("Command execution completed")
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
||||||
|
@ -91,7 +91,7 @@ class CmdOutputTemplate(OutputTemplate):
|
|||||||
Extends OutputTemplate loading a different template for each command.
|
Extends OutputTemplate loading a different template for each command.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
_templates = {
|
_templates_v10 = {
|
||||||
"list_nets": "Virtual Networks for Tenant %(tenant_id)s\n" +
|
"list_nets": "Virtual Networks for Tenant %(tenant_id)s\n" +
|
||||||
"%(networks|\tNetwork ID: %(id)s)s",
|
"%(networks|\tNetwork ID: %(id)s)s",
|
||||||
"show_net": "Network ID: %(network.id)s\n" +
|
"show_net": "Network ID: %(network.id)s\n" +
|
||||||
@ -130,13 +130,31 @@ class CmdOutputTemplate(OutputTemplate):
|
|||||||
"on Virtual Network: %(network_id)s\n" +
|
"on Virtual Network: %(network_id)s\n" +
|
||||||
"for Tenant: %(tenant_id)s"}
|
"for Tenant: %(tenant_id)s"}
|
||||||
|
|
||||||
def __init__(self, cmd, data):
|
_templates_v11 = _templates_v10.copy()
|
||||||
super(CmdOutputTemplate, self).__init__(self._templates[cmd], data)
|
_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):
|
def _handle_exception(ex):
|
||||||
LOG.exception(sys.exc_info())
|
LOG.exception(sys.exc_info())
|
||||||
print "Exception:%s - %s" % (sys.exc_info()[0], sys.exc_info()[1])
|
|
||||||
status_code = None
|
status_code = None
|
||||||
message = None
|
message = None
|
||||||
# Retrieve dict at 1st element of tuple at last argument
|
# Retrieve dict at 1st element of tuple at last argument
|
||||||
@ -149,67 +167,94 @@ def _handle_exception(ex):
|
|||||||
LOG.exception(msg_1 + "-" + msg_2)
|
LOG.exception(msg_1 + "-" + msg_2)
|
||||||
print msg_1
|
print msg_1
|
||||||
print msg_2
|
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):
|
def prepare_output(cmd, tenant_id, response, version):
|
||||||
LOG.debug("Preparing output for response:%s", response)
|
LOG.debug("Preparing output for response:%s, version:%s"
|
||||||
|
% (response, version))
|
||||||
response['tenant_id'] = tenant_id
|
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)
|
LOG.debug("Finished preparing output for command:%s", cmd)
|
||||||
return output
|
return output
|
||||||
|
|
||||||
|
|
||||||
def list_nets(client, *args):
|
def list_nets(client, *args):
|
||||||
tenant_id = args[0]
|
tenant_id, version = args
|
||||||
res = client.list_networks()
|
try:
|
||||||
LOG.debug("Operation 'list_networks' executed.")
|
res = client.list_networks()
|
||||||
output = prepare_output("list_nets", tenant_id, res)
|
LOG.debug("Operation 'list_networks' executed.")
|
||||||
print output
|
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):
|
def create_net(client, *args):
|
||||||
tenant_id, name = args
|
tenant_id, name, version = args
|
||||||
data = {'network': {'name': name}}
|
data = {'network': {'name': name}}
|
||||||
new_net_id = None
|
new_net_id = None
|
||||||
try:
|
try:
|
||||||
res = client.create_network(data)
|
res = client.create_network(data)
|
||||||
new_net_id = res["network"]["id"]
|
new_net_id = res["network"]["id"]
|
||||||
LOG.debug("Operation 'create_network' executed.")
|
LOG.debug("Operation 'create_network' executed.")
|
||||||
output = prepare_output("create_net", tenant_id,
|
output = prepare_output("create_net",
|
||||||
dict(network_id=new_net_id))
|
tenant_id,
|
||||||
|
dict(network_id=new_net_id),
|
||||||
|
version)
|
||||||
print output
|
print output
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
_handle_exception(ex)
|
_handle_exception(ex)
|
||||||
|
|
||||||
|
|
||||||
def delete_net(client, *args):
|
def delete_net(client, *args):
|
||||||
tenant_id, network_id = args
|
tenant_id, network_id, version = args
|
||||||
try:
|
try:
|
||||||
client.delete_network(network_id)
|
client.delete_network(network_id)
|
||||||
LOG.debug("Operation 'delete_network' executed.")
|
LOG.debug("Operation 'delete_network' executed.")
|
||||||
output = prepare_output("delete_net", tenant_id,
|
output = prepare_output("delete_net",
|
||||||
dict(network_id=network_id))
|
tenant_id,
|
||||||
|
dict(network_id=network_id),
|
||||||
|
version)
|
||||||
print output
|
print output
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
_handle_exception(ex)
|
_handle_exception(ex)
|
||||||
|
|
||||||
|
|
||||||
def show_net(client, *args):
|
def show_net(client, *args):
|
||||||
tenant_id, network_id = args
|
tenant_id, network_id, version = args
|
||||||
try:
|
try:
|
||||||
#NOTE(salvatore-orlando) changed for returning exclusively
|
#NOTE(salvatore-orlando) changed for returning exclusively
|
||||||
# output for GET /networks/{net-id} API operation
|
# output for GET /networks/{net-id} API operation
|
||||||
res = client.show_network_details(network_id)["network"]
|
res = client.show_network_details(network_id)["network"]
|
||||||
LOG.debug("Operation 'show_network_details' executed.")
|
LOG.debug("Operation 'show_network_details' executed.")
|
||||||
output = prepare_output("show_net", tenant_id,
|
output = prepare_output("show_net",
|
||||||
dict(network=res))
|
tenant_id,
|
||||||
|
dict(network=res),
|
||||||
|
version)
|
||||||
print output
|
print output
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
_handle_exception(ex)
|
_handle_exception(ex)
|
||||||
|
|
||||||
|
|
||||||
def update_net(client, *args):
|
def update_net(client, *args):
|
||||||
tenant_id, network_id, param_data = args
|
tenant_id, network_id, param_data, version = args
|
||||||
data = {'network': {}}
|
data = {'network': {}}
|
||||||
for kv in param_data.split(","):
|
for kv in param_data.split(","):
|
||||||
k, v = kv.split("=")
|
k, v = kv.split("=")
|
||||||
@ -219,47 +264,67 @@ def update_net(client, *args):
|
|||||||
client.update_network(network_id, data)
|
client.update_network(network_id, data)
|
||||||
LOG.debug("Operation 'update_network' executed.")
|
LOG.debug("Operation 'update_network' executed.")
|
||||||
# Response has no body. Use data for populating output
|
# 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
|
print output
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
_handle_exception(ex)
|
_handle_exception(ex)
|
||||||
|
|
||||||
|
|
||||||
def list_ports(client, *args):
|
def list_ports(client, *args):
|
||||||
tenant_id, network_id = args
|
tenant_id, network_id, version = args
|
||||||
try:
|
try:
|
||||||
ports = client.list_ports(network_id)
|
ports = client.list_ports(network_id)
|
||||||
LOG.debug("Operation 'list_ports' executed.")
|
LOG.debug("Operation 'list_ports' executed.")
|
||||||
data = ports
|
data = ports
|
||||||
data['network_id'] = network_id
|
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
|
print output
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
_handle_exception(ex)
|
_handle_exception(ex)
|
||||||
|
|
||||||
|
|
||||||
def create_port(client, *args):
|
def create_port(client, *args):
|
||||||
tenant_id, network_id = args
|
tenant_id, network_id, version = args
|
||||||
try:
|
try:
|
||||||
res = client.create_port(network_id)
|
res = client.create_port(network_id)
|
||||||
LOG.debug("Operation 'create_port' executed.")
|
LOG.debug("Operation 'create_port' executed.")
|
||||||
new_port_id = res["port"]["id"]
|
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,
|
dict(network_id=network_id,
|
||||||
port_id=new_port_id))
|
port_id=new_port_id),
|
||||||
|
version)
|
||||||
print output
|
print output
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
_handle_exception(ex)
|
_handle_exception(ex)
|
||||||
|
|
||||||
|
|
||||||
def delete_port(client, *args):
|
def delete_port(client, *args):
|
||||||
tenant_id, network_id, port_id = args
|
tenant_id, network_id, port_id, version = args
|
||||||
try:
|
try:
|
||||||
client.delete_port(network_id, port_id)
|
client.delete_port(network_id, port_id)
|
||||||
LOG.debug("Operation 'delete_port' executed.")
|
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,
|
dict(network_id=network_id,
|
||||||
port_id=port_id))
|
port_id=port_id),
|
||||||
|
version)
|
||||||
print output
|
print output
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
_handle_exception(ex)
|
_handle_exception(ex)
|
||||||
@ -267,7 +332,7 @@ def delete_port(client, *args):
|
|||||||
|
|
||||||
|
|
||||||
def show_port(client, *args):
|
def show_port(client, *args):
|
||||||
tenant_id, network_id, port_id = args
|
tenant_id, network_id, port_id, version = args
|
||||||
try:
|
try:
|
||||||
port = client.show_port_details(network_id, port_id)["port"]
|
port = client.show_port_details(network_id, port_id)["port"]
|
||||||
LOG.debug("Operation 'list_port_details' executed.")
|
LOG.debug("Operation 'list_port_details' executed.")
|
||||||
@ -280,16 +345,18 @@ def show_port(client, *args):
|
|||||||
port['attachment'] = attach['id']
|
port['attachment'] = attach['id']
|
||||||
else:
|
else:
|
||||||
port['attachment'] = '<none>'
|
port['attachment'] = '<none>'
|
||||||
output = prepare_output("show_port", tenant_id,
|
output = prepare_output("show_port",
|
||||||
|
tenant_id,
|
||||||
dict(network_id=network_id,
|
dict(network_id=network_id,
|
||||||
port=port))
|
port=port),
|
||||||
|
version)
|
||||||
print output
|
print output
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
_handle_exception(ex)
|
_handle_exception(ex)
|
||||||
|
|
||||||
|
|
||||||
def update_port(client, *args):
|
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': {}}
|
data = {'port': {}}
|
||||||
for kv in param_data.split(","):
|
for kv in param_data.split(","):
|
||||||
k, v = kv.split("=")
|
k, v = kv.split("=")
|
||||||
@ -300,14 +367,14 @@ def update_port(client, *args):
|
|||||||
client.update_port(network_id, port_id, data)
|
client.update_port(network_id, port_id, data)
|
||||||
LOG.debug("Operation 'udpate_port' executed.")
|
LOG.debug("Operation 'udpate_port' executed.")
|
||||||
# Response has no body. Use data for populating output
|
# 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
|
print output
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
_handle_exception(ex)
|
_handle_exception(ex)
|
||||||
|
|
||||||
|
|
||||||
def plug_iface(client, *args):
|
def plug_iface(client, *args):
|
||||||
tenant_id, network_id, port_id, attachment = args
|
tenant_id, network_id, port_id, attachment, version = args
|
||||||
try:
|
try:
|
||||||
data = {'attachment': {'id': '%s' % attachment}}
|
data = {'attachment': {'id': '%s' % attachment}}
|
||||||
client.attach_resource(network_id, port_id, data)
|
client.attach_resource(network_id, port_id, data)
|
||||||
@ -315,20 +382,23 @@ def plug_iface(client, *args):
|
|||||||
output = prepare_output("plug_iface", tenant_id,
|
output = prepare_output("plug_iface", tenant_id,
|
||||||
dict(network_id=network_id,
|
dict(network_id=network_id,
|
||||||
port_id=port_id,
|
port_id=port_id,
|
||||||
attachment=attachment))
|
attachment=attachment),
|
||||||
|
version)
|
||||||
print output
|
print output
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
_handle_exception(ex)
|
_handle_exception(ex)
|
||||||
|
|
||||||
|
|
||||||
def unplug_iface(client, *args):
|
def unplug_iface(client, *args):
|
||||||
tenant_id, network_id, port_id = args
|
tenant_id, network_id, port_id, version = args
|
||||||
try:
|
try:
|
||||||
client.detach_resource(network_id, port_id)
|
client.detach_resource(network_id, port_id)
|
||||||
LOG.debug("Operation 'detach_resource' executed.")
|
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,
|
dict(network_id=network_id,
|
||||||
port_id=port_id))
|
port_id=port_id),
|
||||||
|
version)
|
||||||
print output
|
print output
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
_handle_exception(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
|
from quantum.tests.unit.client_tools import stubs as client_stubs
|
||||||
|
|
||||||
LOG = logging.getLogger('quantum.tests.test_cli')
|
LOG = logging.getLogger('quantum.tests.test_cli')
|
||||||
|
API_VERSION = "1.1"
|
||||||
FORMAT = 'json'
|
FORMAT = 'json'
|
||||||
|
|
||||||
|
|
||||||
@ -49,9 +50,12 @@ class CLITest(unittest.TestCase):
|
|||||||
self.tenant_id = "test_tenant"
|
self.tenant_id = "test_tenant"
|
||||||
self.network_name_1 = "test_network_1"
|
self.network_name_1 = "test_network_1"
|
||||||
self.network_name_2 = "test_network_2"
|
self.network_name_2 = "test_network_2"
|
||||||
|
self.version = API_VERSION
|
||||||
# Prepare client and plugin manager
|
# Prepare client and plugin manager
|
||||||
self.client = Client(tenant=self.tenant_id, format=FORMAT,
|
self.client = Client(tenant=self.tenant_id,
|
||||||
testingStub=client_stubs.FakeHTTPConnection)
|
format=FORMAT,
|
||||||
|
testingStub=client_stubs.FakeHTTPConnection,
|
||||||
|
version=self.version)
|
||||||
# Redirect stdout
|
# Redirect stdout
|
||||||
self.fake_stdout = client_stubs.FakeStdout()
|
self.fake_stdout = client_stubs.FakeStdout()
|
||||||
sys.stdout = self.fake_stdout
|
sys.stdout = self.fake_stdout
|
||||||
@ -64,10 +68,13 @@ class CLITest(unittest.TestCase):
|
|||||||
def _verify_list_networks(self):
|
def _verify_list_networks(self):
|
||||||
# Verification - get raw result from db
|
# Verification - get raw result from db
|
||||||
nw_list = db.network_list(self.tenant_id)
|
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
|
# Fill CLI template
|
||||||
output = cli.prepare_output('list_nets', self.tenant_id,
|
output = cli.prepare_output('list_nets',
|
||||||
dict(networks=networks))
|
self.tenant_id,
|
||||||
|
dict(networks=networks),
|
||||||
|
self.version)
|
||||||
# Verify!
|
# Verify!
|
||||||
# Must add newline at the end to match effect of print call
|
# Must add newline at the end to match effect of print call
|
||||||
self.assertEquals(self.fake_stdout.make_string(), output + '\n')
|
self.assertEquals(self.fake_stdout.make_string(), output + '\n')
|
||||||
@ -79,8 +86,10 @@ class CLITest(unittest.TestCase):
|
|||||||
self.fail("No network created")
|
self.fail("No network created")
|
||||||
network_id = nw_list[0].uuid
|
network_id = nw_list[0].uuid
|
||||||
# Fill CLI template
|
# Fill CLI template
|
||||||
output = cli.prepare_output('create_net', self.tenant_id,
|
output = cli.prepare_output('create_net',
|
||||||
dict(network_id=network_id))
|
self.tenant_id,
|
||||||
|
dict(network_id=network_id),
|
||||||
|
self.version)
|
||||||
# Verify!
|
# Verify!
|
||||||
# Must add newline at the end to match effect of print call
|
# Must add newline at the end to match effect of print call
|
||||||
self.assertEquals(self.fake_stdout.make_string(), output + '\n')
|
self.assertEquals(self.fake_stdout.make_string(), output + '\n')
|
||||||
@ -91,8 +100,10 @@ class CLITest(unittest.TestCase):
|
|||||||
if len(nw_list) != 0:
|
if len(nw_list) != 0:
|
||||||
self.fail("DB should not contain any network")
|
self.fail("DB should not contain any network")
|
||||||
# Fill CLI template
|
# Fill CLI template
|
||||||
output = cli.prepare_output('delete_net', self.tenant_id,
|
output = cli.prepare_output('delete_net',
|
||||||
dict(network_id=network_id))
|
self.tenant_id,
|
||||||
|
dict(network_id=network_id),
|
||||||
|
self.version)
|
||||||
# Verify!
|
# Verify!
|
||||||
# Must add newline at the end to match effect of print call
|
# Must add newline at the end to match effect of print call
|
||||||
self.assertEquals(self.fake_stdout.make_string(), output + '\n')
|
self.assertEquals(self.fake_stdout.make_string(), output + '\n')
|
||||||
@ -101,10 +112,13 @@ class CLITest(unittest.TestCase):
|
|||||||
# Verification - get raw result from db
|
# Verification - get raw result from db
|
||||||
nw_list = db.network_list(self.tenant_id)
|
nw_list = db.network_list(self.tenant_id)
|
||||||
network_data = {'id': nw_list[0].uuid,
|
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
|
# Fill CLI template
|
||||||
output = cli.prepare_output('update_net', self.tenant_id,
|
output = cli.prepare_output('update_net',
|
||||||
dict(network=network_data))
|
self.tenant_id,
|
||||||
|
dict(network=network_data),
|
||||||
|
self.version)
|
||||||
# Verify!
|
# Verify!
|
||||||
# Must add newline at the end to match effect of print call
|
# Must add newline at the end to match effect of print call
|
||||||
self.assertEquals(self.fake_stdout.make_string(), output + '\n')
|
self.assertEquals(self.fake_stdout.make_string(), output + '\n')
|
||||||
@ -112,10 +126,14 @@ class CLITest(unittest.TestCase):
|
|||||||
def _verify_show_network(self):
|
def _verify_show_network(self):
|
||||||
# Verification - get raw result from db
|
# Verification - get raw result from db
|
||||||
nw = db.network_list(self.tenant_id)[0]
|
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
|
# Fill CLI template
|
||||||
output = cli.prepare_output('show_net', self.tenant_id,
|
output = cli.prepare_output('show_net',
|
||||||
dict(network=network))
|
self.tenant_id,
|
||||||
|
dict(network=network),
|
||||||
|
self.version)
|
||||||
# Verify!
|
# Verify!
|
||||||
# Must add newline at the end to match effect of print call
|
# Must add newline at the end to match effect of print call
|
||||||
self.assertEquals(self.fake_stdout.make_string(), output + '\n')
|
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)
|
ports = [dict(id=port.uuid, state=port.state)
|
||||||
for port in port_list]
|
for port in port_list]
|
||||||
# Fill CLI template
|
# 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,
|
dict(network_id=network_id,
|
||||||
ports=ports))
|
ports=ports),
|
||||||
|
self.version)
|
||||||
# Verify!
|
# Verify!
|
||||||
# Must add newline at the end to match effect of print call
|
# Must add newline at the end to match effect of print call
|
||||||
self.assertEquals(self.fake_stdout.make_string(), output + '\n')
|
self.assertEquals(self.fake_stdout.make_string(), output + '\n')
|
||||||
@ -140,9 +160,11 @@ class CLITest(unittest.TestCase):
|
|||||||
self.fail("No port created")
|
self.fail("No port created")
|
||||||
port_id = port_list[0].uuid
|
port_id = port_list[0].uuid
|
||||||
# Fill CLI template
|
# 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,
|
dict(network_id=network_id,
|
||||||
port_id=port_id))
|
port_id=port_id),
|
||||||
|
self.version)
|
||||||
# Verify!
|
# Verify!
|
||||||
# Must add newline at the end to match effect of print call
|
# Must add newline at the end to match effect of print call
|
||||||
self.assertEquals(self.fake_stdout.make_string(), output + '\n')
|
self.assertEquals(self.fake_stdout.make_string(), output + '\n')
|
||||||
@ -153,9 +175,11 @@ class CLITest(unittest.TestCase):
|
|||||||
if len(port_list) != 0:
|
if len(port_list) != 0:
|
||||||
self.fail("DB should not contain any port")
|
self.fail("DB should not contain any port")
|
||||||
# Fill CLI template
|
# 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,
|
dict(network_id=network_id,
|
||||||
port_id=port_id))
|
port_id=port_id),
|
||||||
|
self.version)
|
||||||
# Verify!
|
# Verify!
|
||||||
# Must add newline at the end to match effect of print call
|
# Must add newline at the end to match effect of print call
|
||||||
self.assertEquals(self.fake_stdout.make_string(), output + '\n')
|
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):
|
def _verify_update_port(self, network_id, port_id):
|
||||||
# Verification - get raw result from db
|
# Verification - get raw result from db
|
||||||
port = db.port_get(port_id, network_id)
|
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
|
# 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,
|
dict(network_id=network_id,
|
||||||
port=port_data))
|
port=port_data),
|
||||||
|
self.version)
|
||||||
# Verify!
|
# Verify!
|
||||||
# Must add newline at the end to match effect of print call
|
# Must add newline at the end to match effect of print call
|
||||||
self.assertEquals(self.fake_stdout.make_string(), output + '\n')
|
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
|
# TODO(salvatore-orlando): Must resolve this issue with
|
||||||
# attachment in separate bug fix.
|
# attachment in separate bug fix.
|
||||||
port = db.port_get(port_id, network_id)
|
port = db.port_get(port_id, network_id)
|
||||||
port_data = {'id': port.uuid, 'state': port.state,
|
port_data = {'id': port.uuid,
|
||||||
'attachment': "<none>"}
|
'state': port.state,
|
||||||
|
'attachment': "<none>",
|
||||||
|
'op-status': port.op_status}
|
||||||
if port.interface_id is not None:
|
if port.interface_id is not None:
|
||||||
port_data['attachment'] = port.interface_id
|
port_data['attachment'] = port.interface_id
|
||||||
|
|
||||||
# Fill CLI template
|
# 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,
|
dict(network_id=network_id,
|
||||||
port=port_data))
|
port=port_data),
|
||||||
|
self.version)
|
||||||
# Verify!
|
# Verify!
|
||||||
# Must add newline at the end to match effect of print call
|
# Must add newline at the end to match effect of print call
|
||||||
self.assertEquals(self.fake_stdout.make_string(), output + '\n')
|
self.assertEquals(self.fake_stdout.make_string(), output + '\n')
|
||||||
@ -194,10 +226,12 @@ class CLITest(unittest.TestCase):
|
|||||||
# Verification - get raw result from db
|
# Verification - get raw result from db
|
||||||
port = db.port_get(port_id, network_id)
|
port = db.port_get(port_id, network_id)
|
||||||
# Fill CLI template
|
# 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,
|
dict(network_id=network_id,
|
||||||
port_id=port['uuid'],
|
port_id=port['uuid'],
|
||||||
attachment=port['interface_id']))
|
attachment=port['interface_id']),
|
||||||
|
self.version)
|
||||||
# Verify!
|
# Verify!
|
||||||
# Must add newline at the end to match effect of print call
|
# Must add newline at the end to match effect of print call
|
||||||
self.assertEquals(self.fake_stdout.make_string(), output + '\n')
|
self.assertEquals(self.fake_stdout.make_string(), output + '\n')
|
||||||
@ -206,9 +240,11 @@ class CLITest(unittest.TestCase):
|
|||||||
# Verification - get raw result from db
|
# Verification - get raw result from db
|
||||||
port = db.port_get(port_id, network_id)
|
port = db.port_get(port_id, network_id)
|
||||||
# Fill CLI template
|
# 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,
|
dict(network_id=network_id,
|
||||||
port_id=port['uuid']))
|
port_id=port['uuid']),
|
||||||
|
self.version)
|
||||||
# Verify!
|
# Verify!
|
||||||
# Must add newline at the end to match effect of print call
|
# Must add newline at the end to match effect of print call
|
||||||
self.assertEquals(self.fake_stdout.make_string(), output + '\n')
|
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_1)
|
||||||
db.network_create(self.tenant_id, self.network_name_2)
|
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:
|
except:
|
||||||
LOG.exception("Exception caught: %s", sys.exc_info())
|
LOG.exception("Exception caught: %s", sys.exc_info())
|
||||||
self.fail("test_list_networks failed due to an exception")
|
self.fail("test_list_networks failed due to an exception")
|
||||||
@ -230,7 +268,10 @@ class CLITest(unittest.TestCase):
|
|||||||
|
|
||||||
def test_create_network(self):
|
def test_create_network(self):
|
||||||
try:
|
try:
|
||||||
cli.create_net(self.client, self.tenant_id, "test")
|
cli.create_net(self.client,
|
||||||
|
self.tenant_id,
|
||||||
|
"test",
|
||||||
|
self.version)
|
||||||
except:
|
except:
|
||||||
LOG.exception("Exception caught: %s", sys.exc_info())
|
LOG.exception("Exception caught: %s", sys.exc_info())
|
||||||
self.fail("test_create_network failed due to an exception")
|
self.fail("test_create_network failed due to an exception")
|
||||||
@ -243,7 +284,10 @@ class CLITest(unittest.TestCase):
|
|||||||
try:
|
try:
|
||||||
db.network_create(self.tenant_id, self.network_name_1)
|
db.network_create(self.tenant_id, self.network_name_1)
|
||||||
network_id = db.network_list(self.tenant_id)[0]['uuid']
|
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:
|
except:
|
||||||
LOG.exception("Exception caught: %s", sys.exc_info())
|
LOG.exception("Exception caught: %s", sys.exc_info())
|
||||||
self.fail("test_delete_network failed due to an exception")
|
self.fail("test_delete_network failed due to an exception")
|
||||||
@ -256,7 +300,10 @@ class CLITest(unittest.TestCase):
|
|||||||
try:
|
try:
|
||||||
# Load some data into the datbase
|
# Load some data into the datbase
|
||||||
net = db.network_create(self.tenant_id, self.network_name_1)
|
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:
|
except:
|
||||||
LOG.exception("Exception caught: %s", sys.exc_info())
|
LOG.exception("Exception caught: %s", sys.exc_info())
|
||||||
self.fail("test_detail_network failed due to an exception")
|
self.fail("test_detail_network failed due to an exception")
|
||||||
@ -269,8 +316,11 @@ class CLITest(unittest.TestCase):
|
|||||||
try:
|
try:
|
||||||
net = db.network_create(self.tenant_id, self.network_name_1)
|
net = db.network_create(self.tenant_id, self.network_name_1)
|
||||||
network_id = net['uuid']
|
network_id = net['uuid']
|
||||||
cli.update_net(self.client, self.tenant_id,
|
cli.update_net(self.client,
|
||||||
network_id, 'name=%s' % self.network_name_2)
|
self.tenant_id,
|
||||||
|
network_id,
|
||||||
|
'name=%s' % self.network_name_2,
|
||||||
|
self.version)
|
||||||
except:
|
except:
|
||||||
LOG.exception("Exception caught: %s", sys.exc_info())
|
LOG.exception("Exception caught: %s", sys.exc_info())
|
||||||
self.fail("test_update_network failed due to an exception")
|
self.fail("test_update_network failed due to an exception")
|
||||||
@ -286,7 +336,10 @@ class CLITest(unittest.TestCase):
|
|||||||
network_id = net['uuid']
|
network_id = net['uuid']
|
||||||
db.port_create(network_id)
|
db.port_create(network_id)
|
||||||
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:
|
except:
|
||||||
LOG.exception("Exception caught: %s", sys.exc_info())
|
LOG.exception("Exception caught: %s", sys.exc_info())
|
||||||
self.fail("test_list_ports failed due to an exception")
|
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
|
# Pre-populate data for testing using db api
|
||||||
net = db.network_create(self.tenant_id, self.network_name_1)
|
net = db.network_create(self.tenant_id, self.network_name_1)
|
||||||
network_id = net['uuid']
|
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:
|
except:
|
||||||
LOG.exception("Exception caught: %s", sys.exc_info())
|
LOG.exception("Exception caught: %s", sys.exc_info())
|
||||||
self.fail("test_create_port failed due to an exception")
|
self.fail("test_create_port failed due to an exception")
|
||||||
@ -319,7 +375,11 @@ class CLITest(unittest.TestCase):
|
|||||||
network_id = net['uuid']
|
network_id = net['uuid']
|
||||||
port = db.port_create(network_id)
|
port = db.port_create(network_id)
|
||||||
port_id = port['uuid']
|
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:
|
except:
|
||||||
LOG.exception("Exception caught: %s", sys.exc_info())
|
LOG.exception("Exception caught: %s", sys.exc_info())
|
||||||
self.fail("test_delete_port failed due to an exception")
|
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 = db.port_create(network_id)
|
||||||
port_id = port['uuid']
|
port_id = port['uuid']
|
||||||
# Default state is DOWN - change to ACTIVE.
|
# Default state is DOWN - change to ACTIVE.
|
||||||
cli.update_port(self.client, self.tenant_id, network_id,
|
cli.update_port(self.client,
|
||||||
port_id, 'state=ACTIVE')
|
self.tenant_id,
|
||||||
|
network_id,
|
||||||
|
port_id,
|
||||||
|
'state=ACTIVE',
|
||||||
|
self.version)
|
||||||
except:
|
except:
|
||||||
LOG.exception("Exception caught: %s", sys.exc_info())
|
LOG.exception("Exception caught: %s", sys.exc_info())
|
||||||
self.fail("test_update_port failed due to an exception")
|
self.fail("test_update_port failed due to an exception")
|
||||||
@ -354,7 +418,11 @@ class CLITest(unittest.TestCase):
|
|||||||
network_id = net['uuid']
|
network_id = net['uuid']
|
||||||
port = db.port_create(network_id)
|
port = db.port_create(network_id)
|
||||||
port_id = port['uuid']
|
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:
|
except:
|
||||||
LOG.exception("Exception caught: %s", sys.exc_info())
|
LOG.exception("Exception caught: %s", sys.exc_info())
|
||||||
self.fail("test_show_port_no_attach failed due to an exception")
|
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 = db.port_create(network_id)
|
||||||
port_id = port['uuid']
|
port_id = port['uuid']
|
||||||
db.port_set_attachment(port_id, network_id, iface_id)
|
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:
|
except:
|
||||||
LOG.exception("Exception caught: %s", sys.exc_info())
|
LOG.exception("Exception caught: %s", sys.exc_info())
|
||||||
self.fail("test_show_port_with_attach failed due to an exception")
|
self.fail("test_show_port_with_attach failed due to an exception")
|
||||||
@ -392,8 +464,12 @@ class CLITest(unittest.TestCase):
|
|||||||
network_id = net['uuid']
|
network_id = net['uuid']
|
||||||
port = db.port_create(net['uuid'])
|
port = db.port_create(net['uuid'])
|
||||||
port_id = port['uuid']
|
port_id = port['uuid']
|
||||||
cli.plug_iface(self.client, self.tenant_id, network_id,
|
cli.plug_iface(self.client,
|
||||||
port_id, "test_iface_id")
|
self.tenant_id,
|
||||||
|
network_id,
|
||||||
|
port_id,
|
||||||
|
"test_iface_id",
|
||||||
|
self.version)
|
||||||
except:
|
except:
|
||||||
LOG.exception("Exception caught: %s", sys.exc_info())
|
LOG.exception("Exception caught: %s", sys.exc_info())
|
||||||
self.fail("test_plug_iface failed due to an exception")
|
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 = db.port_create(net['uuid'])
|
||||||
port_id = port['uuid']
|
port_id = port['uuid']
|
||||||
db.port_set_attachment(port_id, network_id, "test_iface_id")
|
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:
|
except:
|
||||||
LOG.exception("Exception caught: %s", sys.exc_info())
|
LOG.exception("Exception caught: %s", sys.exc_info())
|
||||||
self.fail("test_plug_iface failed due to an exception")
|
self.fail("test_plug_iface failed due to an exception")
|
||||||
|
@ -49,30 +49,6 @@ class QuantumException(Exception):
|
|||||||
return self._error_string
|
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):
|
class NotFound(QuantumException):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -111,34 +87,87 @@ class AlreadyAttached(QuantumException):
|
|||||||
"already plugged into port %(att_port_id)s")
|
"already plugged into port %(att_port_id)s")
|
||||||
|
|
||||||
|
|
||||||
# NOTE: on the client side, we often do not know all of the information
|
class QuantumClientException(QuantumException):
|
||||||
# that is known on the server, thus, we create separate exception for
|
|
||||||
# those scenarios
|
def __init__(self, **kwargs):
|
||||||
class PortInUseClient(QuantumException):
|
self.message = kwargs.get('message', "")
|
||||||
message = _("Unable to complete operation on port %(port_id)s " \
|
super(QuantumClientException, self).__init__(**kwargs)
|
||||||
"for network %(net_id)s. An attachment " \
|
|
||||||
"is plugged into the logical port.")
|
|
||||||
|
|
||||||
|
|
||||||
class AlreadyAttachedClient(QuantumException):
|
# NOTE: on the client side, we use different exception types in order
|
||||||
message = _("Unable to plug the attachment %(att_id)s into port " \
|
# to allow client library users to handle server exceptions in try...except
|
||||||
"%(port_id)s for network %(net_id)s. The attachment is " \
|
# blocks. The actual error message is the one generated on the server side
|
||||||
"already plugged into another port.")
|
class NetworkNotFoundClient(QuantumClientException):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class MalformedRequestBody(QuantumException):
|
class PortNotFoundClient(QuantumClientException):
|
||||||
message = _("Malformed request body: %(reason)s")
|
pass
|
||||||
|
|
||||||
|
|
||||||
class MalformedResponseBody(QuantumException):
|
class MalformedResponseBody(QuantumException):
|
||||||
message = _("Malformed response body: %(reason)s")
|
message = _("Malformed response body: %(reason)s")
|
||||||
|
|
||||||
|
|
||||||
class Duplicate(Error):
|
class StateInvalidClient(QuantumClientException):
|
||||||
pass
|
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
|
pass
|
||||||
|
|
||||||
|
|
||||||
@ -154,11 +183,6 @@ class InvalidContentType(Invalid):
|
|||||||
message = _("Invalid content type %(content_type)s.")
|
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):
|
class MissingArgumentError(Error):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -22,7 +22,6 @@
|
|||||||
|
|
||||||
import ConfigParser
|
import ConfigParser
|
||||||
import datetime
|
import datetime
|
||||||
import exceptions as exception
|
|
||||||
import inspect
|
import inspect
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
@ -44,6 +43,18 @@ from quantum.common import exceptions as exception
|
|||||||
from quantum.common.exceptions import ProcessExecutionError
|
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):
|
def import_class(import_str):
|
||||||
"""Returns a class from a string including module and class."""
|
"""Returns a class from a string including module and class."""
|
||||||
mod_str, _sep, class_str = import_str.rpartition('.')
|
mod_str, _sep, class_str = import_str.rpartition('.')
|
||||||
|
Loading…
x
Reference in New Issue
Block a user