From: Somik Behera Date: Tue, 7 Jun 2011 06:07:05 +0000 (-0700) Subject: Merged Brad's ovsplugin code X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=ef3285903c23497d729469331466df620aba0467;p=openstack-build%2Fneutron-build.git Merged Brad's ovsplugin code --- ef3285903c23497d729469331466df620aba0467 diff --cc quantum/cli.py index dc6cf8240,539d14173..9932f17af --- a/quantum/cli.py +++ b/quantum/cli.py @@@ -1,6 -1,7 +1,7 @@@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 - # Copyright 2011, Nicira Networks, Inc. -# Copyright 2011 Nicira Networks, Inc. -# Copyright 2011 Citrix Systems ++# Copyright 2011 Nicira Networks, Inc ++# All Rights Reserved. # # 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 @@@ -14,96 -15,417 +15,47 @@@ # License for the specific language governing permissions and limitations # under the License. # @author: Somik Behera, Nicira Networks, Inc. -# @author: Brad Hall, Nicira Networks, Inc. -import httplib -import logging as LOG -import simplejson -import socket --import sys -import urllib --from manager import QuantumManager -from optparse import OptionParser -from quantum.common.wsgi import Serializer ++""" ++Quantum's Manager class is responsible for parsing a config file and instantiating the correct ++plugin that concretely implement quantum_plugin_base class + -FORMAT = "json" -CONTENT_TYPE = "application/" + FORMAT ++The caller should make sure that QuantumManager is a singleton. ++""" ++import gettext ++gettext.install('quantum', unicode=1) + -### --- Miniclient (taking from the test directory) -### TODO(bgh): move this to a library within quantum -class MiniClient(object): - """A base client class - derived from Glance.BaseClient""" - action_prefix = '/v0.1/tenants/{tenant_id}' - def __init__(self, host, port, use_ssl): - self.host = host - self.port = port - self.use_ssl = use_ssl - self.connection = None - def get_connection_type(self): - if self.use_ssl: - return httplib.HTTPSConnection - else: - return httplib.HTTPConnection - def do_request(self, tenant, method, action, body=None, - headers=None, params=None): - action = MiniClient.action_prefix + action - action = action.replace('{tenant_id}',tenant) - if type(params) is dict: - action += '?' + urllib.urlencode(params) - try: - connection_type = self.get_connection_type() - headers = headers or {} - # Open connection and send request - c = connection_type(self.host, self.port) - c.request(method, action, body, headers) - res = c.getresponse() - status_code = self.get_status_code(res) - if status_code in (httplib.OK, httplib.CREATED, - httplib.ACCEPTED, httplib.NO_CONTENT): - return res - else: - raise Exception("Server returned error: %s" % res.read()) - except (socket.error, IOError), e: - raise Exception("Unable to connect to server. Got error: %s" % e) - def get_status_code(self, response): - if hasattr(response, 'status_int'): - return response.status_int - else: - return response.status -### -- end of miniclient - -### -- Core CLI functions - -def list_nets(manager, *args): - tenant_id = args[0] - networks = manager.get_all_networks(tenant_id) - print "Virtual Networks on Tenant:%s\n" % tenant_id - for net in networks: - id = net["net-id"] - name = net["net-name"] - print "\tNetwork ID:%s \n\tNetwork Name:%s \n" % (id, name) - -def api_list_nets(client, *args): - tenant_id = args[0] - res = client.do_request(tenant_id, 'GET', "/networks." + FORMAT) - resdict = simplejson.loads(res.read()) - LOG.debug(resdict) - print "Virtual Networks on Tenant:%s\n" % tenant_id - for n in resdict["networks"]: - net_id = n["id"] - print "\tNetwork ID:%s\n" % (net_id) - # TODO(bgh): we should make this call pass back the name too - # name = n["net-name"] - # LOG.info("\tNetwork ID:%s \n\tNetwork Name:%s \n" % (id, name)) - -def create_net(manager, *args): - tid, name = args - new_net_id = manager.create_network(tid, name) - print "Created a new Virtual Network with ID:%s\n" % new_net_id - -def api_create_net(client, *args): - tid, name = args - data = {'network': {'network-name': '%s' % name}} - body = Serializer().serialize(data, CONTENT_TYPE) - res = client.do_request(tid, 'POST', "/networks." + FORMAT, body=body) - rd = simplejson.loads(res.read()) - LOG.debug(rd) - nid = None - try: - nid = rd["networks"]["network"]["id"] - except Exception, e: - print "Failed to create network" - # TODO(bgh): grab error details from ws request result - return - print "Created a new Virtual Network with ID:%s\n" % nid - -def delete_net(manager, *args): - tid, nid = args - manager.delete_network(tid, nid) - print "Deleted Virtual Network with ID:%s" % nid - -def api_delete_net(client, *args): - tid, nid = args - res = client.do_request(tid, 'DELETE', "/networks/" + nid + "." + FORMAT) - status = res.status - if status != 202: - print "Failed to delete network" - output = res.read() - print output - else: - print "Deleted Virtual Network with ID:%s" % nid - -def detail_net(manager, *args): - tid, nid = args - iface_list = manager.get_network_details(tid, nid) - print "Remote Interfaces on Virtual Network:%s\n" % nid - for iface in iface_list: - print "\tRemote interface:%s" % iface - -def api_detail_net(client, *args): - tid, nid = args - res = client.do_request(tid, 'GET', - "/networks/%s/ports.%s" % (nid, FORMAT)) - output = res.read() - if res.status != 200: - LOG.error("Failed to list ports: %s" % output) - return - rd = simplejson.loads(output) - LOG.debug(rd) - print "Remote Interfaces on Virtual Network:%s\n" % nid - for port in rd["ports"]: - pid = port["id"] - res = client.do_request(tid, 'GET', - "/networks/%s/ports/%s/attachment.%s" % (nid, pid, FORMAT)) - output = res.read() - rd = simplejson.loads(output) - LOG.debug(rd) - remote_iface = rd["attachment"] - print "\tRemote interface:%s" % remote_iface - -def rename_net(manager, *args): - tid, nid, name = args - manager.rename_network(tid, nid, name) - print "Renamed Virtual Network with ID:%s" % nid - -def api_rename_net(client, *args): - tid, nid, name = args - data = {'network': {'network-name': '%s' % name}} - body = Serializer().serialize(data, CONTENT_TYPE) - res = client.do_request(tid, 'PUT', "/networks/%s.%s" % (nid, FORMAT), - body=body) - resdict = simplejson.loads(res.read()) - LOG.debug(resdict) - print "Renamed Virtual Network with ID:%s" % nid - -def list_ports(manager, *args): - tid, nid = args - ports = manager.get_all_ports(tid, nid) - print "Ports on Virtual Network:%s\n" % nid - for port in ports: - print "\tVirtual Port:%s" % port["port-id"] - -def api_list_ports(client, *args): - tid, nid = args - res = client.do_request(tid, 'GET', - "/networks/%s/ports.%s" % (nid, FORMAT)) - output = res.read() - if res.status != 200: - LOG.error("Failed to list ports: %s" % output) - return - rd = simplejson.loads(output) - LOG.debug(rd) - print "Ports on Virtual Network:%s\n" % nid - for port in rd["ports"]: - print "\tVirtual Port:%s" % port["id"] ++import os + -def create_port(manager, *args): - tid, nid = args - new_port = manager.create_port(tid, nid) - print "Created Virtual Port:%s " \ - "on Virtual Network:%s" % (new_port, nid) ++from common import utils ++from quantum_plugin_base import QuantumPluginBase + -def api_create_port(client, *args): - tid, nid = args - res = client.do_request(tid, 'POST', - "/networks/%s/ports.%s" % (nid, FORMAT)) - output = res.read() - if res.status != 200: - LOG.error("Failed to create port: %s" % output) - return - rd = simplejson.loads(output) - new_port = rd["ports"]["port"]["id"] - print "Created Virtual Port:%s " \ - "on Virtual Network:%s" % (new_port, nid) ++CONFIG_FILE = "plugins.ini" + -def delete_port(manager, *args): - tid, nid, pid = args - LOG.info("Deleted Virtual Port:%s " \ - "on Virtual Network:%s" % (pid, nid)) ++def find_config(basepath): ++ for root, dirs, files in os.walk(basepath): ++ if CONFIG_FILE in files: ++ return os.path.join(root, CONFIG_FILE) ++ return None + -def api_delete_port(client, *args): - tid, nid, pid = args - res = client.do_request(tid, 'DELETE', - "/networks/%s/ports/%s.%s" % (nid, pid, FORMAT)) - output = res.read() - if res.status != 202: - LOG.error("Failed to delete port: %s" % output) - return - LOG.info("Deleted Virtual Port:%s " \ - "on Virtual Network:%s" % (pid, nid)) - -def detail_port(manager, *args): - tid, nid, pid = args - port_detail = manager.get_port_details(tid, nid, pid) - print "Virtual Port:%s on Virtual Network:%s " \ - "contains remote interface:%s" % (pid, nid, port_detail) - -def api_detail_port(client, *args): - tid, nid, pid = args - res = client.do_request(tid, 'GET', - "/networks/%s/ports/%s.%s" % (nid, pid, FORMAT)) - output = res.read() - if res.status != 200: - LOG.error("Failed to get port details: %s" % output) - return - rd = simplejson.loads(output) - port = rd["ports"]["port"] - id = port["id"] - attachment = port["attachment"] - LOG.debug(port) - print "Virtual Port:%s on Virtual Network:%s " \ - "contains remote interface:%s" % (pid, nid, attachment) - -def plug_iface(manager, *args): - tid, nid, pid, vid = args - manager.plug_interface(tid, nid, pid, vid) - print "Plugged remote interface:%s " \ - "into Virtual Network:%s" % (vid, nid) - -def api_plug_iface(client, *args): - tid, nid, pid, vid = args - data = {'port': {'attachment-id': '%s' % vid}} - body = Serializer().serialize(data, CONTENT_TYPE) - res = client.do_request(tid, 'PUT', - "/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 plug iface \"%s\" to port \"%s\": %s" % (vid, - pid, output)) - return - print "Plugged interface \"%s\" to port:%s on network:%s" % (vid, pid, nid) - -def unplug_iface(manager, *args): - tid, nid, pid = args - manager.unplug_interface(tid, nid, pid) - print "UnPlugged remote interface " \ - "from Virtual Port:%s Virtual Network:%s" % (pid, nid) - -def api_unplug_iface(client, *args): - tid, nid, pid = args - data = {'port': {'attachment-id': ''}} - body = Serializer().serialize(data, CONTENT_TYPE) - res = client.do_request(tid, '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)) - return - print "Unplugged interface from port:%s on network:%s" % (pid, nid) - -commands = { - "list_nets": { - "func": list_nets, - "api_func": api_list_nets, - "args": ["tenant-id"] - }, - "create_net": { - "func": create_net, - "api_func": api_create_net, - "args": ["tenant-id", "net-name"] - }, - "delete_net": { - "func": delete_net, - "api_func": api_delete_net, - "args": ["tenant-id", "net-id"] - }, - "detail_net": { - "func": detail_net, - "api_func": api_detail_net, - "args": ["tenant-id", "net-id"] - }, - "rename_net": { - "func": rename_net, - "api_func": api_rename_net, - "args": ["tenant-id", "net-id", "new-name"] - }, - "list_ports": { - "func": list_ports, - "api_func": api_list_ports, - "args": ["tenant-id", "net-id"] - }, - "create_port": { - "func": create_port, - "api_func": api_create_port, - "args": ["tenant-id", "net-id"] - }, - "delete_port": { - "func": delete_port, - "api_func": api_delete_port, - "args": ["tenant-id", "net-id", "port-id"] - }, - "detail_port": { - "func": detail_port, - "api_func": api_detail_port, - "args": ["tenant-id", "net-id", "port-id"] - }, - "plug_iface": { - "func": plug_iface, - "api_func": api_plug_iface, - "args": ["tenant-id", "net-id", "port-id", "iface-id"] - }, - "unplug_iface": { - "func": unplug_iface, - "api_func": api_unplug_iface, - "args": ["tenant-id", "net-id", "port-id"] - }, - } - -def help(): - print "\nCommands:" - for k in commands.keys(): - print " %s %s" % (k, - " ".join(["<%s>" % y for y in commands[k]["args"]])) - -def build_args(cmd, cmdargs, arglist): - args = [] - orig_arglist = arglist[:] - try: - for x in cmdargs: - args.append(arglist[0]) - del arglist[0] - except Exception, e: - 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 - -if __name__ == "__main__": - usagestr = "Usage: %prog [OPTIONS] [args]" - parser = OptionParser(usage=usagestr) - parser.add_option("-l", "--load-plugin", dest="load_plugin", - action="store_true", default=False, - help="Load plugin directly instead of using WS API") - parser.add_option("-H", "--host", dest="host", - type="string", default="127.0.0.1", help="ip address of api host") - parser.add_option("-p", "--port", dest="port", - type="int", default=9696, help="api poort") - parser.add_option("-s", "--ssl", dest="ssl", - action="store_true", default=False, help="use ssl") - parser.add_option("-v", "--verbose", dest="verbose", - action="store_true", default=False, help="turn on verbose logging") - - options, args = parser.parse_args() - - if options.verbose: - LOG.basicConfig(level=LOG.DEBUG) - else: - LOG.basicConfig(level=LOG.WARN) - - if len(args) < 1: - parser.print_help() - help() - sys.exit(1) ++class QuantumManager(object): ++ def __init__(self, config=None): ++ if config == None: ++ self.configuration_file = find_config(os.path.abspath(os.path.dirname(__file__))) ++ else: ++ self.configuration_file = config ++ plugin_location = utils.getPluginFromConfig(self.configuration_file) ++ print "PLUGIN LOCATION:%s" % plugin_location ++ plugin_klass = utils.import_class(plugin_location) ++ if not issubclass(plugin_klass, QuantumPluginBase): ++ raise Exception("Configured Quantum plug-in " \ ++ "didn't pass compatibility test") ++ else: ++ print("Successfully imported Quantum plug-in." \ ++ "All compatibility tests passed\n") ++ self.plugin = plugin_klass() + - cmd = args[0] - if cmd not in commands.keys(): - LOG.error("Unknown command: %s" % cmd) - help() - sys.exit(1) ++ def get_manager(self): ++ return self.plugin - - def usage(): - print "\nUsage:" - print "list_nets " - print "create_net " - print "delete_net " - print "detail_net " - print "rename_net " - print "list_ports " - print "create_port " - print "delete_port " - print "detail_port " - print "plug_iface " - print "unplug_iface " - print "detail_iface " - print "list_iface \n" - - if len(sys.argv) < 2 or len(sys.argv) > 6: - usage() - exit(1) - - quantum = QuantumManager() - manager = quantum.get_manager() - - if sys.argv[1] == "list_nets" and len(sys.argv) == 3: - network_on_tenant = manager.get_all_networks(sys.argv[2]) - print "Virtual Networks on Tenant:%s\n" % sys.argv[2] - for k, v in network_on_tenant.iteritems(): - print"\tNetwork ID:%s \n\tNetwork Name:%s \n" % (k, v) - elif sys.argv[1] == "create_net" and len(sys.argv) == 4: - new_net_id = manager.create_network(sys.argv[2], sys.argv[3]) - print "Created a new Virtual Network with ID:%s\n" % new_net_id - elif sys.argv[1] == "delete_net" and len(sys.argv) == 4: - manager.delete_network(sys.argv[2], sys.argv[3]) - print "Deleted Virtual Network with ID:%s" % sys.argv[3] - elif sys.argv[1] == "detail_net" and len(sys.argv) == 4: - vif_list = manager.get_network_details(sys.argv[2], sys.argv[3]) - print "Remote Interfaces on Virtual Network:%s\n" % sys.argv[3] - for iface in vif_list: - print "\tRemote interface :%s" % iface - elif sys.argv[1] == "rename_net" and len(sys.argv) == 5: - manager.rename_network(sys.argv[2], sys.argv[3], sys.argv[4]) - print "Renamed Virtual Network with ID:%s" % sys.argv[3] - elif sys.argv[1] == "list_ports" and len(sys.argv) == 4: - ports = manager.get_all_ports(sys.argv[2], sys.argv[3]) - print " Virtual Ports on Virtual Network:%s\n" % sys.argv[3] - for port in ports: - print "\tVirtual Port:%s" % port - elif sys.argv[1] == "create_port" and len(sys.argv) == 4: - new_port = manager.create_port(sys.argv[2], sys.argv[3]) - print "Created Virtual Port:%s " \ - "on Virtual Network:%s" % (new_port, sys.argv[3]) - elif sys.argv[1] == "delete_port" and len(sys.argv) == 5: - manager.delete_port(sys.argv[2], sys.argv[3], sys.argv[4]) - print "Deleted Virtual Port:%s " \ - "on Virtual Network:%s" % (sys.argv[3], sys.argv[4]) - elif sys.argv[1] == "detail_port" and len(sys.argv) == 5: - port_detail = manager.get_port_details(sys.argv[2], - sys.argv[3], sys.argv[4]) - print "Virtual Port:%s on Virtual Network:%s " \ - "contains remote interface:%s" % (sys.argv[3], - sys.argv[4], - port_detail) - elif sys.argv[1] == "plug_iface" and len(sys.argv) == 6: - manager.plug_interface(sys.argv[2], sys.argv[3], sys.argv[4], sys.argv[5]) - print "Plugged remote interface:%s " \ - "into Virtual Network:%s" % (sys.argv[5], sys.argv[3]) - elif sys.argv[1] == "unplug_iface" and len(sys.argv) == 5: - manager.unplug_interface(sys.argv[2], sys.argv[3], sys.argv[4]) - print "UnPlugged remote interface " \ - "from Virtual Port:%s Virtual Network:%s" % (sys.argv[4], - sys.argv[3]) - elif sys.argv[1] == "detail_iface" and len(sys.argv) == 5: - remote_iface = manager.get_interface_details(sys.argv[2], - sys.argv[3], sys.argv[4]) - print "Remote interface on Virtual Port:%s " \ - "Virtual Network:%s is %s" % (sys.argv[4], - sys.argv[3], remote_iface) - elif sys.argv[1] == "list_iface" and len(sys.argv) == 4: - iface_list = manager.get_all_attached_interfaces(sys.argv[2], sys.argv[3]) - print "Remote Interfaces on Virtual Network:%s\n" % sys.argv[3] - for iface in iface_list: - print "\tRemote interface :%s" % iface - elif sys.argv[1] == "all" and len(sys.argv) == 2: - print "Not Implemented" - else: - print "invalid arguments: %s" % str(sys.argv) - usage() - args = build_args(cmd, commands[cmd]["args"], args[1:]) - if not args: - sys.exit(1) - LOG.debug("Executing command \"%s\" with args: %s" % (cmd, args)) - if not options.load_plugin: - client = MiniClient(options.host, options.port, options.ssl) - if not commands[cmd].has_key("api_func"): - LOG.error("API version of \"%s\" is not yet implemented" % cmd) - sys.exit(1) - commands[cmd]["api_func"](client, *args) - else: - quantum = QuantumManager() - manager = quantum.get_manager() - commands[cmd]["func"](manager, *args) - sys.exit(0) diff --cc quantum/manager.py index 28daef176,9932f17af..2b62603fb --- a/quantum/manager.py +++ b/quantum/manager.py @@@ -32,12 -33,19 +34,26 @@@ from quantum_plugin_base import Quantum CONFIG_FILE = "plugins.ini" + def find_config(basepath): + for root, dirs, files in os.walk(basepath): + if CONFIG_FILE in files: + return os.path.join(root, CONFIG_FILE) + return None class QuantumManager(object): ++<<<<<<< TREE + + def __init__(self, config=CONFIG_FILE): + self.configuration_file = CONFIG_FILE + plugin_location = utils.getPluginFromConfig(CONFIG_FILE) ++======= + def __init__(self, config=None): + if config == None: + self.configuration_file = find_config(os.path.abspath(os.path.dirname(__file__))) + else: + self.configuration_file = config + plugin_location = utils.getPluginFromConfig(self.configuration_file) ++>>>>>>> MERGE-SOURCE print "PLUGIN LOCATION:%s" % plugin_location plugin_klass = utils.import_class(plugin_location) if not issubclass(plugin_klass, QuantumPluginBase):