c66212cf5d
This commit enhances the port, bridge and router resources with the admin_state_up flag in the MidoNet plugin. Implements: blueprint midonet-admin-state Change-Id: I67f4f9ad4099a05f8161aae79331ebba84f561b8
697 lines
27 KiB
Python
697 lines
27 KiB
Python
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
|
|
|
# Copyright (C) 2012 Midokura Japan K.K.
|
|
# Copyright (C) 2013 Midokura PTE LTD
|
|
# All Rights Reserved.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# 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: Tomoe Sugihara, Midokura Japan KK
|
|
# @author: Ryu Ishimoto, Midokura Japan KK
|
|
# @author: Rossella Sblendido, Midokura Japan KK
|
|
# @author: Duarte Nunes, Midokura Japan KK
|
|
|
|
from midonetclient import exc
|
|
from webob import exc as w_exc
|
|
|
|
from neutron.common import exceptions as n_exc
|
|
from neutron.openstack.common import log as logging
|
|
from neutron.plugins.midonet.common import net_util
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
|
|
def handle_api_error(fn):
|
|
"""Wrapper for methods that throws custom exceptions."""
|
|
def wrapped(*args, **kwargs):
|
|
try:
|
|
return fn(*args, **kwargs)
|
|
except (w_exc.HTTPException,
|
|
exc.MidoApiConnectionError) as ex:
|
|
raise MidonetApiException(msg=ex)
|
|
return wrapped
|
|
|
|
|
|
class MidonetResourceNotFound(n_exc.NotFound):
|
|
message = _('MidoNet %(resource_type)s %(id)s could not be found')
|
|
|
|
|
|
class MidonetApiException(n_exc.NeutronException):
|
|
message = _("MidoNet API error: %(msg)s")
|
|
|
|
|
|
class MidoClient:
|
|
|
|
def __init__(self, mido_api):
|
|
self.mido_api = mido_api
|
|
|
|
@classmethod
|
|
def _fill_dto(cls, dto, fields):
|
|
for field_name, field_value in fields.iteritems():
|
|
# We assume the setters are named the
|
|
# same way as the attributes themselves.
|
|
try:
|
|
getattr(dto, field_name)(field_value)
|
|
except AttributeError:
|
|
pass
|
|
return dto
|
|
|
|
@classmethod
|
|
def _create_dto(cls, dto, fields):
|
|
return cls._fill_dto(dto, fields).create()
|
|
|
|
@classmethod
|
|
def _update_dto(cls, dto, fields):
|
|
return cls._fill_dto(dto, fields).update()
|
|
|
|
@handle_api_error
|
|
def create_bridge(self, **kwargs):
|
|
"""Create a new bridge
|
|
|
|
:param \**kwargs: configuration of the new bridge
|
|
:returns: newly created bridge
|
|
"""
|
|
LOG.debug(_("MidoClient.create_bridge called: "
|
|
"kwargs=%(kwargs)s"), {'kwargs': kwargs})
|
|
return self._create_dto(self.mido_api.add_bridge(), kwargs)
|
|
|
|
@handle_api_error
|
|
def delete_bridge(self, id):
|
|
"""Delete a bridge
|
|
|
|
:param id: id of the bridge
|
|
"""
|
|
LOG.debug(_("MidoClient.delete_bridge called: id=%(id)s"), {'id': id})
|
|
return self.mido_api.delete_bridge(id)
|
|
|
|
@handle_api_error
|
|
def get_bridge(self, id):
|
|
"""Get a bridge
|
|
|
|
:param id: id of the bridge
|
|
:returns: requested bridge. None if bridge does not exist.
|
|
"""
|
|
LOG.debug(_("MidoClient.get_bridge called: id=%s"), id)
|
|
try:
|
|
return self.mido_api.get_bridge(id)
|
|
except w_exc.HTTPNotFound:
|
|
raise MidonetResourceNotFound(resource_type='Bridge', id=id)
|
|
|
|
@handle_api_error
|
|
def update_bridge(self, id, **kwargs):
|
|
"""Update a bridge of the given id with the new fields
|
|
|
|
:param id: id of the bridge
|
|
:param \**kwargs: the fields to update and their values
|
|
:returns: bridge object
|
|
"""
|
|
LOG.debug(_("MidoClient.update_bridge called: "
|
|
"id=%(id)s, kwargs=%(kwargs)s"),
|
|
{'id': id, 'kwargs': kwargs})
|
|
try:
|
|
return self._update_dto(self.mido_api.get_bridge(id), kwargs)
|
|
except w_exc.HTTPNotFound:
|
|
raise MidonetResourceNotFound(resource_type='Bridge', id=id)
|
|
|
|
@handle_api_error
|
|
def create_dhcp(self, bridge, gateway_ip, cidr, host_rts=None,
|
|
dns_servers=None):
|
|
"""Create a new DHCP entry
|
|
|
|
:param bridge: bridge object to add dhcp to
|
|
:param gateway_ip: IP address of gateway
|
|
:param cidr: subnet represented as x.x.x.x/y
|
|
:param host_rts: list of routes set in the host
|
|
:param dns_servers: list of dns servers
|
|
:returns: newly created dhcp
|
|
"""
|
|
LOG.debug(_("MidoClient.create_dhcp called: bridge=%(bridge)s, "
|
|
"cidr=%(cidr)s, gateway_ip=%(gateway_ip)s, "
|
|
"host_rts=%(host_rts)s, dns_servers=%(dns_servers)s"),
|
|
{'bridge': bridge, 'cidr': cidr, 'gateway_ip': gateway_ip,
|
|
'host_rts': host_rts, 'dns_servers': dns_servers})
|
|
self.mido_api.add_bridge_dhcp(bridge, gateway_ip, cidr,
|
|
host_rts=host_rts,
|
|
dns_nservers=dns_servers)
|
|
|
|
@handle_api_error
|
|
def add_dhcp_host(self, bridge, cidr, ip, mac):
|
|
"""Add DHCP host entry
|
|
|
|
:param bridge: bridge the DHCP is configured for
|
|
:param cidr: subnet represented as x.x.x.x/y
|
|
:param ip: IP address
|
|
:param mac: MAC address
|
|
"""
|
|
LOG.debug(_("MidoClient.add_dhcp_host called: bridge=%(bridge)s, "
|
|
"cidr=%(cidr)s, ip=%(ip)s, mac=%(mac)s"),
|
|
{'bridge': bridge, 'cidr': cidr, 'ip': ip, 'mac': mac})
|
|
subnet = bridge.get_dhcp_subnet(net_util.subnet_str(cidr))
|
|
if subnet is None:
|
|
raise MidonetApiException(msg=_("Tried to add to"
|
|
"non-existent DHCP"))
|
|
|
|
subnet.add_dhcp_host().ip_addr(ip).mac_addr(mac).create()
|
|
|
|
@handle_api_error
|
|
def remove_dhcp_host(self, bridge, cidr, ip, mac):
|
|
"""Remove DHCP host entry
|
|
|
|
:param bridge: bridge the DHCP is configured for
|
|
:param cidr: subnet represented as x.x.x.x/y
|
|
:param ip: IP address
|
|
:param mac: MAC address
|
|
"""
|
|
LOG.debug(_("MidoClient.remove_dhcp_host called: bridge=%(bridge)s, "
|
|
"cidr=%(cidr)s, ip=%(ip)s, mac=%(mac)s"),
|
|
{'bridge': bridge, 'cidr': cidr, 'ip': ip, 'mac': mac})
|
|
subnet = bridge.get_dhcp_subnet(net_util.subnet_str(cidr))
|
|
if subnet is None:
|
|
LOG.warn(_("Tried to delete mapping from non-existent subnet"))
|
|
return
|
|
|
|
for dh in subnet.get_dhcp_hosts():
|
|
if dh.get_mac_addr() == mac and dh.get_ip_addr() == ip:
|
|
LOG.debug(_("MidoClient.remove_dhcp_host: Deleting %(dh)r"),
|
|
{"dh": dh})
|
|
dh.delete()
|
|
|
|
@handle_api_error
|
|
def delete_dhcp_host(self, bridge_id, cidr, ip, mac):
|
|
"""Delete DHCP host entry
|
|
|
|
:param bridge_id: id of the bridge of the DHCP
|
|
:param cidr: subnet represented as x.x.x.x/y
|
|
:param ip: IP address
|
|
:param mac: MAC address
|
|
"""
|
|
LOG.debug(_("MidoClient.delete_dhcp_host called: "
|
|
"bridge_id=%(bridge_id)s, cidr=%(cidr)s, ip=%(ip)s, "
|
|
"mac=%(mac)s"), {'bridge_id': bridge_id,
|
|
'cidr': cidr,
|
|
'ip': ip, 'mac': mac})
|
|
bridge = self.get_bridge(bridge_id)
|
|
self.remove_dhcp_host(bridge, net_util.subnet_str(cidr), ip, mac)
|
|
|
|
@handle_api_error
|
|
def delete_dhcp(self, bridge, cidr):
|
|
"""Delete a DHCP entry
|
|
|
|
:param bridge: bridge to remove DHCP from
|
|
:param cidr: subnet represented as x.x.x.x/y
|
|
"""
|
|
LOG.debug(_("MidoClient.delete_dhcp called: bridge=%(bridge)s, "
|
|
"cidr=%(cidr)s"),
|
|
{'bridge': bridge, 'cidr': cidr})
|
|
dhcp_subnets = bridge.get_dhcp_subnets()
|
|
net_addr, net_len = net_util.net_addr(cidr)
|
|
if not dhcp_subnets:
|
|
raise MidonetApiException(
|
|
msg=_("Tried to delete non-existent DHCP"))
|
|
for dhcp in dhcp_subnets:
|
|
if dhcp.get_subnet_prefix() == net_addr:
|
|
dhcp.delete()
|
|
break
|
|
|
|
@handle_api_error
|
|
def delete_port(self, id, delete_chains=False):
|
|
"""Delete a port
|
|
|
|
:param id: id of the port
|
|
"""
|
|
LOG.debug(_("MidoClient.delete_port called: id=%(id)s, "
|
|
"delete_chains=%(delete_chains)s"),
|
|
{'id': id, 'delete_chains': delete_chains})
|
|
if delete_chains:
|
|
self.delete_port_chains(id)
|
|
|
|
self.mido_api.delete_port(id)
|
|
|
|
@handle_api_error
|
|
def get_port(self, id):
|
|
"""Get a port
|
|
|
|
:param id: id of the port
|
|
:returns: requested port. None if it does not exist
|
|
"""
|
|
LOG.debug(_("MidoClient.get_port called: id=%(id)s"), {'id': id})
|
|
try:
|
|
return self.mido_api.get_port(id)
|
|
except w_exc.HTTPNotFound:
|
|
raise MidonetResourceNotFound(resource_type='Port', id=id)
|
|
|
|
@handle_api_error
|
|
def add_bridge_port(self, bridge, **kwargs):
|
|
"""Add a port on a bridge
|
|
|
|
:param bridge: bridge to add a new port to
|
|
:param \**kwargs: configuration of the new port
|
|
:returns: newly created port
|
|
"""
|
|
LOG.debug(_("MidoClient.add_bridge_port called: "
|
|
"bridge=%(bridge)s, kwargs=%(kwargs)s"),
|
|
{'bridge': bridge, 'kwargs': kwargs})
|
|
return self._create_dto(self.mido_api.add_bridge_port(bridge), kwargs)
|
|
|
|
@handle_api_error
|
|
def update_port(self, id, **kwargs):
|
|
"""Update a port of the given id with the new fields
|
|
|
|
:param id: id of the port
|
|
:param \**kwargs: the fields to update and their values
|
|
"""
|
|
LOG.debug(_("MidoClient.update_port called: "
|
|
"id=%(id)s, kwargs=%(kwargs)s"),
|
|
{'id': id, 'kwargs': kwargs})
|
|
try:
|
|
return self._update_dto(self.mido_api.get_port(id), kwargs)
|
|
except w_exc.HTTPNotFound:
|
|
raise MidonetResourceNotFound(resource_type='Port', id=id)
|
|
|
|
@handle_api_error
|
|
def add_router_port(self, router, **kwargs):
|
|
"""Add a new port to an existing router.
|
|
|
|
:param router: router to add a new port to
|
|
:param \**kwargs: configuration of the new port
|
|
:returns: newly created port
|
|
"""
|
|
return self._create_dto(self.mido_api.add_router_port(router), kwargs)
|
|
|
|
@handle_api_error
|
|
def create_router(self, **kwargs):
|
|
"""Create a new router
|
|
|
|
:param \**kwargs: configuration of the new router
|
|
:returns: newly created router
|
|
"""
|
|
LOG.debug(_("MidoClient.create_router called: "
|
|
"kwargs=%(kwargs)s"), {'kwargs': kwargs})
|
|
return self._create_dto(self.mido_api.add_router(), kwargs)
|
|
|
|
@handle_api_error
|
|
def delete_router(self, id):
|
|
"""Delete a router
|
|
|
|
:param id: id of the router
|
|
"""
|
|
LOG.debug(_("MidoClient.delete_router called: id=%(id)s"), {'id': id})
|
|
return self.mido_api.delete_router(id)
|
|
|
|
@handle_api_error
|
|
def get_router(self, id):
|
|
"""Get a router with the given id
|
|
|
|
:param id: id of the router
|
|
:returns: requested router object. None if it does not exist.
|
|
"""
|
|
LOG.debug(_("MidoClient.get_router called: id=%(id)s"), {'id': id})
|
|
try:
|
|
return self.mido_api.get_router(id)
|
|
except w_exc.HTTPNotFound:
|
|
raise MidonetResourceNotFound(resource_type='Router', id=id)
|
|
|
|
@handle_api_error
|
|
def update_router(self, id, **kwargs):
|
|
"""Update a router of the given id with the new name
|
|
|
|
:param id: id of the router
|
|
:param \**kwargs: the fields to update and their values
|
|
:returns: router object
|
|
"""
|
|
LOG.debug(_("MidoClient.update_router called: "
|
|
"id=%(id)s, kwargs=%(kwargs)s"),
|
|
{'id': id, 'kwargs': kwargs})
|
|
try:
|
|
return self._update_dto(self.mido_api.get_router(id), kwargs)
|
|
except w_exc.HTTPNotFound:
|
|
raise MidonetResourceNotFound(resource_type='Router', id=id)
|
|
|
|
@handle_api_error
|
|
def delete_route(self, id):
|
|
return self.mido_api.delete_route(id)
|
|
|
|
@handle_api_error
|
|
def add_dhcp_route_option(self, bridge, cidr, gw_ip, dst_ip):
|
|
"""Add Option121 route to subnet
|
|
|
|
:param bridge: Bridge to add the option route to
|
|
:param cidr: subnet represented as x.x.x.x/y
|
|
:param gw_ip: IP address of the next hop
|
|
:param dst_ip: IP address of the destination, in x.x.x.x/y format
|
|
"""
|
|
LOG.debug(_("MidoClient.add_dhcp_route_option called: "
|
|
"bridge=%(bridge)s, cidr=%(cidr)s, gw_ip=%(gw_ip)s"
|
|
"dst_ip=%(dst_ip)s"),
|
|
{"bridge": bridge, "cidr": cidr, "gw_ip": gw_ip,
|
|
"dst_ip": dst_ip})
|
|
subnet = bridge.get_dhcp_subnet(net_util.subnet_str(cidr))
|
|
if subnet is None:
|
|
raise MidonetApiException(
|
|
msg=_("Tried to access non-existent DHCP"))
|
|
prefix, length = dst_ip.split("/")
|
|
routes = [{'destinationPrefix': prefix, 'destinationLength': length,
|
|
'gatewayAddr': gw_ip}]
|
|
cur_routes = subnet.get_opt121_routes()
|
|
if cur_routes:
|
|
routes = routes + cur_routes
|
|
subnet.opt121_routes(routes).update()
|
|
|
|
@handle_api_error
|
|
def link(self, port, peer_id):
|
|
"""Link a port to a given peerId."""
|
|
self.mido_api.link(port, peer_id)
|
|
|
|
@handle_api_error
|
|
def delete_port_routes(self, routes, port_id):
|
|
"""Remove routes whose next hop port is the given port ID."""
|
|
for route in routes:
|
|
if route.get_next_hop_port() == port_id:
|
|
self.mido_api.delete_route(route.get_id())
|
|
|
|
@handle_api_error
|
|
def get_router_routes(self, router_id):
|
|
"""Get all routes for the given router."""
|
|
return self.mido_api.get_router_routes(router_id)
|
|
|
|
@handle_api_error
|
|
def unlink(self, port):
|
|
"""Unlink a port
|
|
|
|
:param port: port object
|
|
"""
|
|
LOG.debug(_("MidoClient.unlink called: port=%(port)s"),
|
|
{'port': port})
|
|
if port.get_peer_id():
|
|
self.mido_api.unlink(port)
|
|
else:
|
|
LOG.warn(_("Attempted to unlink a port that was not linked. %s"),
|
|
port.get_id())
|
|
|
|
@handle_api_error
|
|
def remove_rules_by_property(self, tenant_id, chain_name, key, value):
|
|
"""Remove all the rules that match the provided key and value."""
|
|
LOG.debug(_("MidoClient.remove_rules_by_property called: "
|
|
"tenant_id=%(tenant_id)s, chain_name=%(chain_name)s"
|
|
"key=%(key)s, value=%(value)s"),
|
|
{'tenant_id': tenant_id, 'chain_name': chain_name,
|
|
'key': key, 'value': value})
|
|
chain = self.get_chain_by_name(tenant_id, chain_name)
|
|
if chain is None:
|
|
raise MidonetResourceNotFound(resource_type='Chain',
|
|
id=chain_name)
|
|
|
|
for r in chain.get_rules():
|
|
if key in r.get_properties():
|
|
if r.get_properties()[key] == value:
|
|
self.mido_api.delete_rule(r.get_id())
|
|
|
|
@handle_api_error
|
|
def add_router_chains(self, router, inbound_chain_name,
|
|
outbound_chain_name):
|
|
"""Create chains for a new router.
|
|
|
|
Creates inbound and outbound chains for the router with the given
|
|
names, and the new chains are set on the router.
|
|
|
|
:param router: router to set chains for
|
|
:param inbound_chain_name: Name of the inbound chain
|
|
:param outbound_chain_name: Name of the outbound chain
|
|
"""
|
|
LOG.debug(_("MidoClient.create_router_chains called: "
|
|
"router=%(router)s, inbound_chain_name=%(in_chain)s, "
|
|
"outbound_chain_name=%(out_chain)s"),
|
|
{"router": router, "in_chain": inbound_chain_name,
|
|
"out_chain": outbound_chain_name})
|
|
tenant_id = router.get_tenant_id()
|
|
|
|
inbound_chain = self.mido_api.add_chain().tenant_id(tenant_id).name(
|
|
inbound_chain_name,).create()
|
|
outbound_chain = self.mido_api.add_chain().tenant_id(tenant_id).name(
|
|
outbound_chain_name).create()
|
|
|
|
# set chains to in/out filters
|
|
router.inbound_filter_id(inbound_chain.get_id()).outbound_filter_id(
|
|
outbound_chain.get_id()).update()
|
|
return inbound_chain, outbound_chain
|
|
|
|
@handle_api_error
|
|
def delete_router_chains(self, id):
|
|
"""Deletes chains of a router.
|
|
|
|
:param id: router ID to delete chains of
|
|
"""
|
|
LOG.debug(_("MidoClient.delete_router_chains called: "
|
|
"id=%(id)s"), {'id': id})
|
|
router = self.get_router(id)
|
|
if (router.get_inbound_filter_id()):
|
|
self.mido_api.delete_chain(router.get_inbound_filter_id())
|
|
|
|
if (router.get_outbound_filter_id()):
|
|
self.mido_api.delete_chain(router.get_outbound_filter_id())
|
|
|
|
@handle_api_error
|
|
def delete_port_chains(self, id):
|
|
"""Deletes chains of a port.
|
|
|
|
:param id: port ID to delete chains of
|
|
"""
|
|
LOG.debug(_("MidoClient.delete_port_chains called: "
|
|
"id=%(id)s"), {'id': id})
|
|
port = self.get_port(id)
|
|
if (port.get_inbound_filter_id()):
|
|
self.mido_api.delete_chain(port.get_inbound_filter_id())
|
|
|
|
if (port.get_outbound_filter_id()):
|
|
self.mido_api.delete_chain(port.get_outbound_filter_id())
|
|
|
|
@handle_api_error
|
|
def get_link_port(self, router, peer_router_id):
|
|
"""Setup a route on the router to the next hop router."""
|
|
LOG.debug(_("MidoClient.get_link_port called: "
|
|
"router=%(router)s, peer_router_id=%(peer_router_id)s"),
|
|
{'router': router, 'peer_router_id': peer_router_id})
|
|
# Find the port linked between the two routers
|
|
link_port = None
|
|
for p in router.get_peer_ports():
|
|
if p.get_device_id() == peer_router_id:
|
|
link_port = p
|
|
break
|
|
return link_port
|
|
|
|
@handle_api_error
|
|
def add_router_route(self, router, type='Normal',
|
|
src_network_addr=None, src_network_length=None,
|
|
dst_network_addr=None, dst_network_length=None,
|
|
next_hop_port=None, next_hop_gateway=None,
|
|
weight=100):
|
|
"""Setup a route on the router."""
|
|
return self.mido_api.add_router_route(
|
|
router, type=type, src_network_addr=src_network_addr,
|
|
src_network_length=src_network_length,
|
|
dst_network_addr=dst_network_addr,
|
|
dst_network_length=dst_network_length,
|
|
next_hop_port=next_hop_port, next_hop_gateway=next_hop_gateway,
|
|
weight=weight)
|
|
|
|
@handle_api_error
|
|
def add_static_nat(self, tenant_id, chain_name, from_ip, to_ip, port_id,
|
|
nat_type='dnat', **kwargs):
|
|
"""Add a static NAT entry
|
|
|
|
:param tenant_id: owner fo the chain to add a NAT to
|
|
:param chain_name: name of the chain to add a NAT to
|
|
:param from_ip: IP to translate from
|
|
:param from_ip: IP to translate from
|
|
:param to_ip: IP to translate to
|
|
:param port_id: port to match on
|
|
:param nat_type: 'dnat' or 'snat'
|
|
"""
|
|
LOG.debug(_("MidoClient.add_static_nat called: "
|
|
"tenant_id=%(tenant_id)s, chain_name=%(chain_name)s, "
|
|
"from_ip=%(from_ip)s, to_ip=%(to_ip)s, "
|
|
"port_id=%(port_id)s, nat_type=%(nat_type)s"),
|
|
{'tenant_id': tenant_id, 'chain_name': chain_name,
|
|
'from_ip': from_ip, 'to_ip': to_ip,
|
|
'portid': port_id, 'nat_type': nat_type})
|
|
if nat_type not in ['dnat', 'snat']:
|
|
raise ValueError(_("Invalid NAT type passed in %s") % nat_type)
|
|
|
|
chain = self.get_chain_by_name(tenant_id, chain_name)
|
|
nat_targets = []
|
|
nat_targets.append(
|
|
{'addressFrom': to_ip, 'addressTo': to_ip,
|
|
'portFrom': 0, 'portTo': 0})
|
|
|
|
rule = chain.add_rule().type(nat_type).flow_action('accept').position(
|
|
1).nat_targets(nat_targets).properties(kwargs)
|
|
|
|
if nat_type == 'dnat':
|
|
rule = rule.nw_dst_address(from_ip).nw_dst_length(32).in_ports(
|
|
[port_id])
|
|
else:
|
|
rule = rule.nw_src_address(from_ip).nw_src_length(32).out_ports(
|
|
[port_id])
|
|
|
|
return rule.create()
|
|
|
|
@handle_api_error
|
|
def add_dynamic_snat(self, tenant_id, pre_chain_name, post_chain_name,
|
|
snat_ip, port_id, **kwargs):
|
|
"""Add SNAT masquerading rule
|
|
|
|
MidoNet requires two rules on the router, one to do NAT to a range of
|
|
ports, and another to retrieve back the original IP in the return
|
|
flow.
|
|
"""
|
|
pre_chain = self.get_chain_by_name(tenant_id, pre_chain_name)
|
|
post_chain = self.get_chain_by_name(tenant_id, post_chain_name)
|
|
|
|
pre_chain.add_rule().nw_dst_address(snat_ip).nw_dst_length(
|
|
32).type('rev_snat').flow_action('accept').in_ports(
|
|
[port_id]).properties(kwargs).position(1).create()
|
|
|
|
nat_targets = []
|
|
nat_targets.append(
|
|
{'addressFrom': snat_ip, 'addressTo': snat_ip,
|
|
'portFrom': 1, 'portTo': 65535})
|
|
|
|
post_chain.add_rule().type('snat').flow_action(
|
|
'accept').nat_targets(nat_targets).out_ports(
|
|
[port_id]).properties(kwargs).position(1).create()
|
|
|
|
@handle_api_error
|
|
def remove_static_route(self, router, ip):
|
|
"""Remove static route for the IP
|
|
|
|
:param router: next hop router to remove the routes to
|
|
:param ip: IP address of the route to remove
|
|
"""
|
|
LOG.debug(_("MidoClient.remote_static_route called: "
|
|
"router=%(router)s, ip=%(ip)s"),
|
|
{'router': router, 'ip': ip})
|
|
for r in router.get_routes():
|
|
if (r.get_dst_network_addr() == ip and
|
|
r.get_dst_network_length() == 32):
|
|
self.mido_api.delete_route(r.get_id())
|
|
|
|
@handle_api_error
|
|
def update_port_chains(self, port, inbound_chain_id, outbound_chain_id):
|
|
"""Bind inbound and outbound chains to the port."""
|
|
LOG.debug(_("MidoClient.update_port_chains called: port=%(port)s"
|
|
"inbound_chain_id=%(inbound_chain_id)s, "
|
|
"outbound_chain_id=%(outbound_chain_id)s"),
|
|
{"port": port, "inbound_chain_id": inbound_chain_id,
|
|
"outbound_chain_id": outbound_chain_id})
|
|
port.inbound_filter_id(inbound_chain_id).outbound_filter_id(
|
|
outbound_chain_id).update()
|
|
|
|
@handle_api_error
|
|
def create_chain(self, tenant_id, name):
|
|
"""Create a new chain."""
|
|
LOG.debug(_("MidoClient.create_chain called: tenant_id=%(tenant_id)s "
|
|
" name=%(name)s"), {"tenant_id": tenant_id, "name": name})
|
|
return self.mido_api.add_chain().tenant_id(tenant_id).name(
|
|
name).create()
|
|
|
|
@handle_api_error
|
|
def delete_chain(self, id):
|
|
"""Delete chain matching the ID."""
|
|
LOG.debug(_("MidoClient.delete_chain called: id=%(id)s"), {"id": id})
|
|
self.mido_api.delete_chain(id)
|
|
|
|
@handle_api_error
|
|
def delete_chains_by_names(self, tenant_id, names):
|
|
"""Delete chains matching the names given for a tenant."""
|
|
LOG.debug(_("MidoClient.delete_chains_by_names called: "
|
|
"tenant_id=%(tenant_id)s names=%(names)s "),
|
|
{"tenant_id": tenant_id, "names": names})
|
|
chains = self.mido_api.get_chains({'tenant_id': tenant_id})
|
|
for c in chains:
|
|
if c.get_name() in names:
|
|
self.mido_api.delete_chain(c.get_id())
|
|
|
|
@handle_api_error
|
|
def get_chain_by_name(self, tenant_id, name):
|
|
"""Get the chain by its name."""
|
|
LOG.debug(_("MidoClient.get_chain_by_name called: "
|
|
"tenant_id=%(tenant_id)s name=%(name)s "),
|
|
{"tenant_id": tenant_id, "name": name})
|
|
for c in self.mido_api.get_chains({'tenant_id': tenant_id}):
|
|
if c.get_name() == name:
|
|
return c
|
|
return None
|
|
|
|
@handle_api_error
|
|
def get_port_group_by_name(self, tenant_id, name):
|
|
"""Get the port group by name."""
|
|
LOG.debug(_("MidoClient.get_port_group_by_name called: "
|
|
"tenant_id=%(tenant_id)s name=%(name)s "),
|
|
{"tenant_id": tenant_id, "name": name})
|
|
for p in self.mido_api.get_port_groups({'tenant_id': tenant_id}):
|
|
if p.get_name() == name:
|
|
return p
|
|
return None
|
|
|
|
@handle_api_error
|
|
def create_port_group(self, tenant_id, name):
|
|
"""Create a port group
|
|
|
|
Create a new port group for a given name and ID.
|
|
"""
|
|
LOG.debug(_("MidoClient.create_port_group called: "
|
|
"tenant_id=%(tenant_id)s name=%(name)s"),
|
|
{"tenant_id": tenant_id, "name": name})
|
|
return self.mido_api.add_port_group().tenant_id(tenant_id).name(
|
|
name).create()
|
|
|
|
@handle_api_error
|
|
def delete_port_group_by_name(self, tenant_id, name):
|
|
"""Delete port group matching the name given for a tenant."""
|
|
LOG.debug(_("MidoClient.delete_port_group_by_name called: "
|
|
"tenant_id=%(tenant_id)s name=%(name)s "),
|
|
{"tenant_id": tenant_id, "name": name})
|
|
pgs = self.mido_api.get_port_groups({'tenant_id': tenant_id})
|
|
for pg in pgs:
|
|
if pg.get_name() == name:
|
|
LOG.debug(_("Deleting pg %(id)s"), {"id": pg.get_id()})
|
|
self.mido_api.delete_port_group(pg.get_id())
|
|
|
|
@handle_api_error
|
|
def add_port_to_port_group_by_name(self, tenant_id, name, port_id):
|
|
"""Add a port to a port group with the given name."""
|
|
LOG.debug(_("MidoClient.add_port_to_port_group_by_name called: "
|
|
"tenant_id=%(tenant_id)s name=%(name)s "
|
|
"port_id=%(port_id)s"),
|
|
{"tenant_id": tenant_id, "name": name, "port_id": port_id})
|
|
pg = self.get_port_group_by_name(tenant_id, name)
|
|
if pg is None:
|
|
raise MidonetResourceNotFound(resource_type='PortGroup', id=name)
|
|
|
|
pg = pg.add_port_group_port().port_id(port_id).create()
|
|
return pg
|
|
|
|
@handle_api_error
|
|
def remove_port_from_port_groups(self, port_id):
|
|
"""Remove a port binding from all the port groups."""
|
|
LOG.debug(_("MidoClient.remove_port_from_port_groups called: "
|
|
"port_id=%(port_id)s"), {"port_id": port_id})
|
|
port = self.get_port(port_id)
|
|
for pg in port.get_port_groups():
|
|
pg.delete()
|
|
|
|
@handle_api_error
|
|
def add_chain_rule(self, chain, action='accept', **kwargs):
|
|
"""Create a new accept chain rule."""
|
|
self.mido_api.add_chain_rule(chain, action, **kwargs)
|