7b38df15a1
Change-Id: Iab4c2ada2bfcb99452f940666b25cb1f7d4d7e58
259 lines
10 KiB
Python
259 lines
10 KiB
Python
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
|
#
|
|
# Copyright 2012, Cisco Systems, Inc.
|
|
#
|
|
# 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
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
# @author: Sumit Naiksatam, Cisco Systems, Inc.
|
|
|
|
import logging
|
|
|
|
from quantum.api.api_common import OperationalStatus
|
|
from quantum.common import exceptions as exc
|
|
from quantum.db import api as db
|
|
from quantum.plugins.linuxbridge.common import constants as const
|
|
from quantum.plugins.linuxbridge.common import utils as cutil
|
|
from quantum.plugins.linuxbridge.db import l2network_db as cdb
|
|
from quantum.quantum_plugin_base import QuantumPluginBase
|
|
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
|
|
class LinuxBridgePlugin(QuantumPluginBase):
|
|
"""
|
|
LinuxBridgePlugin provides support for Quantum abstractions
|
|
using LinuxBridge. A new VLAN is created for each network.
|
|
It relies on an agent to perform the actual bridge configuration
|
|
on each host.
|
|
"""
|
|
|
|
def __init__(self, configfile=None):
|
|
cdb.initialize()
|
|
LOG.debug("Linux Bridge Plugin initialization done successfully")
|
|
|
|
def _get_vlan_for_tenant(self, tenant_id, **kwargs):
|
|
"""Get an available VLAN ID"""
|
|
try:
|
|
return cdb.reserve_vlanid()
|
|
except:
|
|
raise Exception("Failed to reserve VLAN ID for network")
|
|
|
|
def _release_vlan_for_tenant(self, tenant_id, net_id, **kwargs):
|
|
"""Release the ID"""
|
|
vlan_binding = cdb.get_vlan_binding(net_id)
|
|
return cdb.release_vlanid(vlan_binding[const.VLANID])
|
|
|
|
def _validate_port_state(self, port_state):
|
|
if port_state.upper() not in ('ACTIVE', 'DOWN'):
|
|
raise exc.StateInvalid(port_state=port_state)
|
|
return True
|
|
|
|
def get_all_networks(self, tenant_id, **kwargs):
|
|
"""
|
|
Returns a dictionary containing all
|
|
<network_uuid, network_name> for
|
|
the specified tenant.
|
|
"""
|
|
LOG.debug("LinuxBridgePlugin.get_all_networks() called")
|
|
networks_list = db.network_list(tenant_id)
|
|
new_networks_list = []
|
|
for network in networks_list:
|
|
new_network_dict = cutil.make_net_dict(network[const.UUID],
|
|
network[const.NETWORKNAME],
|
|
[], network[const.OPSTATUS])
|
|
new_networks_list.append(new_network_dict)
|
|
|
|
# This plugin does not perform filtering at the moment
|
|
return new_networks_list
|
|
|
|
def get_network_details(self, tenant_id, net_id):
|
|
"""
|
|
retrieved a list of all the remote vifs that
|
|
are attached to the network
|
|
"""
|
|
LOG.debug("LinuxBridgePlugin.get_network_details() called")
|
|
db.validate_network_ownership(tenant_id, net_id)
|
|
network = db.network_get(net_id)
|
|
ports_list = db.port_list(net_id)
|
|
ports_on_net = []
|
|
for port in ports_list:
|
|
new_port = cutil.make_port_dict(port)
|
|
ports_on_net.append(new_port)
|
|
|
|
new_network = cutil.make_net_dict(network[const.UUID],
|
|
network[const.NETWORKNAME],
|
|
ports_on_net,
|
|
network[const.OPSTATUS])
|
|
|
|
return new_network
|
|
|
|
def create_network(self, tenant_id, net_name, **kwargs):
|
|
"""
|
|
Creates a new Virtual Network, and assigns it
|
|
a symbolic name.
|
|
"""
|
|
LOG.debug("LinuxBridgePlugin.create_network() called")
|
|
new_network = db.network_create(tenant_id, net_name,
|
|
op_status=OperationalStatus.UP)
|
|
new_net_id = new_network[const.UUID]
|
|
vlan_id = self._get_vlan_for_tenant(tenant_id)
|
|
cdb.add_vlan_binding(vlan_id, new_net_id)
|
|
new_net_dict = {
|
|
const.NET_ID: new_net_id,
|
|
const.NET_NAME: net_name,
|
|
const.NET_PORTS: [],
|
|
const.NET_OP_STATUS: new_network[const.OPSTATUS],
|
|
}
|
|
return new_net_dict
|
|
|
|
def delete_network(self, tenant_id, net_id):
|
|
"""
|
|
Deletes the network with the specified network identifier
|
|
belonging to the specified tenant.
|
|
"""
|
|
LOG.debug("LinuxBridgePlugin.delete_network() called")
|
|
db.validate_network_ownership(tenant_id, net_id)
|
|
net = db.network_get(net_id)
|
|
if net:
|
|
ports_on_net = db.port_list(net_id)
|
|
if len(ports_on_net) > 0:
|
|
for port in ports_on_net:
|
|
if port[const.INTERFACEID]:
|
|
raise exc.NetworkInUse(net_id=net_id)
|
|
for port in ports_on_net:
|
|
self.delete_port(tenant_id, net_id, port[const.UUID])
|
|
|
|
net_dict = cutil.make_net_dict(net[const.UUID],
|
|
net[const.NETWORKNAME],
|
|
[], net[const.OPSTATUS])
|
|
try:
|
|
self._release_vlan_for_tenant(tenant_id, net_id)
|
|
cdb.remove_vlan_binding(net_id)
|
|
except Exception as excp:
|
|
LOG.warning("Exception: %s" % excp)
|
|
db.network_update(net_id, tenant_id, {const.OPSTATUS:
|
|
OperationalStatus.DOWN})
|
|
db.network_destroy(net_id)
|
|
return net_dict
|
|
# Network not found
|
|
raise exc.NetworkNotFound(net_id=net_id)
|
|
|
|
def update_network(self, tenant_id, net_id, **kwargs):
|
|
"""
|
|
Updates the attributes of a particular Virtual Network.
|
|
"""
|
|
LOG.debug("LinuxBridgePlugin.update_network() called")
|
|
db.validate_network_ownership(tenant_id, net_id)
|
|
network = db.network_update(net_id, tenant_id, **kwargs)
|
|
net_dict = cutil.make_net_dict(network[const.UUID],
|
|
network[const.NETWORKNAME],
|
|
[], network[const.OPSTATUS])
|
|
return net_dict
|
|
|
|
def get_all_ports(self, tenant_id, net_id, **kwargs):
|
|
"""
|
|
Retrieves all port identifiers belonging to the
|
|
specified Virtual Network.
|
|
"""
|
|
LOG.debug("LinuxBridgePlugin.get_all_ports() called")
|
|
db.validate_network_ownership(tenant_id, net_id)
|
|
ports_list = db.port_list(net_id)
|
|
ports_on_net = []
|
|
for port in ports_list:
|
|
new_port = cutil.make_port_dict(port)
|
|
ports_on_net.append(new_port)
|
|
|
|
# This plugin does not perform filtering at the moment
|
|
return ports_on_net
|
|
|
|
def get_port_details(self, tenant_id, net_id, port_id):
|
|
"""
|
|
This method allows the user to retrieve a remote interface
|
|
that is attached to this particular port.
|
|
"""
|
|
LOG.debug("LinuxBridgePlugin.get_port_details() called")
|
|
db.validate_port_ownership(tenant_id, net_id, port_id)
|
|
port = db.port_get(port_id, net_id)
|
|
new_port_dict = cutil.make_port_dict(port)
|
|
return new_port_dict
|
|
|
|
def create_port(self, tenant_id, net_id, port_state=None, **kwargs):
|
|
"""
|
|
Creates a port on the specified Virtual Network.
|
|
"""
|
|
LOG.debug("LinuxBridgePlugin.create_port() called")
|
|
db.validate_network_ownership(tenant_id, net_id)
|
|
port = db.port_create(net_id, port_state,
|
|
op_status=OperationalStatus.DOWN)
|
|
new_port_dict = cutil.make_port_dict(port)
|
|
return new_port_dict
|
|
|
|
def update_port(self, tenant_id, net_id, port_id, **kwargs):
|
|
"""
|
|
Updates the attributes of a port on the specified Virtual Network.
|
|
"""
|
|
LOG.debug("LinuxBridgePlugin.update_port() called")
|
|
db.validate_port_ownership(tenant_id, net_id, port_id)
|
|
self._validate_port_state(kwargs["state"])
|
|
port = db.port_update(port_id, net_id, **kwargs)
|
|
|
|
new_port_dict = cutil.make_port_dict(port)
|
|
return new_port_dict
|
|
|
|
def delete_port(self, tenant_id, net_id, port_id):
|
|
"""
|
|
Deletes a port on a specified Virtual Network,
|
|
if the port contains a remote interface attachment,
|
|
the remote interface is first un-plugged and then the port
|
|
is deleted.
|
|
"""
|
|
LOG.debug("LinuxBridgePlugin.delete_port() called")
|
|
db.validate_port_ownership(tenant_id, net_id, port_id)
|
|
port = db.port_get(port_id, net_id)
|
|
attachment_id = port[const.INTERFACEID]
|
|
if not attachment_id:
|
|
db.port_destroy(port_id, net_id)
|
|
new_port_dict = cutil.make_port_dict(port)
|
|
return new_port_dict
|
|
else:
|
|
raise exc.PortInUse(port_id=port_id, net_id=net_id,
|
|
att_id=attachment_id)
|
|
|
|
def plug_interface(self, tenant_id, net_id, port_id, remote_interface_id):
|
|
"""
|
|
Attaches a remote interface to the specified port on the
|
|
specified Virtual Network.
|
|
"""
|
|
LOG.debug("LinuxBridgePlugin.plug_interface() called")
|
|
db.validate_port_ownership(tenant_id, net_id, port_id)
|
|
port = db.port_get(port_id, net_id)
|
|
attachment_id = port[const.INTERFACEID]
|
|
if attachment_id:
|
|
raise exc.PortInUse(port_id=port_id, net_id=net_id,
|
|
att_id=attachment_id)
|
|
db.port_set_attachment(port_id, net_id, remote_interface_id)
|
|
|
|
def unplug_interface(self, tenant_id, net_id, port_id):
|
|
"""
|
|
Detaches a remote interface from the specified port on the
|
|
specified Virtual Network.
|
|
"""
|
|
LOG.debug("LinuxBridgePlugin.unplug_interface() called")
|
|
db.validate_port_ownership(tenant_id, net_id, port_id)
|
|
port = db.port_get(port_id, net_id)
|
|
attachment_id = port[const.INTERFACEID]
|
|
if attachment_id is None:
|
|
return
|
|
db.port_unset_attachment(port_id, net_id)
|
|
db.port_update(port_id, net_id, op_status=OperationalStatus.DOWN)
|