Santhosh/Vinkesh | Fixed all the pep8 violations. Modified the 'req' to 'request' across all the services and wsgi so that it's consistent with other projects

This commit is contained in:
Santhosh 2011-06-08 15:51:47 +05:30
parent 6458fa7cff
commit fed70a5272
26 changed files with 326 additions and 272 deletions

View File

@ -33,9 +33,10 @@ if os.path.exists(os.path.join(possible_topdir, 'quantum', '__init__.py')):
gettext.install('quantum', unicode=1) gettext.install('quantum', unicode=1)
from quantum import service from quantum import service
from quantum.common import config from quantum.common import config
def create_options(parser): def create_options(parser):
""" """
Sets up the CLI and config-file options that may be Sets up the CLI and config-file options that may be
@ -58,4 +59,3 @@ if __name__ == '__main__':
service.wait() service.wait()
except RuntimeError, e: except RuntimeError, e:
sys.exit("ERROR: %s" % e) sys.exit("ERROR: %s" % e)

View File

@ -12,4 +12,4 @@ paste.app_factory = quantum.l2Network.service:app_factory
bind_host = 0.0.0.0 bind_host = 0.0.0.0
# Port the bind the API server to # Port the bind the API server to
bind_port = 9696 bind_port = 9696

View File

@ -54,8 +54,9 @@ class APIRouterV01(wsgi.Router):
mapper.resource('port', 'ports', mapper.resource('port', 'ports',
controller=ports.Controller(), controller=ports.Controller(),
parent_resource=dict(member_name='network', parent_resource=dict(member_name='network',
collection_name=\ collection_name=uri_prefix +\
uri_prefix + 'networks')) 'networks'))
mapper.connect("get_resource", mapper.connect("get_resource",
uri_prefix + 'networks/{network_id}/' \ uri_prefix + 'networks/{network_id}/' \
'ports/{id}/attachment{.format}', 'ports/{id}/attachment{.format}',

View File

@ -36,8 +36,7 @@ class Fault(webob.exc.HTTPException):
432: "portInUse", 432: "portInUse",
440: "alreadyAttached", 440: "alreadyAttached",
470: "serviceUnavailable", 470: "serviceUnavailable",
471: "pluginFault" 471: "pluginFault"}
}
def __init__(self, exception): def __init__(self, exception):
"""Create a Fault for the given webob.exc.exception.""" """Create a Fault for the given webob.exc.exception."""
@ -52,7 +51,7 @@ class Fault(webob.exc.HTTPException):
fault_data = { fault_data = {
fault_name: { fault_name: {
'code': code, 'code': code,
'message': self.wrapped_exc.explanation, 'message': self.wrapped_exc.explanation,
'detail': self.wrapped_exc.detail}} 'detail': self.wrapped_exc.detail}}
# 'code' is an attribute on the fault tag itself # 'code' is an attribute on the fault tag itself
metadata = {'application/xml': {'attributes': {fault_name: 'code'}}} metadata = {'application/xml': {'attributes': {fault_name: 'code'}}}

View File

@ -44,63 +44,66 @@ class Controller(common.QuantumController):
self._resource_name = 'network' self._resource_name = 'network'
super(Controller, self).__init__() super(Controller, self).__init__()
def index(self, req, tenant_id): def index(self, request, tenant_id):
""" Returns a list of network ids """ """ Returns a list of network ids """
#TODO: this should be for a given tenant!!! #TODO: this should be for a given tenant!!!
return self._items(req, tenant_id, is_detail=False) return self._items(request, tenant_id, is_detail=False)
def _items(self, req, tenant_id, is_detail): def _items(self, request, tenant_id, is_detail):
""" Returns a list of networks. """ """ Returns a list of networks. """
networks = self.network_manager.get_all_networks(tenant_id) networks = self.network_manager.get_all_networks(tenant_id)
builder = networks_view.get_view_builder(req) builder = networks_view.get_view_builder(request)
result = [builder.build(network, is_detail)['network'] result = [builder.build(network, is_detail)['network']
for network in networks] for network in networks]
return dict(networks=result) return dict(networks=result)
def show(self, req, tenant_id, id): def show(self, request, tenant_id, id):
""" Returns network details for the given network id """ """ Returns network details for the given network id """
try: try:
network = self.network_manager.get_network_details( network = self.network_manager.get_network_details(
tenant_id, id) tenant_id, id)
builder = networks_view.get_view_builder(req) builder = networks_view.get_view_builder(request)
#build response with details #build response with details
result = builder.build(network, True) result = builder.build(network, True)
return dict(networks=result) return dict(networks=result)
except exception.NetworkNotFound as e: except exception.NetworkNotFound as e:
return faults.Fault(faults.NetworkNotFound(e)) return faults.Fault(faults.NetworkNotFound(e))
def create(self, req, tenant_id): def create(self, request, tenant_id):
""" Creates a new network for a given tenant """ """ Creates a new network for a given tenant """
#look for network name in request #look for network name in request
try: try:
req_params = \ request_params = \
self._parse_request_params(req, self._network_ops_param_list) self._parse_request_params(request,
self._network_ops_param_list)
except exc.HTTPError as e: except exc.HTTPError as e:
return faults.Fault(e) return faults.Fault(e)
network = self.network_manager.\ network = self.network_manager.\
create_network(tenant_id,req_params['network-name']) create_network(tenant_id,
builder = networks_view.get_view_builder(req) request_params['network-name'])
builder = networks_view.get_view_builder(request)
result = builder.build(network) result = builder.build(network)
return dict(networks=result) return dict(networks=result)
def update(self, req, tenant_id, id): def update(self, request, tenant_id, id):
""" Updates the name for the network with the given id """ """ Updates the name for the network with the given id """
try: try:
req_params = \ request_params = \
self._parse_request_params(req, self._network_ops_param_list) self._parse_request_params(request,
self._network_ops_param_list)
except exc.HTTPError as e: except exc.HTTPError as e:
return faults.Fault(e) return faults.Fault(e)
try: try:
network = self.network_manager.rename_network(tenant_id, network = self.network_manager.rename_network(tenant_id,
id, req_params['network-name']) id, request_params['network-name'])
builder = networks_view.get_view_builder(req) builder = networks_view.get_view_builder(request)
result = builder.build(network, True) result = builder.build(network, True)
return dict(networks=result) return dict(networks=result)
except exception.NetworkNotFound as e: except exception.NetworkNotFound as e:
return faults.Fault(faults.NetworkNotFound(e)) return faults.Fault(faults.NetworkNotFound(e))
def delete(self, req, tenant_id, id): def delete(self, request, tenant_id, id):
""" Destroys the network with the given id """ """ Destroys the network with the given id """
try: try:
self.network_manager.delete_network(tenant_id, id) self.network_manager.delete_network(tenant_id, id)

View File

@ -24,51 +24,49 @@ from quantum.common import exceptions as exception
LOG = logging.getLogger('quantum.api.ports') LOG = logging.getLogger('quantum.api.ports')
class Controller(common.QuantumController): class Controller(common.QuantumController):
""" Port API controller for Quantum API """ """ Port API controller for Quantum API """
_port_ops_param_list = [{ _port_ops_param_list = [{
'param-name': 'port-state', 'param-name': 'port-state',
'default-value': 'DOWN', 'default-value': 'DOWN',
'required': False},] 'required': False}, ]
_attachment_ops_param_list = [{ _attachment_ops_param_list = [{
'param-name': 'attachment-id', 'param-name': 'attachment-id',
'required': True},] 'required': True}, ]
_serialization_metadata = { _serialization_metadata = {
"application/xml": { "application/xml": {
"attributes": { "attributes": {
"port": ["id","state"], "port": ["id", "state"], }, }, }
},
},
}
def __init__(self, plugin_conf_file=None): def __init__(self, plugin_conf_file=None):
self._resource_name = 'port' self._resource_name = 'port'
super(Controller, self).__init__() super(Controller, self).__init__()
def index(self, req, tenant_id, network_id): def index(self, request, tenant_id, network_id):
""" Returns a list of port ids for a given network """ """ Returns a list of port ids for a given network """
return self._items(req, tenant_id, network_id, is_detail=False) return self._items(request, tenant_id, network_id, is_detail=False)
def _items(self, req, tenant_id, network_id, is_detail): def _items(self, request, tenant_id, network_id, is_detail):
""" Returns a list of networks. """ """ Returns a list of networks. """
try : try:
ports = self.network_manager.get_all_ports(tenant_id, network_id) ports = self.network_manager.get_all_ports(tenant_id, network_id)
builder = ports_view.get_view_builder(req) builder = ports_view.get_view_builder(request)
result = [builder.build(port, is_detail)['port'] result = [builder.build(port, is_detail)['port']
for port in ports] for port in ports]
return dict(ports=result) return dict(ports=result)
except exception.NetworkNotFound as e: except exception.NetworkNotFound as e:
return faults.Fault(faults.NetworkNotFound(e)) return faults.Fault(faults.NetworkNotFound(e))
def show(self, req, tenant_id, network_id, id): def show(self, request, tenant_id, network_id, id):
""" Returns port details for given port and network """ """ Returns port details for given port and network """
try: try:
port = self.network_manager.get_port_details( port = self.network_manager.get_port_details(
tenant_id, network_id, id) tenant_id, network_id, id)
builder = ports_view.get_view_builder(req) builder = ports_view.get_view_builder(request)
#build response with details #build response with details
result = builder.build(port, True) result = builder.build(port, True)
return dict(ports=result) return dict(ports=result)
@ -77,19 +75,19 @@ class Controller(common.QuantumController):
except exception.PortNotFound as e: except exception.PortNotFound as e:
return faults.Fault(faults.PortNotFound(e)) return faults.Fault(faults.PortNotFound(e))
def create(self, req, tenant_id, network_id): def create(self, request, tenant_id, network_id):
""" Creates a new port for a given network """ """ Creates a new port for a given network """
#look for port state in request #look for port state in request
try: try:
req_params = \ request_params = \
self._parse_request_params(req, self._port_ops_param_list) self._parse_request_params(request, self._port_ops_param_list)
except exc.HTTPError as e: except exc.HTTPError as e:
return faults.Fault(e) return faults.Fault(e)
try: try:
port = self.network_manager.create_port(tenant_id, port = self.network_manager.create_port(tenant_id,
network_id, network_id,
req_params['port-state']) request_params['port-state'])
builder = ports_view.get_view_builder(req) builder = ports_view.get_view_builder(request)
result = builder.build(port) result = builder.build(port)
return dict(ports=result) return dict(ports=result)
except exception.NetworkNotFound as e: except exception.NetworkNotFound as e:
@ -97,18 +95,18 @@ class Controller(common.QuantumController):
except exception.StateInvalid as e: except exception.StateInvalid as e:
return faults.Fault(faults.RequestedStateInvalid(e)) return faults.Fault(faults.RequestedStateInvalid(e))
def update(self, req, tenant_id, network_id, id): def update(self, request, tenant_id, network_id, id):
""" Updates the state of a port for a given network """ """ Updates the state of a port for a given network """
#look for port state in request #look for port state in request
try: try:
req_params = \ request_params = \
self._parse_request_params(req, self._port_ops_param_list) self._parse_request_params(request, self._port_ops_param_list)
except exc.HTTPError as e: except exc.HTTPError as e:
return faults.Fault(e) return faults.Fault(e)
try: try:
port = self.network_manager.update_port(tenant_id,network_id, id, port = self.network_manager.update_port(tenant_id, network_id, id,
req_params['port-state']) request_params['port-state'])
builder = ports_view.get_view_builder(req) builder = ports_view.get_view_builder(request)
result = builder.build(port, True) result = builder.build(port, True)
return dict(ports=result) return dict(ports=result)
except exception.NetworkNotFound as e: except exception.NetworkNotFound as e:
@ -118,7 +116,7 @@ class Controller(common.QuantumController):
except exception.StateInvalid as e: except exception.StateInvalid as e:
return faults.Fault(faults.RequestedStateInvalid(e)) return faults.Fault(faults.RequestedStateInvalid(e))
def delete(self, req, tenant_id, network_id, id): def delete(self, request, tenant_id, network_id, id):
""" Destroys the port with the given id """ """ Destroys the port with the given id """
#look for port state in request #look for port state in request
try: try:
@ -132,7 +130,7 @@ class Controller(common.QuantumController):
except exception.PortInUse as e: except exception.PortInUse as e:
return faults.Fault(faults.PortInUse(e)) return faults.Fault(faults.PortInUse(e))
def get_resource(self,req,tenant_id, network_id, id): def get_resource(self, request, tenant_id, network_id, id):
try: try:
result = self.network_manager.get_interface_details( result = self.network_manager.get_interface_details(
tenant_id, network_id, id) tenant_id, network_id, id)
@ -143,19 +141,19 @@ class Controller(common.QuantumController):
return faults.Fault(faults.PortNotFound(e)) return faults.Fault(faults.PortNotFound(e))
#TODO - Complete implementation of these APIs #TODO - Complete implementation of these APIs
def attach_resource(self,req,tenant_id, network_id, id): def attach_resource(self, request, tenant_id, network_id, id):
content_type = req.best_match_content_type() content_type = request.best_match_content_type()
print "Content type:%s" %content_type print "Content type:%s" % content_type
try: try:
req_params = \ request_params = \
self._parse_request_params(req, self._parse_request_params(request,
self._attachment_ops_param_list) self._attachment_ops_param_list)
except exc.HTTPError as e: except exc.HTTPError as e:
return faults.Fault(e) return faults.Fault(e)
try: try:
self.network_manager.plug_interface(tenant_id, self.network_manager.plug_interface(tenant_id,
network_id,id, network_id, id,
req_params['attachment-id']) request_params['attachment-id'])
return exc.HTTPAccepted() return exc.HTTPAccepted()
except exception.NetworkNotFound as e: except exception.NetworkNotFound as e:
return faults.Fault(faults.NetworkNotFound(e)) return faults.Fault(faults.NetworkNotFound(e))
@ -167,10 +165,10 @@ class Controller(common.QuantumController):
return faults.Fault(faults.AlreadyAttached(e)) return faults.Fault(faults.AlreadyAttached(e))
#TODO - Complete implementation of these APIs #TODO - Complete implementation of these APIs
def detach_resource(self,req,tenant_id, network_id, id): def detach_resource(self, request, tenant_id, network_id, id):
try: try:
self.network_manager.unplug_interface(tenant_id, self.network_manager.unplug_interface(tenant_id,
network_id,id) network_id, id)
return exc.HTTPAccepted() return exc.HTTPAccepted()
except exception.NetworkNotFound as e: except exception.NetworkNotFound as e:
return faults.Fault(faults.NetworkNotFound(e)) return faults.Fault(faults.NetworkNotFound(e))

View File

@ -13,4 +13,4 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
# @author: Somik Behera, Nicira Networks, Inc. # @author: Somik Behera, Nicira Networks, Inc.

View File

@ -33,17 +33,17 @@ class ViewBuilder(object):
def build(self, network_data, is_detail=False): def build(self, network_data, is_detail=False):
"""Generic method used to generate a network entity.""" """Generic method used to generate a network entity."""
print "NETWORK-DATA:%s" %network_data print "NETWORK-DATA:%s" % network_data
if is_detail: if is_detail:
network = self._build_detail(network_data) network = self._build_detail(network_data)
else: else:
network = self._build_simple(network_data) network = self._build_simple(network_data)
return network return network
def _build_simple(self, network_data): def _build_simple(self, network_data):
"""Return a simple model of a server.""" """Return a simple model of a server."""
return dict(network=dict(id=network_data['net-id'])) return dict(network=dict(id=network_data['net-id']))
def _build_detail(self, network_data): def _build_detail(self, network_data):
"""Return a simple model of a server.""" """Return a simple model of a server."""
return dict(network=dict(id=network_data['net-id'], return dict(network=dict(id=network_data['net-id'],

View File

@ -31,7 +31,7 @@ class ViewBuilder(object):
def build(self, port_data, is_detail=False): def build(self, port_data, is_detail=False):
"""Generic method used to generate a port entity.""" """Generic method used to generate a port entity."""
print "PORT-DATA:%s" %port_data print "PORT-DATA:%s" % port_data
if is_detail: if is_detail:
port = self._build_detail(port_data) port = self._build_detail(port_data)
else: else:

View File

@ -31,25 +31,29 @@ from quantum.common.wsgi import Serializer
FORMAT = "json" FORMAT = "json"
CONTENT_TYPE = "application/" + FORMAT CONTENT_TYPE = "application/" + FORMAT
### --- Miniclient (taking from the test directory) ### --- Miniclient (taking from the test directory)
### TODO(bgh): move this to a library within quantum ### TODO(bgh): move this to a library within quantum
class MiniClient(object): class MiniClient(object):
"""A base client class - derived from Glance.BaseClient""" """A base client class - derived from Glance.BaseClient"""
action_prefix = '/v0.1/tenants/{tenant_id}' action_prefix = '/v0.1/tenants/{tenant_id}'
def __init__(self, host, port, use_ssl): def __init__(self, host, port, use_ssl):
self.host = host self.host = host
self.port = port self.port = port
self.use_ssl = use_ssl self.use_ssl = use_ssl
self.connection = None self.connection = None
def get_connection_type(self): def get_connection_type(self):
if self.use_ssl: if self.use_ssl:
return httplib.HTTPSConnection return httplib.HTTPSConnection
else: else:
return httplib.HTTPConnection return httplib.HTTPConnection
def do_request(self, tenant, method, action, body=None, def do_request(self, tenant, method, action, body=None,
headers=None, params=None): headers=None, params=None):
action = MiniClient.action_prefix + action action = MiniClient.action_prefix + action
action = action.replace('{tenant_id}',tenant) action = action.replace('{tenant_id}', tenant)
if type(params) is dict: if type(params) is dict:
action += '?' + urllib.urlencode(params) action += '?' + urllib.urlencode(params)
try: try:
@ -67,6 +71,7 @@ class MiniClient(object):
raise Exception("Server returned error: %s" % res.read()) raise Exception("Server returned error: %s" % res.read())
except (socket.error, IOError), e: except (socket.error, IOError), e:
raise Exception("Unable to connect to server. Got error: %s" % e) raise Exception("Unable to connect to server. Got error: %s" % e)
def get_status_code(self, response): def get_status_code(self, response):
if hasattr(response, 'status_int'): if hasattr(response, 'status_int'):
return response.status_int return response.status_int
@ -76,6 +81,7 @@ class MiniClient(object):
### -- Core CLI functions ### -- Core CLI functions
def list_nets(manager, *args): def list_nets(manager, *args):
tenant_id = args[0] tenant_id = args[0]
networks = manager.get_all_networks(tenant_id) networks = manager.get_all_networks(tenant_id)
@ -85,6 +91,7 @@ def list_nets(manager, *args):
name = net["net-name"] name = net["net-name"]
print "\tNetwork ID:%s \n\tNetwork Name:%s \n" % (id, name) print "\tNetwork ID:%s \n\tNetwork Name:%s \n" % (id, name)
def api_list_nets(client, *args): def api_list_nets(client, *args):
tenant_id = args[0] tenant_id = args[0]
res = client.do_request(tenant_id, 'GET', "/networks." + FORMAT) res = client.do_request(tenant_id, 'GET', "/networks." + FORMAT)
@ -98,11 +105,13 @@ def api_list_nets(client, *args):
# name = n["net-name"] # name = n["net-name"]
# LOG.info("\tNetwork ID:%s \n\tNetwork Name:%s \n" % (id, name)) # LOG.info("\tNetwork ID:%s \n\tNetwork Name:%s \n" % (id, name))
def create_net(manager, *args): def create_net(manager, *args):
tid, name = args tid, name = args
new_net_id = manager.create_network(tid, name) new_net_id = manager.create_network(tid, name)
print "Created a new Virtual Network with ID:%s\n" % new_net_id print "Created a new Virtual Network with ID:%s\n" % new_net_id
def api_create_net(client, *args): def api_create_net(client, *args):
tid, name = args tid, name = args
data = {'network': {'network-name': '%s' % name}} data = {'network': {'network-name': '%s' % name}}
@ -119,11 +128,13 @@ def api_create_net(client, *args):
return return
print "Created a new Virtual Network with ID:%s\n" % nid print "Created a new Virtual Network with ID:%s\n" % nid
def delete_net(manager, *args): def delete_net(manager, *args):
tid, nid = args tid, nid = args
manager.delete_network(tid, nid) manager.delete_network(tid, nid)
print "Deleted Virtual Network with ID:%s" % nid print "Deleted Virtual Network with ID:%s" % nid
def api_delete_net(client, *args): def api_delete_net(client, *args):
tid, nid = args tid, nid = args
res = client.do_request(tid, 'DELETE', "/networks/" + nid + "." + FORMAT) res = client.do_request(tid, 'DELETE', "/networks/" + nid + "." + FORMAT)
@ -135,6 +146,7 @@ def api_delete_net(client, *args):
else: else:
print "Deleted Virtual Network with ID:%s" % nid print "Deleted Virtual Network with ID:%s" % nid
def detail_net(manager, *args): def detail_net(manager, *args):
tid, nid = args tid, nid = args
iface_list = manager.get_network_details(tid, nid) iface_list = manager.get_network_details(tid, nid)
@ -142,6 +154,7 @@ def detail_net(manager, *args):
for iface in iface_list: for iface in iface_list:
print "\tRemote interface:%s" % iface print "\tRemote interface:%s" % iface
def api_detail_net(client, *args): def api_detail_net(client, *args):
tid, nid = args tid, nid = args
res = client.do_request(tid, 'GET', res = client.do_request(tid, 'GET',
@ -163,11 +176,13 @@ def api_detail_net(client, *args):
remote_iface = rd["attachment"] remote_iface = rd["attachment"]
print "\tRemote interface:%s" % remote_iface print "\tRemote interface:%s" % remote_iface
def rename_net(manager, *args): def rename_net(manager, *args):
tid, nid, name = args tid, nid, name = args
manager.rename_network(tid, nid, name) manager.rename_network(tid, nid, name)
print "Renamed Virtual Network with ID:%s" % nid print "Renamed Virtual Network with ID:%s" % nid
def api_rename_net(client, *args): def api_rename_net(client, *args):
tid, nid, name = args tid, nid, name = args
data = {'network': {'network-name': '%s' % name}} data = {'network': {'network-name': '%s' % name}}
@ -178,6 +193,7 @@ def api_rename_net(client, *args):
LOG.debug(resdict) LOG.debug(resdict)
print "Renamed Virtual Network with ID:%s" % nid print "Renamed Virtual Network with ID:%s" % nid
def list_ports(manager, *args): def list_ports(manager, *args):
tid, nid = args tid, nid = args
ports = manager.get_all_ports(tid, nid) ports = manager.get_all_ports(tid, nid)
@ -185,6 +201,7 @@ def list_ports(manager, *args):
for port in ports: for port in ports:
print "\tVirtual Port:%s" % port["port-id"] print "\tVirtual Port:%s" % port["port-id"]
def api_list_ports(client, *args): def api_list_ports(client, *args):
tid, nid = args tid, nid = args
res = client.do_request(tid, 'GET', res = client.do_request(tid, 'GET',
@ -199,12 +216,14 @@ def api_list_ports(client, *args):
for port in rd["ports"]: for port in rd["ports"]:
print "\tVirtual Port:%s" % port["id"] print "\tVirtual Port:%s" % port["id"]
def create_port(manager, *args): def create_port(manager, *args):
tid, nid = args tid, nid = args
new_port = manager.create_port(tid, nid) new_port = manager.create_port(tid, nid)
print "Created Virtual Port:%s " \ print "Created Virtual Port:%s " \
"on Virtual Network:%s" % (new_port, nid) "on Virtual Network:%s" % (new_port, nid)
def api_create_port(client, *args): def api_create_port(client, *args):
tid, nid = args tid, nid = args
res = client.do_request(tid, 'POST', res = client.do_request(tid, 'POST',
@ -218,11 +237,13 @@ def api_create_port(client, *args):
print "Created Virtual Port:%s " \ print "Created Virtual Port:%s " \
"on Virtual Network:%s" % (new_port, nid) "on Virtual Network:%s" % (new_port, nid)
def delete_port(manager, *args): def delete_port(manager, *args):
tid, nid, pid = args tid, nid, pid = args
LOG.info("Deleted Virtual Port:%s " \ LOG.info("Deleted Virtual Port:%s " \
"on Virtual Network:%s" % (pid, nid)) "on Virtual Network:%s" % (pid, nid))
def api_delete_port(client, *args): def api_delete_port(client, *args):
tid, nid, pid = args tid, nid, pid = args
res = client.do_request(tid, 'DELETE', res = client.do_request(tid, 'DELETE',
@ -234,12 +255,14 @@ def api_delete_port(client, *args):
LOG.info("Deleted Virtual Port:%s " \ LOG.info("Deleted Virtual Port:%s " \
"on Virtual Network:%s" % (pid, nid)) "on Virtual Network:%s" % (pid, nid))
def detail_port(manager, *args): def detail_port(manager, *args):
tid, nid, pid = args tid, nid, pid = args
port_detail = manager.get_port_details(tid, nid, pid) port_detail = manager.get_port_details(tid, nid, pid)
print "Virtual Port:%s on Virtual Network:%s " \ print "Virtual Port:%s on Virtual Network:%s " \
"contains remote interface:%s" % (pid, nid, port_detail) "contains remote interface:%s" % (pid, nid, port_detail)
def api_detail_port(client, *args): def api_detail_port(client, *args):
tid, nid, pid = args tid, nid, pid = args
res = client.do_request(tid, 'GET', res = client.do_request(tid, 'GET',
@ -256,12 +279,14 @@ def api_detail_port(client, *args):
print "Virtual Port:%s on Virtual Network:%s " \ print "Virtual Port:%s on Virtual Network:%s " \
"contains remote interface:%s" % (pid, nid, attachment) "contains remote interface:%s" % (pid, nid, attachment)
def plug_iface(manager, *args): def plug_iface(manager, *args):
tid, nid, pid, vid = args tid, nid, pid, vid = args
manager.plug_interface(tid, nid, pid, vid) manager.plug_interface(tid, nid, pid, vid)
print "Plugged remote interface:%s " \ print "Plugged remote interface:%s " \
"into Virtual Network:%s" % (vid, nid) "into Virtual Network:%s" % (vid, nid)
def api_plug_iface(client, *args): def api_plug_iface(client, *args):
tid, nid, pid, vid = args tid, nid, pid, vid = args
data = {'port': {'attachment-id': '%s' % vid}} data = {'port': {'attachment-id': '%s' % vid}}
@ -276,12 +301,14 @@ def api_plug_iface(client, *args):
return return
print "Plugged interface \"%s\" to port:%s on network:%s" % (vid, pid, nid) print "Plugged interface \"%s\" to port:%s on network:%s" % (vid, pid, nid)
def unplug_iface(manager, *args):
def unplug_iface(manager, *args):
tid, nid, pid = args tid, nid, pid = args
manager.unplug_interface(tid, nid, pid) manager.unplug_interface(tid, nid, pid)
print "UnPlugged remote interface " \ print "UnPlugged remote interface " \
"from Virtual Port:%s Virtual Network:%s" % (pid, nid) "from Virtual Port:%s Virtual Network:%s" % (pid, nid)
def api_unplug_iface(client, *args): def api_unplug_iface(client, *args):
tid, nid, pid = args tid, nid, pid = args
data = {'port': {'attachment-id': ''}} data = {'port': {'attachment-id': ''}}
@ -296,63 +323,53 @@ def api_unplug_iface(client, *args):
return return
print "Unplugged interface from port:%s on network:%s" % (pid, nid) print "Unplugged interface from port:%s on network:%s" % (pid, nid)
commands = { commands = {
"list_nets": { "list_nets": {
"func": list_nets, "func": list_nets,
"api_func": api_list_nets, "api_func": api_list_nets,
"args": ["tenant-id"] "args": ["tenant-id"]},
},
"create_net": { "create_net": {
"func": create_net, "func": create_net,
"api_func": api_create_net, "api_func": api_create_net,
"args": ["tenant-id", "net-name"] "args": ["tenant-id", "net-name"]},
},
"delete_net": { "delete_net": {
"func": delete_net, "func": delete_net,
"api_func": api_delete_net, "api_func": api_delete_net,
"args": ["tenant-id", "net-id"] "args": ["tenant-id", "net-id"]},
},
"detail_net": { "detail_net": {
"func": detail_net, "func": detail_net,
"api_func": api_detail_net, "api_func": api_detail_net,
"args": ["tenant-id", "net-id"] "args": ["tenant-id", "net-id"]},
},
"rename_net": { "rename_net": {
"func": rename_net, "func": rename_net,
"api_func": api_rename_net, "api_func": api_rename_net,
"args": ["tenant-id", "net-id", "new-name"] "args": ["tenant-id", "net-id", "new-name"]},
},
"list_ports": { "list_ports": {
"func": list_ports, "func": list_ports,
"api_func": api_list_ports, "api_func": api_list_ports,
"args": ["tenant-id", "net-id"] "args": ["tenant-id", "net-id"]},
},
"create_port": { "create_port": {
"func": create_port, "func": create_port,
"api_func": api_create_port, "api_func": api_create_port,
"args": ["tenant-id", "net-id"] "args": ["tenant-id", "net-id"]},
},
"delete_port": { "delete_port": {
"func": delete_port, "func": delete_port,
"api_func": api_delete_port, "api_func": api_delete_port,
"args": ["tenant-id", "net-id", "port-id"] "args": ["tenant-id", "net-id", "port-id"]},
},
"detail_port": { "detail_port": {
"func": detail_port, "func": detail_port,
"api_func": api_detail_port, "api_func": api_detail_port,
"args": ["tenant-id", "net-id", "port-id"] "args": ["tenant-id", "net-id", "port-id"]},
},
"plug_iface": { "plug_iface": {
"func": plug_iface, "func": plug_iface,
"api_func": api_plug_iface, "api_func": api_plug_iface,
"args": ["tenant-id", "net-id", "port-id", "iface-id"] "args": ["tenant-id", "net-id", "port-id", "iface-id"]},
},
"unplug_iface": { "unplug_iface": {
"func": unplug_iface, "func": unplug_iface,
"api_func": api_unplug_iface, "api_func": api_unplug_iface,
"args": ["tenant-id", "net-id", "port-id"] "args": ["tenant-id", "net-id", "port-id"]}, }
},
}
def help(): def help():
print "\nCommands:" print "\nCommands:"
@ -360,6 +377,7 @@ def help():
print " %s %s" % (k, print " %s %s" % (k,
" ".join(["<%s>" % y for y in commands[k]["args"]])) " ".join(["<%s>" % y for y in commands[k]["args"]]))
def build_args(cmd, cmdargs, arglist): def build_args(cmd, cmdargs, arglist):
args = [] args = []
orig_arglist = arglist[:] orig_arglist = arglist[:]
@ -381,6 +399,7 @@ def build_args(cmd, cmdargs, arglist):
return None return None
return args return args
if __name__ == "__main__": if __name__ == "__main__":
usagestr = "Usage: %prog [OPTIONS] <command> [args]" usagestr = "Usage: %prog [OPTIONS] <command> [args]"
parser = OptionParser(usage=usagestr) parser = OptionParser(usage=usagestr)
@ -420,7 +439,7 @@ if __name__ == "__main__":
LOG.debug("Executing command \"%s\" with args: %s" % (cmd, args)) LOG.debug("Executing command \"%s\" with args: %s" % (cmd, args))
if not options.load_plugin: if not options.load_plugin:
client = MiniClient(options.host, options.port, options.ssl) client = MiniClient(options.host, options.port, options.ssl)
if not commands[cmd].has_key("api_func"): if "api_func" not in commands[cmd]:
LOG.error("API version of \"%s\" is not yet implemented" % cmd) LOG.error("API version of \"%s\" is not yet implemented" % cmd)
sys.exit(1) sys.exit(1)
commands[cmd]["api_func"](client, *args) commands[cmd]["api_func"](client, *args)

View File

@ -33,6 +33,7 @@ from paste import deploy
from quantum.common import flags from quantum.common import flags
from quantum.common import exceptions as exception from quantum.common import exceptions as exception
from quantum.common import extensions
DEFAULT_LOG_FORMAT = "%(asctime)s %(levelname)8s [%(name)s] %(message)s" DEFAULT_LOG_FORMAT = "%(asctime)s %(levelname)8s [%(name)s] %(message)s"
DEFAULT_LOG_DATE_FORMAT = "%Y-%m-%d %H:%M:%S" DEFAULT_LOG_DATE_FORMAT = "%Y-%m-%d %H:%M:%S"
@ -209,7 +210,7 @@ def find_config_file(options, args):
fix_path(os.path.join('~', '.quantum')), fix_path(os.path.join('~', '.quantum')),
fix_path('~'), fix_path('~'),
os.path.join(FLAGS.state_path, 'etc'), os.path.join(FLAGS.state_path, 'etc'),
os.path.join(FLAGS.state_path, 'etc','quantum'), os.path.join(FLAGS.state_path, 'etc', 'quantum'),
'/etc/quantum/', '/etc/quantum/',
'/etc'] '/etc']
for cfg_dir in config_file_dirs: for cfg_dir in config_file_dirs:
@ -244,12 +245,10 @@ def load_paste_config(app_name, options, args):
problem loading the configuration file. problem loading the configuration file.
""" """
conf_file = find_config_file(options, args) conf_file = find_config_file(options, args)
print "Conf_file:%s" %conf_file
if not conf_file: if not conf_file:
raise RuntimeError("Unable to locate any configuration file. " raise RuntimeError("Unable to locate any configuration file. "
"Cannot load application %s" % app_name) "Cannot load application %s" % app_name)
try: try:
print "App_name:%s" %app_name
conf = deploy.appconfig("config:%s" % conf_file, name=app_name) conf = deploy.appconfig("config:%s" % conf_file, name=app_name)
return conf_file, conf return conf_file, conf
except Exception, e: except Exception, e:
@ -257,7 +256,7 @@ def load_paste_config(app_name, options, args):
% (conf_file, e)) % (conf_file, e))
def load_paste_app(conf_file, app_name): def load_paste_app(app_name, options, args):
""" """
Builds and returns a WSGI app from a paste config file. Builds and returns a WSGI app from a paste config file.
@ -278,16 +277,15 @@ def load_paste_app(conf_file, app_name):
:raises RuntimeError when config file cannot be located or application :raises RuntimeError when config file cannot be located or application
cannot be loaded from config file cannot be loaded from config file
""" """
#conf_file, conf = load_paste_config(app_name, options, args) conf_file, conf = load_paste_config(app_name, options, args)
try: try:
conf_file = os.path.abspath(conf_file)
app = deploy.loadapp("config:%s" % conf_file, name=app_name) app = deploy.loadapp("config:%s" % conf_file, name=app_name)
except (LookupError, ImportError), e: except (LookupError, ImportError), e:
raise RuntimeError("Unable to load %(app_name)s from " raise RuntimeError("Unable to load %(app_name)s from "
"configuration file %(conf_file)s." "configuration file %(conf_file)s."
"\nGot: %(e)r" % locals()) "\nGot: %(e)r" % locals())
return app return conf, app
def get_option(options, option, **kwargs): def get_option(options, option, **kwargs):

View File

@ -25,7 +25,7 @@ import logging
class QuantumException(Exception): class QuantumException(Exception):
"""Base Quantum Exception """Base Quantum Exception
Taken from nova.exception.NovaException Taken from nova.exception.NovaException
To correctly use this class, inherit from it and define To correctly use this class, inherit from it and define
a 'message' property. That message will get printf'd a 'message' property. That message will get printf'd
@ -45,6 +45,7 @@ class QuantumException(Exception):
def __str__(self): def __str__(self):
return self._error_string return self._error_string
class ProcessExecutionError(IOError): class ProcessExecutionError(IOError):
def __init__(self, stdout=None, stderr=None, exit_code=None, cmd=None, def __init__(self, stdout=None, stderr=None, exit_code=None, cmd=None,
description=None): description=None):
@ -84,11 +85,11 @@ class NetworkNotFound(NotFound):
class PortNotFound(NotFound): class PortNotFound(NotFound):
message = _("Port %(port_id)s could not be found " \ message = _("Port %(port_id)s could not be found " \
"on network %(net_id)s") "on network %(net_id)s")
class StateInvalid(QuantumException): class StateInvalid(QuantumException):
message = _("Unsupported port state: %(port_state)s") message = _("Unsupported port state: %(port_state)s")
class NetworkInUse(QuantumException): class NetworkInUse(QuantumException):
message = _("Unable to complete operation on network %(net_id)s. " \ message = _("Unable to complete operation on network %(net_id)s. " \
@ -100,11 +101,13 @@ class PortInUse(QuantumException):
"for network %(net_id)s. The attachment '%(att_id)s" \ "for network %(net_id)s. The attachment '%(att_id)s" \
"is plugged into the logical port.") "is plugged into the logical port.")
class AlreadyAttached(QuantumException): class AlreadyAttached(QuantumException):
message = _("Unable to plug the attachment %(att_id)s into port " \ message = _("Unable to plug the attachment %(att_id)s into port " \
"%(port_id)s for network %(net_id)s. The attachment is " \ "%(port_id)s for network %(net_id)s. The attachment is " \
"already plugged into port %(att_port_id)s") "already plugged into port %(att_port_id)s")
class Duplicate(Error): class Duplicate(Error):
pass pass

View File

@ -23,7 +23,7 @@ Global flags should be defined here, the rest are defined where they're used.
""" """
import getopt import getopt
import os import os
import string import string
import sys import sys
@ -249,4 +249,3 @@ def DECLARE(name, module_string, flag_values=FLAGS):
DEFINE_string('state_path', os.path.join(os.path.dirname(__file__), '../../'), DEFINE_string('state_path', os.path.join(os.path.dirname(__file__), '../../'),
"Top-level directory for maintaining quantum's state") "Top-level directory for maintaining quantum's state")

View File

@ -37,6 +37,7 @@ from exceptions import ProcessExecutionError
TIME_FORMAT = "%Y-%m-%dT%H:%M:%SZ" TIME_FORMAT = "%Y-%m-%dT%H:%M:%SZ"
FLAGS = flags.FLAGS FLAGS = flags.FLAGS
def int_from_bool_as_string(subject): def int_from_bool_as_string(subject):
""" """
Interpret a string as a boolean and return either 1 or 0. Interpret a string as a boolean and return either 1 or 0.
@ -188,6 +189,7 @@ def isotime(at=None):
def parse_isotime(timestr): def parse_isotime(timestr):
return datetime.datetime.strptime(timestr, TIME_FORMAT) return datetime.datetime.strptime(timestr, TIME_FORMAT)
def getPluginFromConfig(file="config.ini"): def getPluginFromConfig(file="config.ini"):
Config = ConfigParser.ConfigParser() Config = ConfigParser.ConfigParser()
Config.read(file) Config.read(file)

View File

@ -40,6 +40,7 @@ from quantum.common import exceptions as exception
LOG = logging.getLogger('quantum.common.wsgi') LOG = logging.getLogger('quantum.common.wsgi')
class WritableLogger(object): class WritableLogger(object):
"""A thin wrapper that responds to `write` and logs.""" """A thin wrapper that responds to `write` and logs."""
@ -126,7 +127,7 @@ class Request(webob.Request):
""" """
parts = self.path.rsplit('.', 1) parts = self.path.rsplit('.', 1)
LOG.debug("Request parts:%s",parts) LOG.debug("Request parts:%s", parts)
if len(parts) > 1: if len(parts) > 1:
format = parts[1] format = parts[1]
if format in ['json', 'xml']: if format in ['json', 'xml']:
@ -134,7 +135,7 @@ class Request(webob.Request):
ctypes = ['application/json', 'application/xml'] ctypes = ['application/json', 'application/xml']
bm = self.accept.best_match(ctypes) bm = self.accept.best_match(ctypes)
LOG.debug("BM:%s",bm) LOG.debug("BM:%s", bm)
return bm or 'application/json' return bm or 'application/json'
def get_content_type(self): def get_content_type(self):
@ -336,21 +337,21 @@ class Controller(object):
arg_dict = req.environ['wsgiorg.routing_args'][1] arg_dict = req.environ['wsgiorg.routing_args'][1]
action = arg_dict['action'] action = arg_dict['action']
method = getattr(self, action) method = getattr(self, action)
LOG.debug("ARG_DICT:%s",arg_dict) LOG.debug("ARG_DICT:%s", arg_dict)
LOG.debug("Action:%s",action) LOG.debug("Action:%s", action)
LOG.debug("Method:%s",method) LOG.debug("Method:%s", method)
LOG.debug("%s %s" % (req.method, req.url)) LOG.debug("%s %s" % (req.method, req.url))
del arg_dict['controller'] del arg_dict['controller']
del arg_dict['action'] del arg_dict['action']
if 'format' in arg_dict: if 'format' in arg_dict:
del arg_dict['format'] del arg_dict['format']
arg_dict['req'] = req arg_dict['request'] = req
result = method(**arg_dict) result = method(**arg_dict)
if type(result) is dict: if type(result) is dict:
content_type = req.best_match_content_type() content_type = req.best_match_content_type()
LOG.debug("Content type:%s",content_type) LOG.debug("Content type:%s", content_type)
LOG.debug("Result:%s",result) LOG.debug("Result:%s", result)
default_xmlns = self.get_default_xmlns(req) default_xmlns = self.get_default_xmlns(req)
body = self._serialize(result, content_type, default_xmlns) body = self._serialize(result, content_type, default_xmlns)
@ -497,7 +498,7 @@ class Serializer(object):
xmlns = metadata.get('xmlns', None) xmlns = metadata.get('xmlns', None)
if xmlns: if xmlns:
result.setAttribute('xmlns', xmlns) result.setAttribute('xmlns', xmlns)
LOG.debug("DATA:%s",data) LOG.debug("DATA:%s", data)
if type(data) is list: if type(data) is list:
LOG.debug("TYPE IS LIST") LOG.debug("TYPE IS LIST")
collections = metadata.get('list_collections', {}) collections = metadata.get('list_collections', {})
@ -538,8 +539,7 @@ class Serializer(object):
result.appendChild(node) result.appendChild(node)
else: else:
# Type is atom # Type is atom
LOG.debug("TYPE IS ATOM:%s",data) LOG.debug("TYPE IS ATOM:%s", data)
node = doc.createTextNode(str(data)) node = doc.createTextNode(str(data))
result.appendChild(node) result.appendChild(node)
return result return result

View File

@ -25,6 +25,7 @@ _ENGINE = None
_MAKER = None _MAKER = None
BASE = models.BASE BASE = models.BASE
def configure_db(options): def configure_db(options):
""" """
Establish the database, create an engine if needed, and Establish the database, create an engine if needed, and
@ -40,6 +41,7 @@ def configure_db(options):
pool_recycle=3600) pool_recycle=3600)
register_models() register_models()
def get_session(autocommit=True, expire_on_commit=False): def get_session(autocommit=True, expire_on_commit=False):
"""Helper method to grab session""" """Helper method to grab session"""
global _MAKER, _ENGINE global _MAKER, _ENGINE
@ -50,18 +52,21 @@ def get_session(autocommit=True, expire_on_commit=False):
expire_on_commit=expire_on_commit) expire_on_commit=expire_on_commit)
return _MAKER() return _MAKER()
def register_models(): def register_models():
"""Register Models and create properties""" """Register Models and create properties"""
global _ENGINE global _ENGINE
assert _ENGINE assert _ENGINE
BASE.metadata.create_all(_ENGINE) BASE.metadata.create_all(_ENGINE)
def unregister_models(): def unregister_models():
"""Unregister Models, useful clearing out data before testing""" """Unregister Models, useful clearing out data before testing"""
global _ENGINE global _ENGINE
assert _ENGINE assert _ENGINE
BASE.metadata.drop_all(_ENGINE) BASE.metadata.drop_all(_ENGINE)
def network_create(tenant_id, name): def network_create(tenant_id, name):
session = get_session() session = get_session()
net = None net = None
@ -77,12 +82,14 @@ def network_create(tenant_id, name):
session.flush() session.flush()
return net return net
def network_list(tenant_id): def network_list(tenant_id):
session = get_session() session = get_session()
return session.query(models.Network).\ return session.query(models.Network).\
filter_by(tenant_id=tenant_id).\ filter_by(tenant_id=tenant_id).\
all() all()
def network_get(net_id): def network_get(net_id):
session = get_session() session = get_session()
try: try:
@ -92,6 +99,7 @@ def network_get(net_id):
except exc.NoResultFound: except exc.NoResultFound:
raise Exception("No net found with id = %s" % net_id) raise Exception("No net found with id = %s" % net_id)
def network_rename(net_id, tenant_id, new_name): def network_rename(net_id, tenant_id, new_name):
session = get_session() session = get_session()
try: try:
@ -106,6 +114,7 @@ def network_rename(net_id, tenant_id, new_name):
return net return net
raise Exception("A network with name \"%s\" already exists" % new_name) raise Exception("A network with name \"%s\" already exists" % new_name)
def network_destroy(net_id): def network_destroy(net_id):
session = get_session() session = get_session()
try: try:
@ -118,6 +127,7 @@ def network_destroy(net_id):
except exc.NoResultFound: except exc.NoResultFound:
raise Exception("No network found with id = %s" % net_id) raise Exception("No network found with id = %s" % net_id)
def port_create(net_id): def port_create(net_id):
session = get_session() session = get_session()
with session.begin(): with session.begin():
@ -126,12 +136,14 @@ def port_create(net_id):
session.flush() session.flush()
return port return port
def port_list(net_id): def port_list(net_id):
session = get_session() session = get_session()
return session.query(models.Port).\ return session.query(models.Port).\
filter_by(network_id=net_id).\ filter_by(network_id=net_id).\
all() all()
def port_get(port_id): def port_get(port_id):
session = get_session() session = get_session()
try: try:
@ -141,6 +153,7 @@ def port_get(port_id):
except exc.NoResultFound: except exc.NoResultFound:
raise Exception("No port found with id = %s " % port_id) raise Exception("No port found with id = %s " % port_id)
def port_set_attachment(port_id, new_interface_id): def port_set_attachment(port_id, new_interface_id):
session = get_session() session = get_session()
ports = None ports = None
@ -157,7 +170,9 @@ def port_set_attachment(port_id, new_interface_id):
session.flush() session.flush()
return port return port
else: else:
raise Exception("Port with attachment \"%s\" already exists" % (new_interface_id)) raise Exception("Port with attachment \"%s\" already exists"
% (new_interface_id))
def port_destroy(port_id): def port_destroy(port_id):
session = get_session() session = get_session()
@ -170,4 +185,3 @@ def port_destroy(port_id):
return port return port
except exc.NoResultFound: except exc.NoResultFound:
raise Exception("No port found with id = %s " % port_id) raise Exception("No port found with id = %s " % port_id)

View File

@ -25,12 +25,14 @@ from sqlalchemy.orm import relation
BASE = declarative_base() BASE = declarative_base()
class Port(BASE): class Port(BASE):
"""Represents a port on a quantum network""" """Represents a port on a quantum network"""
__tablename__ = 'ports' __tablename__ = 'ports'
uuid = Column(String(255), primary_key=True) uuid = Column(String(255), primary_key=True)
network_id = Column(String(255), ForeignKey("networks.uuid"), nullable=False) network_id = Column(String(255), ForeignKey("networks.uuid"),
nullable=False)
interface_id = Column(String(255)) interface_id = Column(String(255))
def __init__(self, network_id): def __init__(self, network_id):
@ -38,7 +40,9 @@ class Port(BASE):
self.network_id = network_id self.network_id = network_id
def __repr__(self): def __repr__(self):
return "<Port(%s,%s,%s)>" % (self.uuid, self.network_id, self.interface_id) return "<Port(%s,%s,%s)>" % (self.uuid, self.network_id,
self.interface_id)
class Network(BASE): class Network(BASE):
"""Represents a quantum network""" """Represents a quantum network"""
@ -56,4 +60,4 @@ class Network(BASE):
def __repr__(self): def __repr__(self):
return "<Network(%s,%s,%s)>" % \ return "<Network(%s,%s,%s)>" % \
(self.uuid,self.name,self.tenant_id) (self.uuid, self.name, self.tenant_id)

View File

@ -18,12 +18,14 @@
""" """
Quantum's Manager class is responsible for parsing a config file and instantiating the correct Quantum's Manager class is responsible for parsing a config file and
plugin that concretely implement quantum_plugin_base class instantiating the correct plugin that concretely implement quantum_plugin_base
class.
The caller should make sure that QuantumManager is a singleton. The caller should make sure that QuantumManager is a singleton.
""" """
import gettext import gettext
import os
gettext.install('quantum', unicode=1) gettext.install('quantum', unicode=1)
import os import os
@ -33,16 +35,19 @@ from quantum_plugin_base import QuantumPluginBase
CONFIG_FILE = "plugins.ini" CONFIG_FILE = "plugins.ini"
def find_config(basepath): def find_config(basepath):
for root, dirs, files in os.walk(basepath): for root, dirs, files in os.walk(basepath):
if CONFIG_FILE in files: if CONFIG_FILE in files:
return os.path.join(root, CONFIG_FILE) return os.path.join(root, CONFIG_FILE)
return None return None
class QuantumManager(object): class QuantumManager(object):
def __init__(self, config=None): def __init__(self, config=None):
if config == None: if config == None:
self.configuration_file = find_config(os.path.abspath(os.path.dirname(__file__))) self.configuration_file = find_config(
os.path.abspath(os.path.dirname(__file__)))
else: else:
self.configuration_file = config self.configuration_file = config
plugin_location = utils.getPluginFromConfig(self.configuration_file) plugin_location = utils.getPluginFromConfig(self.configuration_file)
@ -58,4 +63,3 @@ class QuantumManager(object):
def get_manager(self): def get_manager(self):
return self.plugin return self.plugin

View File

@ -17,33 +17,32 @@
from quantum.common import exceptions as exc from quantum.common import exceptions as exc
class QuantumEchoPlugin(object): class QuantumEchoPlugin(object):
""" """
QuantumEchoPlugin is a demo plugin that doesn't QuantumEchoPlugin is a demo plugin that doesn't
do anything but demonstrated the concept of a do anything but demonstrated the concept of a
concrete Quantum Plugin. Any call to this plugin concrete Quantum Plugin. Any call to this plugin
will result in just a "print" to std. out with will result in just a "print" to std. out with
the name of the method that was called. the name of the method that was called.
""" """
def get_all_networks(self, tenant_id): def get_all_networks(self, tenant_id):
""" """
Returns a dictionary containing all Returns a dictionary containing all
<network_uuid, network_name> for <network_uuid, network_name> for
the specified tenant. the specified tenant.
""" """
print("get_all_networks() called\n") print("get_all_networks() called\n")
def create_network(self, tenant_id, net_name): def create_network(self, tenant_id, net_name):
""" """
Creates a new Virtual Network, and assigns it Creates a new Virtual Network, and assigns it
a symbolic name. a symbolic name.
""" """
print("create_network() called\n") print("create_network() called\n")
def delete_network(self, tenant_id, net_id): def delete_network(self, tenant_id, net_id):
""" """
Deletes the network with the specified network identifier Deletes the network with the specified network identifier
@ -51,38 +50,33 @@ class QuantumEchoPlugin(object):
""" """
print("delete_network() called\n") print("delete_network() called\n")
def get_network_details(self, tenant_id, net_id): def get_network_details(self, tenant_id, net_id):
""" """
Deletes the Virtual Network belonging to a the Deletes the Virtual Network belonging to a the
spec spec
""" """
print("get_network_details() called\n") print("get_network_details() called\n")
def rename_network(self, tenant_id, net_id, new_name): def rename_network(self, tenant_id, net_id, new_name):
""" """
Updates the symbolic name belonging to a particular Updates the symbolic name belonging to a particular
Virtual Network. Virtual Network.
""" """
print("rename_network() called\n") print("rename_network() called\n")
def get_all_ports(self, tenant_id, net_id): def get_all_ports(self, tenant_id, net_id):
""" """
Retrieves all port identifiers belonging to the Retrieves all port identifiers belonging to the
specified Virtual Network. specified Virtual Network.
""" """
print("get_all_ports() called\n") print("get_all_ports() called\n")
def create_port(self, tenant_id, net_id): def create_port(self, tenant_id, net_id):
""" """
Creates a port on the specified Virtual Network. Creates a port on the specified Virtual Network.
""" """
print("create_port() called\n") print("create_port() called\n")
def delete_port(self, tenant_id, net_id, port_id): def delete_port(self, tenant_id, net_id, port_id):
""" """
Deletes a port on a specified Virtual Network, Deletes a port on a specified Virtual Network,
@ -97,24 +91,21 @@ class QuantumEchoPlugin(object):
Updates the state of a port on the specified Virtual Network. Updates the state of a port on the specified Virtual Network.
""" """
print("update_port() called\n") print("update_port() called\n")
def get_port_details(self, tenant_id, net_id, port_id): def get_port_details(self, tenant_id, net_id, port_id):
""" """
This method allows the user to retrieve a remote interface This method allows the user to retrieve a remote interface
that is attached to this particular port. that is attached to this particular port.
""" """
print("get_port_details() called\n") print("get_port_details() called\n")
def plug_interface(self, tenant_id, net_id, port_id, remote_interface_id): def plug_interface(self, tenant_id, net_id, port_id, remote_interface_id):
""" """
Attaches a remote interface to the specified port on the Attaches a remote interface to the specified port on the
specified Virtual Network. specified Virtual Network.
""" """
print("plug_interface() called\n") print("plug_interface() called\n")
def unplug_interface(self, tenant_id, net_id, port_id): def unplug_interface(self, tenant_id, net_id, port_id):
""" """
Detaches a remote interface from the specified port on the Detaches a remote interface from the specified port on the
@ -130,18 +121,17 @@ class DummyDataPlugin(object):
hard-coded data structures to aid in quantum hard-coded data structures to aid in quantum
client/cli development client/cli development
""" """
def get_all_networks(self, tenant_id): def get_all_networks(self, tenant_id):
""" """
Returns a dictionary containing all Returns a dictionary containing all
<network_uuid, network_name> for <network_uuid, network_name> for
the specified tenant. the specified tenant.
""" """
nets = {"001": "lNet1", "002": "lNet2" , "003": "lNet3"} nets = {"001": "lNet1", "002": "lNet2", "003": "lNet3"}
print("get_all_networks() called\n") print("get_all_networks() called\n")
return nets return nets
def create_network(self, tenant_id, net_name): def create_network(self, tenant_id, net_name):
""" """
Creates a new Virtual Network, and assigns it Creates a new Virtual Network, and assigns it
@ -150,8 +140,7 @@ class DummyDataPlugin(object):
print("create_network() called\n") print("create_network() called\n")
# return network_id of the created network # return network_id of the created network
return 101 return 101
def delete_network(self, tenant_id, net_id): def delete_network(self, tenant_id, net_id):
""" """
Deletes the network with the specified network identifier Deletes the network with the specified network identifier
@ -159,7 +148,6 @@ class DummyDataPlugin(object):
""" """
print("delete_network() called\n") print("delete_network() called\n")
def get_network_details(self, tenant_id, net_id): def get_network_details(self, tenant_id, net_id):
""" """
retrieved a list of all the remote vifs that retrieved a list of all the remote vifs that
@ -168,16 +156,14 @@ class DummyDataPlugin(object):
print("get_network_details() called\n") print("get_network_details() called\n")
vifs_on_net = ["/tenant1/networks/net_id/portid/vif2.0"] vifs_on_net = ["/tenant1/networks/net_id/portid/vif2.0"]
return vifs_on_net return vifs_on_net
def rename_network(self, tenant_id, net_id, new_name): def rename_network(self, tenant_id, net_id, new_name):
""" """
Updates the symbolic name belonging to a particular Updates the symbolic name belonging to a particular
Virtual Network. Virtual Network.
""" """
print("rename_network() called\n") print("rename_network() called\n")
def get_all_ports(self, tenant_id, net_id): def get_all_ports(self, tenant_id, net_id):
""" """
Retrieves all port identifiers belonging to the Retrieves all port identifiers belonging to the
@ -186,8 +172,7 @@ class DummyDataPlugin(object):
print("get_all_ports() called\n") print("get_all_ports() called\n")
port_ids_on_net = ["2", "3", "4"] port_ids_on_net = ["2", "3", "4"]
return port_ids_on_net return port_ids_on_net
def create_port(self, tenant_id, net_id): def create_port(self, tenant_id, net_id):
""" """
Creates a port on the specified Virtual Network. Creates a port on the specified Virtual Network.
@ -201,8 +186,7 @@ class DummyDataPlugin(object):
Updates the state of a port on the specified Virtual Network. Updates the state of a port on the specified Virtual Network.
""" """
print("update_port() called\n") print("update_port() called\n")
def delete_port(self, tenant_id, net_id, port_id): def delete_port(self, tenant_id, net_id, port_id):
""" """
Deletes a port on a specified Virtual Network, Deletes a port on a specified Virtual Network,
@ -211,8 +195,7 @@ class DummyDataPlugin(object):
is deleted. is deleted.
""" """
print("delete_port() called\n") print("delete_port() called\n")
def get_port_details(self, tenant_id, net_id, port_id): def get_port_details(self, tenant_id, net_id, port_id):
""" """
This method allows the user to retrieve a remote interface This method allows the user to retrieve a remote interface
@ -221,24 +204,22 @@ class DummyDataPlugin(object):
print("get_port_details() called\n") print("get_port_details() called\n")
#returns the remote interface UUID #returns the remote interface UUID
return "/tenant1/networks/net_id/portid/vif2.1" return "/tenant1/networks/net_id/portid/vif2.1"
def plug_interface(self, tenant_id, net_id, port_id, remote_interface_id): def plug_interface(self, tenant_id, net_id, port_id, remote_interface_id):
""" """
Attaches a remote interface to the specified port on the Attaches a remote interface to the specified port on the
specified Virtual Network. specified Virtual Network.
""" """
print("plug_interface() called\n") print("plug_interface() called\n")
def unplug_interface(self, tenant_id, net_id, port_id): def unplug_interface(self, tenant_id, net_id, port_id):
""" """
Detaches a remote interface from the specified port on the Detaches a remote interface from the specified port on the
specified Virtual Network. specified Virtual Network.
""" """
print("unplug_interface() called\n") print("unplug_interface() called\n")
class FakePlugin(object): class FakePlugin(object):
""" """
FakePlugin is a demo plugin that provides FakePlugin is a demo plugin that provides
@ -248,72 +229,66 @@ class FakePlugin(object):
#static data for networks and ports #static data for networks and ports
_port_dict_1 = { _port_dict_1 = {
1 : {'port-id': 1, 1: {'port-id': 1,
'port-state': 'DOWN', 'port-state': 'DOWN',
'attachment': None}, 'attachment': None},
2 : {'port-id': 2, 2: {'port-id': 2,
'port-state':'UP', 'port-state': 'UP',
'attachment': None} 'attachment': None}}
}
_port_dict_2 = { _port_dict_2 = {
1 : {'port-id': 1, 1: {'port-id': 1,
'port-state': 'UP', 'port-state': 'UP',
'attachment': 'SomeFormOfVIFID'}, 'attachment': 'SomeFormOfVIFID'},
2 : {'port-id': 2, 2: {'port-id': 2,
'port-state':'DOWN', 'port-state': 'DOWN',
'attachment': None} 'attachment': None}}
} _networks = {'001':
_networks={'001':
{ {
'net-id':'001', 'net-id': '001',
'net-name':'pippotest', 'net-name': 'pippotest',
'net-ports': _port_dict_1 'net-ports': _port_dict_1},
},
'002': '002':
{ {
'net-id':'002', 'net-id': '002',
'net-name':'cicciotest', 'net-name': 'cicciotest',
'net-ports': _port_dict_2 'net-ports': _port_dict_2}}
}}
def __init__(self): def __init__(self):
FakePlugin._net_counter=len(FakePlugin._networks) FakePlugin._net_counter = len(FakePlugin._networks)
def _get_network(self, tenant_id, network_id): def _get_network(self, tenant_id, network_id):
network = FakePlugin._networks.get(network_id) network = FakePlugin._networks.get(network_id)
if not network: if not network:
raise exc.NetworkNotFound(net_id=network_id) raise exc.NetworkNotFound(net_id=network_id)
return network return network
def _get_port(self, tenant_id, network_id, port_id): def _get_port(self, tenant_id, network_id, port_id):
net = self._get_network(tenant_id, network_id) net = self._get_network(tenant_id, network_id)
port = net['net-ports'].get(int(port_id)) port = net['net-ports'].get(int(port_id))
if not port: if not port:
raise exc.PortNotFound(net_id=network_id, port_id=port_id) raise exc.PortNotFound(net_id=network_id, port_id=port_id)
return port return port
def _validate_port_state(self, port_state): def _validate_port_state(self, port_state):
if port_state.upper() not in ('UP','DOWN'): if port_state.upper() not in ('UP', 'DOWN'):
raise exc.StateInvalid(port_state=port_state) raise exc.StateInvalid(port_state=port_state)
return True return True
def _validate_attachment(self, tenant_id, network_id, port_id, def _validate_attachment(self, tenant_id, network_id, port_id,
remote_interface_id): remote_interface_id):
network = self._get_network(tenant_id, network_id) network = self._get_network(tenant_id, network_id)
for port in network['net-ports'].values(): for port in network['net-ports'].values():
if port['attachment'] == remote_interface_id: if port['attachment'] == remote_interface_id:
raise exc.AlreadyAttached(net_id = network_id, raise exc.AlreadyAttached(net_id=network_id,
port_id = port_id, port_id=port_id,
att_id = port['attachment'], att_id=port['attachment'],
att_port_id = port['port-id']) att_port_id=port['port-id'])
def get_all_networks(self, tenant_id): def get_all_networks(self, tenant_id):
""" """
Returns a dictionary containing all Returns a dictionary containing all
<network_uuid, network_name> for <network_uuid, network_name> for
the specified tenant. the specified tenant.
""" """
print("get_all_networks() called\n") print("get_all_networks() called\n")
return FakePlugin._networks.values() return FakePlugin._networks.values()
@ -333,16 +308,16 @@ class FakePlugin(object):
""" """
print("create_network() called\n") print("create_network() called\n")
FakePlugin._net_counter += 1 FakePlugin._net_counter += 1
new_net_id=("0" * (3 - len(str(FakePlugin._net_counter)))) + \ new_net_id = ("0" * (3 - len(str(FakePlugin._net_counter)))) + \
str(FakePlugin._net_counter) str(FakePlugin._net_counter)
print new_net_id print new_net_id
new_net_dict={'net-id':new_net_id, new_net_dict = {'net-id': new_net_id,
'net-name':net_name, 'net-name': net_name,
'net-ports': {}} 'net-ports': {}}
FakePlugin._networks[new_net_id]=new_net_dict FakePlugin._networks[new_net_id] = new_net_dict
# return network_id of the created network # return network_id of the created network
return new_net_dict return new_net_dict
def delete_network(self, tenant_id, net_id): def delete_network(self, tenant_id, net_id):
""" """
Deletes the network with the specified network identifier Deletes the network with the specified network identifier
@ -360,7 +335,7 @@ class FakePlugin(object):
return net return net
# Network not found # Network not found
raise exc.NetworkNotFound(net_id=net_id) raise exc.NetworkNotFound(net_id=net_id)
def rename_network(self, tenant_id, net_id, new_name): def rename_network(self, tenant_id, net_id, new_name):
""" """
Updates the symbolic name belonging to a particular Updates the symbolic name belonging to a particular
@ -368,7 +343,7 @@ class FakePlugin(object):
""" """
print("rename_network() called\n") print("rename_network() called\n")
net = self._get_network(tenant_id, net_id) net = self._get_network(tenant_id, net_id)
net['net-name']=new_name net['net-name'] = new_name
return net return net
def get_all_ports(self, tenant_id, net_id): def get_all_ports(self, tenant_id, net_id):
@ -388,7 +363,7 @@ class FakePlugin(object):
""" """
print("get_port_details() called\n") print("get_port_details() called\n")
return self._get_port(tenant_id, net_id, port_id) return self._get_port(tenant_id, net_id, port_id)
def create_port(self, tenant_id, net_id, port_state=None): def create_port(self, tenant_id, net_id, port_state=None):
""" """
Creates a port on the specified Virtual Network. Creates a port on the specified Virtual Network.
@ -396,15 +371,15 @@ class FakePlugin(object):
print("create_port() called\n") print("create_port() called\n")
net = self._get_network(tenant_id, net_id) net = self._get_network(tenant_id, net_id)
# check port state # check port state
# TODO(salvatore-orlando): Validate port state in API? # TODO(salvatore-orlando): Validate port state in API?
self._validate_port_state(port_state) self._validate_port_state(port_state)
ports = net['net-ports'] ports = net['net-ports']
new_port_id = max(ports.keys())+1 new_port_id = max(ports.keys()) + 1
new_port_dict = {'port-id':new_port_id, new_port_dict = {'port-id': new_port_id,
'port-state': port_state, 'port-state': port_state,
'attachment': None} 'attachment': None}
ports[new_port_id] = new_port_dict ports[new_port_id] = new_port_dict
return new_port_dict return new_port_dict
def update_port(self, tenant_id, net_id, port_id, port_state): def update_port(self, tenant_id, net_id, port_id, port_state):
""" """
@ -414,8 +389,8 @@ class FakePlugin(object):
port = self._get_port(tenant_id, net_id, port_id) port = self._get_port(tenant_id, net_id, port_id)
self._validate_port_state(port_state) self._validate_port_state(port_state)
port['port-state'] = port_state port['port-state'] = port_state
return port return port
def delete_port(self, tenant_id, net_id, port_id): def delete_port(self, tenant_id, net_id, port_id):
""" """
Deletes a port on a specified Virtual Network, Deletes a port on a specified Virtual Network,
@ -427,14 +402,13 @@ class FakePlugin(object):
net = self._get_network(tenant_id, net_id) net = self._get_network(tenant_id, net_id)
port = self._get_port(tenant_id, net_id, port_id) port = self._get_port(tenant_id, net_id, port_id)
if port['attachment']: if port['attachment']:
raise exc.PortInUse(net_id=net_id,port_id=port_id, raise exc.PortInUse(net_id=net_id, port_id=port_id,
att_id=port['attachment']) att_id=port['attachment'])
try: try:
net['net-ports'].pop(int(port_id)) net['net-ports'].pop(int(port_id))
except KeyError: except KeyError:
raise exc.PortNotFound(net_id=net_id, port_id=port_id) raise exc.PortNotFound(net_id=net_id, port_id=port_id)
def plug_interface(self, tenant_id, net_id, port_id, remote_interface_id): def plug_interface(self, tenant_id, net_id, port_id, remote_interface_id):
""" """
Attaches a remote interface to the specified port on the Attaches a remote interface to the specified port on the
@ -446,10 +420,10 @@ class FakePlugin(object):
remote_interface_id) remote_interface_id)
port = self._get_port(tenant_id, net_id, port_id) port = self._get_port(tenant_id, net_id, port_id)
if port['attachment']: if port['attachment']:
raise exc.PortInUse(net_id=net_id,port_id=port_id, raise exc.PortInUse(net_id=net_id, port_id=port_id,
att_id=port['attachment']) att_id=port['attachment'])
port['attachment'] = remote_interface_id port['attachment'] = remote_interface_id
def unplug_interface(self, tenant_id, net_id, port_id): def unplug_interface(self, tenant_id, net_id, port_id):
""" """
Detaches a remote interface from the specified port on the Detaches a remote interface from the specified port on the
@ -460,5 +434,3 @@ class FakePlugin(object):
# TODO(salvatore-orlando): # TODO(salvatore-orlando):
# Should unplug on port without attachment raise an Error? # Should unplug on port without attachment raise an Error?
port['attachment'] = None port['attachment'] = None

View File

@ -13,4 +13,4 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
# @author: Somik Behera, Nicira Networks, Inc. # @author: Somik Behera, Nicira Networks, Inc.

View File

@ -28,6 +28,7 @@ import time
from optparse import OptionParser from optparse import OptionParser
from subprocess import * from subprocess import *
# A class to represent a VIF (i.e., a port that has 'iface-id' and 'vif-mac' # A class to represent a VIF (i.e., a port that has 'iface-id' and 'vif-mac'
# attributes set). # attributes set).
class VifPort: class VifPort:
@ -37,11 +38,13 @@ class VifPort:
self.vif_id = vif_id self.vif_id = vif_id
self.vif_mac = vif_mac self.vif_mac = vif_mac
self.switch = switch self.switch = switch
def __str__(self): def __str__(self):
return "iface-id=" + self.vif_id + ", vif_mac=" + \ return "iface-id=" + self.vif_id + ", vif_mac=" + \
self.vif_mac + ", port_name=" + self.port_name + \ self.vif_mac + ", port_name=" + self.port_name + \
", ofport=" + self.ofport + ", bridge name = " + self.switch.br_name ", ofport=" + self.ofport + ", bridge name = " + self.switch.br_name
class OVSBridge: class OVSBridge:
def __init__(self, br_name): def __init__(self, br_name):
self.br_name = br_name self.br_name = br_name
@ -51,27 +54,27 @@ class OVSBridge:
return Popen(args, stdout=PIPE).communicate()[0] return Popen(args, stdout=PIPE).communicate()[0]
def run_vsctl(self, args): def run_vsctl(self, args):
full_args = ["ovs-vsctl" ] + args full_args = ["ovs-vsctl"] + args
return self.run_cmd(full_args) return self.run_cmd(full_args)
def reset_bridge(self): def reset_bridge(self):
self.run_vsctl([ "--" , "--if-exists", "del-br", self.br_name]) self.run_vsctl(["--", "--if-exists", "del-br", self.br_name])
self.run_vsctl(["add-br", self.br_name]) self.run_vsctl(["add-br", self.br_name])
def delete_port(self, port_name): def delete_port(self, port_name):
self.run_vsctl([ "--" , "--if-exists", "del-port", self.br_name, self.run_vsctl(["--", "--if-exists", "del-port", self.br_name,
port_name]) port_name])
def set_db_attribute(self, table_name, record, column, value): def set_db_attribute(self, table_name, record, column, value):
args = [ "set", table_name, record, "%s=%s" % (column,value) ] args = ["set", table_name, record, "%s=%s" % (column, value)]
self.run_vsctl(args) self.run_vsctl(args)
def clear_db_attribute(self, table_name,record, column): def clear_db_attribute(self, table_name, record, column):
args = [ "clear", table_name, record, column ] args = ["clear", table_name, record, column]
self.run_vsctl(args) self.run_vsctl(args)
def run_ofctl(self, cmd, args): def run_ofctl(self, cmd, args):
full_args = ["ovs-ofctl", cmd, self.br_name ] + args full_args = ["ovs-ofctl", cmd, self.br_name] + args
return self.run_cmd(full_args) return self.run_cmd(full_args)
def remove_all_flows(self): def remove_all_flows(self):
@ -80,7 +83,7 @@ class OVSBridge:
def get_port_ofport(self, port_name): def get_port_ofport(self, port_name):
return self.db_get_val("Interface", port_name, "ofport") return self.db_get_val("Interface", port_name, "ofport")
def add_flow(self,**dict): def add_flow(self, **dict):
if "actions" not in dict: if "actions" not in dict:
raise Exception("must specify one or more actions") raise Exception("must specify one or more actions")
if "priority" not in dict: if "priority" not in dict:
@ -90,9 +93,9 @@ class OVSBridge:
if "match" in dict: if "match" in dict:
flow_str += "," + dict["match"] flow_str += "," + dict["match"]
flow_str += ",actions=%s" % (dict["actions"]) flow_str += ",actions=%s" % (dict["actions"])
self.run_ofctl("add-flow", [ flow_str ] ) self.run_ofctl("add-flow", [flow_str])
def delete_flows(self,**dict): def delete_flows(self, **dict):
all_args = [] all_args = []
if "priority" in dict: if "priority" in dict:
all_args.append("priority=%s" % dict["priority"]) all_args.append("priority=%s" % dict["priority"])
@ -101,14 +104,14 @@ class OVSBridge:
if "actions" in dict: if "actions" in dict:
all_args.append("actions=%s" % (dict["actions"])) all_args.append("actions=%s" % (dict["actions"]))
flow_str = ",".join(all_args) flow_str = ",".join(all_args)
self.run_ofctl("del-flows", [ flow_str ] ) self.run_ofctl("del-flows", [flow_str])
def db_get_map(self, table, record, column): def db_get_map(self, table, record, column):
str = self.run_vsctl([ "get" , table, record, column ]).rstrip("\n\r") str = self.run_vsctl(["get", table, record, column]).rstrip("\n\r")
return self.db_str_to_map(str) return self.db_str_to_map(str)
def db_get_val(self, table, record, column): def db_get_val(self, table, record, column):
return self.run_vsctl([ "get" , table, record, column ]).rstrip("\n\r") return self.run_vsctl(["get", table, record, column]).rstrip("\n\r")
def db_str_to_map(self, full_str): def db_str_to_map(self, full_str):
list = full_str.strip("{}").split(", ") list = full_str.strip("{}").split(", ")
@ -121,7 +124,7 @@ class OVSBridge:
return ret return ret
def get_port_name_list(self): def get_port_name_list(self):
res = self.run_vsctl([ "list-ports", self.br_name]) res = self.run_vsctl(["list-ports", self.br_name])
return res.split("\n")[0:-1] return res.split("\n")[0:-1]
def get_port_stats(self, port_name): def get_port_stats(self, port_name):
@ -132,47 +135,53 @@ class OVSBridge:
edge_ports = [] edge_ports = []
port_names = self.get_port_name_list() port_names = self.get_port_name_list()
for name in port_names: for name in port_names:
external_ids = self.db_get_map("Interface",name,"external_ids") external_ids = self.db_get_map("Interface", name, "external_ids")
if "iface-id" in external_ids and "attached-mac" in external_ids: if "iface-id" in external_ids and "attached-mac" in external_ids:
ofport = self.db_get_val("Interface",name,"ofport") ofport = self.db_get_val("Interface", name, "ofport")
p = VifPort(name, ofport, external_ids["iface-id"], p = VifPort(name, ofport, external_ids["iface-id"],
external_ids["attached-mac"], self) external_ids["attached-mac"], self)
edge_ports.append(p) edge_ports.append(p)
else: else:
# iface-id might not be set. See if we can figure it out and # iface-id might not be set. See if we can figure it out and
# set it here. # set it here.
external_ids = self.db_get_map("Interface",name,"external_ids") external_ids = self.db_get_map("Interface", name,
"external_ids")
if "attached-mac" not in external_ids: if "attached-mac" not in external_ids:
continue continue
vif_uuid = external_ids.get("xs-vif-uuid", "") vif_uuid = external_ids.get("xs-vif-uuid", "")
if len(vif_uuid) == 0: if len(vif_uuid) == 0:
continue continue
LOG.debug("iface-id not set, got vif-uuid: %s" % vif_uuid) LOG.debug("iface-id not set, got vif-uuid: %s" % vif_uuid)
res = os.popen("xe vif-param-get param-name=other-config uuid=%s | grep nicira-iface-id | awk '{print $2}'" % vif_uuid).readline() res = os.popen("xe vif-param-get param-name=other-config "
"uuid=%s | grep nicira-iface-id | "
"awk '{print $2}'"
% vif_uuid).readline()
res = res.strip() res = res.strip()
if len(res) == 0: if len(res) == 0:
continue continue
external_ids["iface-id"] = res external_ids["iface-id"] = res
LOG.info("Setting interface \"%s\" iface-id to \"%s\"" % (name, res)) LOG.info("Setting interface \"%s\" iface-id to \"%s\""
% (name, res))
self.set_db_attribute("Interface", name, self.set_db_attribute("Interface", name,
"external-ids:iface-id", res) "external-ids:iface-id", res)
ofport = self.db_get_val("Interface",name,"ofport") ofport = self.db_get_val("Interface", name, "ofport")
p = VifPort(name, ofport, external_ids["iface-id"], p = VifPort(name, ofport, external_ids["iface-id"],
external_ids["attached-mac"], self) external_ids["attached-mac"], self)
edge_ports.append(p) edge_ports.append(p)
return edge_ports return edge_ports
class OVSNaaSPlugin: class OVSNaaSPlugin:
def __init__(self, integ_br): def __init__(self, integ_br):
self.setup_integration_br(integ_br) self.setup_integration_br(integ_br)
def port_bound(self, port, vlan_id): def port_bound(self, port, vlan_id):
self.int_br.set_db_attribute("Port", port.port_name,"tag", self.int_br.set_db_attribute("Port", port.port_name, "tag",
str(vlan_id)) str(vlan_id))
def port_unbound(self, port, still_exists): def port_unbound(self, port, still_exists):
if still_exists: if still_exists:
self.int_br.clear_db_attribute("Port", port.port_name,"tag") self.int_br.clear_db_attribute("Port", port.port_name, "tag")
def setup_integration_br(self, integ_br): def setup_integration_br(self, integ_br):
self.int_br = OVSBridge(integ_br) self.int_br = OVSBridge(integ_br)
@ -182,7 +191,8 @@ class OVSNaaSPlugin:
# switch all other traffic using L2 learning # switch all other traffic using L2 learning
self.int_br.add_flow(priority=1, actions="normal") self.int_br.add_flow(priority=1, actions="normal")
# FIXME send broadcast everywhere, regardless of tenant # FIXME send broadcast everywhere, regardless of tenant
#int_br.add_flow(priority=3, match="dl_dst=ff:ff:ff:ff:ff:ff", actions="normal") #int_br.add_flow(priority=3, match="dl_dst=ff:ff:ff:ff:ff:ff",
# actions="normal")
def daemon_loop(self, conn): def daemon_loop(self, conn):
self.local_vlan_map = {} self.local_vlan_map = {}
@ -216,9 +226,9 @@ class OVSNaaSPlugin:
else: else:
# no binding, put him on the 'dead vlan' # no binding, put him on the 'dead vlan'
self.int_br.set_db_attribute("Port", p.port_name, "tag", self.int_br.set_db_attribute("Port", p.port_name, "tag",
"4095") "4095")
old_b = old_local_bindings.get(p.vif_id,None) old_b = old_local_bindings.get(p.vif_id, None)
new_b = new_local_bindings.get(p.vif_id,None) new_b = new_local_bindings.get(p.vif_id, None)
if old_b != new_b: if old_b != new_b:
if old_b is not None: if old_b is not None:
LOG.info("Removing binding to net-id = %s for %s" LOG.info("Removing binding to net-id = %s for %s"

View File

@ -24,6 +24,7 @@ import quantum.db.api as db
import quantum.db.models as models import quantum.db.models as models
import ovs_models import ovs_models
def get_vlans(): def get_vlans():
session = db.get_session() session = db.get_session()
try: try:
@ -33,9 +34,10 @@ def get_vlans():
return [] return []
res = [] res = []
for x in bindings: for x in bindings:
res.append((x.vlan_id, x.network_id)) res.append((x.vlan_id, x.network_id))
return res return res
def add_vlan_binding(vlanid, netid): def add_vlan_binding(vlanid, netid):
session = db.get_session() session = db.get_session()
binding = ovs_models.VlanBinding(vlanid, netid) binding = ovs_models.VlanBinding(vlanid, netid)
@ -43,6 +45,7 @@ def add_vlan_binding(vlanid, netid):
session.flush() session.flush()
return binding.vlan_id return binding.vlan_id
def remove_vlan_binding(netid): def remove_vlan_binding(netid):
session = db.get_session() session = db.get_session()
try: try:
@ -54,6 +57,7 @@ def remove_vlan_binding(netid):
pass pass
session.flush() session.flush()
def update_network_binding(netid, ifaceid): def update_network_binding(netid, ifaceid):
session = db.get_session() session = db.get_session()
# Add to or delete from the bindings table # Add to or delete from the bindings table

View File

@ -23,9 +23,9 @@ import uuid
from sqlalchemy import Column, Integer, String, ForeignKey from sqlalchemy import Column, Integer, String, ForeignKey
from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relation from sqlalchemy.orm import relation
from quantum.db.models import BASE from quantum.db.models import BASE
class NetworkBinding(BASE): class NetworkBinding(BASE):
"""Represents a binding of network_id, vif_id""" """Represents a binding of network_id, vif_id"""
__tablename__ = 'network_bindings' __tablename__ = 'network_bindings'
@ -42,6 +42,7 @@ class NetworkBinding(BASE):
return "<NetworkBinding(%s,%s)>" % \ return "<NetworkBinding(%s,%s)>" % \
(self.network_id, self.vif_id) (self.network_id, self.vif_id)
class VlanBinding(BASE): class VlanBinding(BASE):
"""Represents a binding of network_id, vlan_id""" """Represents a binding of network_id, vlan_id"""
__tablename__ = 'vlan_bindings' __tablename__ = 'vlan_bindings'

View File

@ -29,24 +29,29 @@ from optparse import OptionParser
import quantum.db.api as db import quantum.db.api as db
import ovs_db import ovs_db
CONF_FILE="ovs_quantum_plugin.ini" CONF_FILE = "ovs_quantum_plugin.ini"
LOG.basicConfig(level=LOG.WARN) LOG.basicConfig(level=LOG.WARN)
LOG.getLogger("ovs_quantum_plugin") LOG.getLogger("ovs_quantum_plugin")
def find_config(basepath): def find_config(basepath):
for root, dirs, files in os.walk(basepath): for root, dirs, files in os.walk(basepath):
if CONF_FILE in files: if CONF_FILE in files:
return os.path.join(root, CONF_FILE) return os.path.join(root, CONF_FILE)
return None return None
class VlanMap(object): class VlanMap(object):
vlans = {} vlans = {}
def __init__(self): def __init__(self):
for x in xrange(2, 4094): for x in xrange(2, 4094):
self.vlans[x] = None self.vlans[x] = None
def set(self, vlan_id, network_id): def set(self, vlan_id, network_id):
self.vlans[vlan_id] = network_id self.vlans[vlan_id] = network_id
def acquire(self, network_id): def acquire(self, network_id):
for x in xrange(2, 4094): for x in xrange(2, 4094):
if self.vlans[x] == None: if self.vlans[x] == None:
@ -54,8 +59,10 @@ class VlanMap(object):
# LOG.debug("VlanMap::acquire %s -> %s" % (x, network_id)) # LOG.debug("VlanMap::acquire %s -> %s" % (x, network_id))
return x return x
raise Exception("No free vlans..") raise Exception("No free vlans..")
def get(self, vlan_id): def get(self, vlan_id):
return self.vlans[vlan_id] return self.vlans[vlan_id]
def release(self, network_id): def release(self, network_id):
for x in self.vlans.keys(): for x in self.vlans.keys():
if self.vlans[x] == network_id: if self.vlans[x] == network_id:
@ -64,14 +71,17 @@ class VlanMap(object):
return return
LOG.error("No vlan found with network \"%s\"" % network_id) LOG.error("No vlan found with network \"%s\"" % network_id)
class OVSQuantumPlugin(QuantumPluginBase): class OVSQuantumPlugin(QuantumPluginBase):
def __init__(self, configfile=None): def __init__(self, configfile=None):
config = ConfigParser.ConfigParser() config = ConfigParser.ConfigParser()
if configfile == None: if configfile == None:
if os.path.exists(CONF_FILE): if os.path.exists(CONF_FILE):
configfile = CONF_FILE configfile = CONF_FILE
else: else:
configfile = find_config(os.path.abspath(os.path.dirname(__file__))) configfile = find_config(os.path.abspath(
os.path.dirname(__file__)))
if configfile == None: if configfile == None:
raise Exception("Configuration file \"%s\" doesn't exist" % raise Exception("Configuration file \"%s\" doesn't exist" %
(configfile)) (configfile))
@ -93,7 +103,8 @@ class OVSQuantumPlugin(QuantumPluginBase):
vlans = ovs_db.get_vlans() vlans = ovs_db.get_vlans()
for x in vlans: for x in vlans:
vlan_id, network_id = x vlan_id, network_id = x
# LOG.debug("Adding already populated vlan %s -> %s" % (vlan_id, network_id)) # LOG.debug("Adding already populated vlan %s -> %s"
# % (vlan_id, network_id))
self.vmap.set(vlan_id, network_id) self.vmap.set(vlan_id, network_id)
def get_all_networks(self, tenant_id): def get_all_networks(self, tenant_id):
@ -109,8 +120,8 @@ class OVSQuantumPlugin(QuantumPluginBase):
def create_network(self, tenant_id, net_name): def create_network(self, tenant_id, net_name):
d = {} d = {}
try: try:
res = db.network_create(tenant_id, net_name) res = db.network_create(tenant_id, net_name)
LOG.debug("Created newtork: %s" % res) LOG.debug("Created newtork: %s" % res)
except Exception, e: except Exception, e:
LOG.error("Error: %s" % str(e)) LOG.error("Error: %s" % str(e))
return d return d
@ -199,21 +210,28 @@ class OVSQuantumPlugin(QuantumPluginBase):
res = db.port_get(port_id) res = db.port_get(port_id)
return res.interface_id return res.interface_id
class VlanMapTest(unittest.TestCase): class VlanMapTest(unittest.TestCase):
def setUp(self): def setUp(self):
self.vmap = VlanMap() self.vmap = VlanMap()
def tearDown(self): def tearDown(self):
pass pass
def testAddVlan(self): def testAddVlan(self):
vlan_id = self.vmap.acquire("foobar") vlan_id = self.vmap.acquire("foobar")
self.assertTrue(vlan_id == 2) self.assertTrue(vlan_id == 2)
def testReleaseVlan(self): def testReleaseVlan(self):
vlan_id = self.vmap.acquire("foobar") vlan_id = self.vmap.acquire("foobar")
self.vmap.release("foobar") self.vmap.release("foobar")
self.assertTrue(self.vmap.get(vlan_id) == None) self.assertTrue(self.vmap.get(vlan_id) == None)
# TODO(bgh): Make the tests use a sqlite database instead of mysql # TODO(bgh): Make the tests use a sqlite database instead of mysql
class OVSPluginTest(unittest.TestCase): class OVSPluginTest(unittest.TestCase):
def setUp(self): def setUp(self):
self.quantum = OVSQuantumPlugin() self.quantum = OVSQuantumPlugin()
self.tenant_id = "testtenant" self.tenant_id = "testtenant"
@ -312,6 +330,7 @@ class OVSPluginTest(unittest.TestCase):
self.quantum.delete_port(self.tenant_id, id, p["port-id"]) self.quantum.delete_port(self.tenant_id, id, p["port-id"])
self.quantum.delete_network(self.tenant_id, id) self.quantum.delete_network(self.tenant_id, id)
if __name__ == "__main__": if __name__ == "__main__":
usagestr = "Usage: %prog [OPTIONS] <command> [args]" usagestr = "Usage: %prog [OPTIONS] <command> [args]"
parser = OptionParser(usage=usagestr) parser = OptionParser(usage=usagestr)

View File

@ -19,6 +19,7 @@ import httplib
import socket import socket
import urllib import urllib
class MiniClient(object): class MiniClient(object):
"""A base client class - derived from Glance.BaseClient""" """A base client class - derived from Glance.BaseClient"""
@ -50,7 +51,7 @@ class MiniClient(object):
def do_request(self, tenant, method, action, body=None, def do_request(self, tenant, method, action, body=None,
headers=None, params=None): 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
HTTP status code is not 2xx HTTP status code is not 2xx
@ -62,14 +63,14 @@ class MiniClient(object):
""" """
action = MiniClient.action_prefix + action action = MiniClient.action_prefix + action
action = action.replace('{tenant_id}',tenant) action = action.replace('{tenant_id}', tenant)
if type(params) is dict: if type(params) is dict:
action += '?' + urllib.urlencode(params) action += '?' + urllib.urlencode(params)
try: try:
connection_type = self.get_connection_type() connection_type = self.get_connection_type()
headers = headers or {} headers = headers or {}
# Open connection and send request # Open connection and send request
c = connection_type(self.host, self.port) c = connection_type(self.host, self.port)
c.request(method, action, body, headers) c.request(method, action, body, headers)
@ -95,4 +96,4 @@ class MiniClient(object):
if hasattr(response, 'status_int'): if hasattr(response, 'status_int'):
return response.status_int return response.status_int
else: else:
return response.status return response.status

View File

@ -34,16 +34,18 @@ TENANT_ID = 'totore'
FORMAT = "json" FORMAT = "json"
test_network1_data = \ test_network1_data = \
{'network': {'network-name': 'test1' }} {'network': {'network-name': 'test1'}}
test_network2_data = \ test_network2_data = \
{'network': {'network-name': 'test2' }} {'network': {'network-name': 'test2'}}
def print_response(res): def print_response(res):
content = res.read() content = res.read()
print "Status: %s" %res.status print "Status: %s" % res.status
print "Content: %s" %content print "Content: %s" % content
return content return content
class QuantumTest(unittest.TestCase): class QuantumTest(unittest.TestCase):
def setUp(self): def setUp(self):
self.client = MiniClient(HOST, PORT, USE_SSL) self.client = MiniClient(HOST, PORT, USE_SSL)
@ -58,7 +60,7 @@ class QuantumTest(unittest.TestCase):
def test_listNetworks(self): def test_listNetworks(self):
self.create_network(test_network1_data) self.create_network(test_network1_data)
self.create_network(test_network2_data) self.create_network(test_network2_data)
res = self.client.do_request(TENANT_ID,'GET', "/networks." + FORMAT) res = self.client.do_request(TENANT_ID, 'GET', "/networks." + FORMAT)
self.assertEqual(res.status, 200, "bad response: %s" % res.read()) self.assertEqual(res.status, 200, "bad response: %s" % res.read())
def test_createNetwork(self): def test_createNetwork(self):
@ -111,8 +113,9 @@ class QuantumTest(unittest.TestCase):
resdict = simplejson.loads(res.read()) resdict = simplejson.loads(res.read())
self.assertTrue(resdict["networks"]["network"]["id"] == net_id, self.assertTrue(resdict["networks"]["network"]["id"] == net_id,
"Network_rename: renamed network has a different uuid") "Network_rename: renamed network has a different uuid")
self.assertTrue(resdict["networks"]["network"]["name"] == "test_renamed", self.assertTrue(
"Network rename didn't take effect") resdict["networks"]["network"]["name"] == "test_renamed",
"Network rename didn't take effect")
def delete_networks(self): def delete_networks(self):
# Remove all the networks created on the tenant # Remove all the networks created on the tenant