Syncing with lp:quantum

This commit is contained in:
Sumit Naiksatam 2011-08-19 18:48:20 -07:00
commit 9c805ac851
4 changed files with 82 additions and 110 deletions

View File

@ -240,7 +240,7 @@ def api_plug_iface(client, *args):
res = client.attach_resource(nid, pid, data)
except Exception, e:
LOG.error("Failed to plug iface \"%s\" to port \"%s\": %s" % (vid,
pid, output))
pid, e))
return
LOG.debug(res)
print "Plugged interface \"%s\" to port:%s on network:%s" % (vid, pid, nid)
@ -386,6 +386,6 @@ if __name__ == "__main__":
commands[cmd]["api_func"](client, *args)
else:
quantum = QuantumManager()
manager = quantum.get_manager()
manager = quantum.get_plugin()
commands[cmd]["func"](manager, *args)
sys.exit(0)

View File

@ -20,16 +20,32 @@ import httplib
import socket
import urllib
from quantum.common.wsgi import Serializer
from quantum.common import exceptions
EXCEPTIONS = {
400: exceptions.BadInputError,
401: exceptions.NotAuthorized,
420: exceptions.NetworkNotFound,
421: exceptions.NetworkInUse,
422: exceptions.NetworkNameExists,
430: exceptions.PortNotFound,
431: exceptions.StateInvalid,
432: exceptions.PortInUse,
440: exceptions.AlreadyAttached,
441: exceptions.AttachmentNotReady,
}
class api_call(object):
class ApiCall(object):
"""A Decorator to add support for format and tenant overriding"""
def __init__(self, f):
self.f = f
def __init__(self, function):
self.function = function
def __get__(self, instance, owner):
def with_params(*args, **kwargs):
# Temporarily set format and tenant for this request
"""
Temporarily sets the format and tenant for this request
"""
(format, tenant) = (instance.format, instance.tenant)
if 'format' in kwargs:
@ -37,7 +53,7 @@ class api_call(object):
if 'tenant' in kwargs:
instance.tenant = kwargs['tenant']
ret = self.f(instance, *args)
ret = self.function(instance, *args)
(instance.format, instance.tenant) = (format, tenant)
return ret
return with_params
@ -49,7 +65,7 @@ class Client(object):
action_prefix = '/v0.1/tenants/{tenant_id}'
"""Action query strings"""
# Action query strings
networks_path = "/networks"
network_path = "/networks/%s"
ports_path = "/networks/%s/ports"
@ -133,9 +149,9 @@ class Client(object):
certs = dict((x, certs[x]) for x in certs if certs[x] != None)
if self.use_ssl and len(certs):
c = connection_type(self.host, self.port, **certs)
conn = connection_type(self.host, self.port, **certs)
else:
c = connection_type(self.host, self.port)
conn = connection_type(self.host, self.port)
if self.logger:
self.logger.debug("Quantum Client Request:\n" \
@ -143,8 +159,8 @@ class Client(object):
if body:
self.logger.debug(body)
c.request(method, action, body, headers)
res = c.getresponse()
conn.request(method, action, body, headers)
res = conn.getresponse()
status_code = self.get_status_code(res)
data = res.read()
@ -158,6 +174,8 @@ class Client(object):
httplib.NO_CONTENT):
return self.deserialize(data, status_code)
else:
if res.status in EXCEPTIONS:
raise EXCEPTIONS[res.status]()
raise Exception("Server returned error: %s" % res.read())
except (socket.error, IOError), e:
@ -175,6 +193,10 @@ class Client(object):
return response.status
def serialize(self, data):
"""
Serializes a dictionary with a single key (which can contain any
structure) into either xml or json
"""
if data is None:
return None
elif type(data) is dict:
@ -184,65 +206,72 @@ class Client(object):
% type(data))
def deserialize(self, data, status_code):
"""
Deserializes a an xml or json string into a dictionary
"""
if status_code == 202:
return data
return Serializer().deserialize(data, self.content_type())
def content_type(self, format=None):
"""
Returns the mime-type for either 'xml' or 'json'. Defaults to the
currently set format
"""
if not format:
format = self.format
return "application/%s" % (format)
@api_call
@ApiCall
def list_networks(self):
"""
Fetches a list of all networks for a tenant
"""
return self.do_request("GET", self.networks_path)
@api_call
@ApiCall
def show_network_details(self, network):
"""
Fetches the details of a certain network
"""
return self.do_request("GET", self.network_path % (network))
@api_call
@ApiCall
def create_network(self, body=None):
"""
Creates a new network
"""
return self.do_request("POST", self.networks_path, body=body)
@api_call
@ApiCall
def update_network(self, network, body=None):
"""
Updates a network
"""
return self.do_request("PUT", self.network_path % (network), body=body)
@api_call
@ApiCall
def delete_network(self, network):
"""
Deletes the specified network
"""
return self.do_request("DELETE", self.network_path % (network))
@api_call
@ApiCall
def list_ports(self, network):
"""
Fetches a list of ports on a given network
"""
return self.do_request("GET", self.ports_path % (network))
@api_call
@ApiCall
def show_port_details(self, network, port):
"""
Fetches the details of a certain port
"""
return self.do_request("GET", self.port_path % (network, port))
@api_call
@ApiCall
def create_port(self, network, body=None):
"""
Creates a new port on a given network
@ -250,14 +279,14 @@ class Client(object):
body = self.serialize(body)
return self.do_request("POST", self.ports_path % (network), body=body)
@api_call
@ApiCall
def delete_port(self, network, port):
"""
Deletes the specified port from a network
"""
return self.do_request("DELETE", self.port_path % (network, port))
@api_call
@ApiCall
def set_port_state(self, network, port, body=None):
"""
Sets the state of the specified port
@ -265,14 +294,14 @@ class Client(object):
return self.do_request("PUT",
self.port_path % (network, port), body=body)
@api_call
@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))
@api_call
@ApiCall
def attach_resource(self, network, port, body=None):
"""
Sets the attachment-id of the specified port
@ -280,7 +309,7 @@ class Client(object):
return self.do_request("PUT",
self.attachment_path % (network, port), body=body)
@api_call
@ApiCall
def detach_resource(self, network, port):
"""
Removes the attachment-id of the specified port

View File

@ -111,6 +111,10 @@ class AlreadyAttached(QuantumException):
"already plugged into port %(att_port_id)s")
class AttachmentNotReady(QuantumException):
message = _("The attachment %(att_id)s is not ready")
class NetworkNameExists(QuantumException):
message = _("Unable to set network name to %(net_name). " \
"Network with id %(net_id) already has this name for " \

View File

@ -15,106 +15,45 @@
# under the License.
# @author: Dan Wendlandt, Nicira Networks, Inc.
import httplib
import logging as LOG
import json
import socket
import sys
import urllib
from quantum.manager import QuantumManager
from optparse import OptionParser
from quantum.common.wsgi import Serializer
from quantum.cli import MiniClient
import sys
from quantum.client import Client
from quantum.manager import QuantumManager
FORMAT = "json"
CONTENT_TYPE = "application/" + FORMAT
def delete_all_nets(client, tenant_id):
res = client.do_request(tenant_id, 'GET', "/networks." + FORMAT)
resdict = json.loads(res.read())
LOG.debug(resdict)
for n in resdict["networks"]:
def delete_all_nets(client):
res = client.list_networks()
for n in res["networks"]:
nid = n["id"]
res = client.do_request(tenant_id, 'GET',
"/networks/%s/ports.%s" % (nid, FORMAT))
output = res.read()
if res.status != 200:
LOG.error("Failed to list ports: %s" % output)
continue
rd = json.loads(output)
LOG.debug(rd)
for port in rd["ports"]:
pid = port["id"]
data = {'port': {'attachment-id': ''}}
body = Serializer().serialize(data, CONTENT_TYPE)
res = client.do_request(tenant_id, 'DELETE',
"/networks/%s/ports/%s/attachment.%s" % \
(nid, pid, FORMAT), body=body)
output = res.read()
LOG.debug(output)
if res.status != 202:
LOG.error("Failed to unplug iface from port \"%s\": %s" % (vid,
pid, output))
continue
LOG.info("Unplugged interface from port:%s on network:%s" % (pid,
nid))
res = client.do_request(tenant_id, 'DELETE',
"/networks/%s/ports/%s.%s" % (nid, pid, FORMAT))
output = res.read()
if res.status != 202:
LOG.error("Failed to delete port: %s" % output)
continue
pres = client.list_ports(nid)
for port in pres["ports"]:
pid = port['id']
client.detach_resource(nid, pid)
client.delete_port(nid, pid)
print "Deleted Virtual Port:%s " \
"on Virtual Network:%s" % (pid, nid)
res = client.do_request(tenant_id, 'DELETE',
"/networks/" + nid + "." + FORMAT)
status = res.status
if status != 202:
Log.error("Failed to delete network: %s" % nid)
output = res.read()
print output
else:
print "Deleted Virtual Network with ID:%s" % nid
client.delete_network(nid)
print "Deleted Virtual Network with ID:%s" % nid
def create_net_with_attachments(net_name, iface_ids):
def create_net_with_attachments(client, net_name, iface_ids):
data = {'network': {'net-name': '%s' % net_name}}
body = Serializer().serialize(data, CONTENT_TYPE)
res = client.do_request(tenant_id, 'POST',
"/networks." + FORMAT, body=body)
rd = json.loads(res.read())
LOG.debug(rd)
nid = rd["networks"]["network"]["id"]
res = client.create_network(data)
nid = res["networks"]["network"]["id"]
print "Created a new Virtual Network %s with ID:%s" % (net_name, nid)
for iface_id in iface_ids:
res = client.do_request(tenant_id, 'POST',
"/networks/%s/ports.%s" % (nid, FORMAT))
output = res.read()
if res.status != 200:
LOG.error("Failed to create port: %s" % output)
continue
rd = json.loads(output)
new_port_id = rd["ports"]["port"]["id"]
res = client.create_port(nid)
new_port_id = res["ports"]["port"]["id"]
print "Created Virtual Port:%s " \
"on Virtual Network:%s" % (new_port_id, nid)
data = {'port': {'attachment-id': '%s' % iface_id}}
body = Serializer().serialize(data, CONTENT_TYPE)
res = client.do_request(tenant_id, 'PUT',
"/networks/%s/ports/%s/attachment.%s" %\
(nid, new_port_id, FORMAT), body=body)
output = res.read()
LOG.debug(output)
if res.status != 202:
LOG.error("Failed to plug iface \"%s\" to port \"%s\": %s" % \
(iface_id, new_port_id, output))
continue
client.attach_resource(nid, new_port_id, data)
print "Plugged interface \"%s\" to port:%s on network:%s" % \
(iface_id, new_port_id, nid)
@ -149,7 +88,6 @@ if __name__ == "__main__":
if len(args) < 1:
parser.print_help()
help()
sys.exit(1)
nets = {}
@ -163,12 +101,13 @@ if __name__ == "__main__":
print "nets: %s" % str(nets)
client = MiniClient(options.host, options.port, options.ssl)
client = Client(options.host, options.port, options.ssl,
format='json', tenant=tenant_id)
if options.delete:
delete_all_nets(client, tenant_id)
delete_all_nets(client)
for net_name, iface_ids in nets.items():
create_net_with_attachments(net_name, iface_ids)
create_net_with_attachments(client, net_name, iface_ids)
sys.exit(0)