# @author: Ryu Ishimoto, Midokura Japan KK
+from webob import exc as w_exc
+
+from quantum.common import exceptions as q_exc
from quantum.openstack.common import log as logging
LOG = logging.getLogger(__name__)
PREFIX = 'OS_SG_'
-SUFFIX_IN = '_IN'
-SUFFIX_OUT = '_OUT'
+NAME_IDENTIFIABLE_PREFIX_LEN = len(PREFIX) + 36 # 36 = length of uuid
+OS_FLOATING_IP_RULE_KEY = 'OS_FLOATING_IP'
OS_ROUTER_IN_CHAIN_NAME_FORMAT = 'OS_ROUTER_IN_%s'
OS_ROUTER_OUT_CHAIN_NAME_FORMAT = 'OS_ROUTER_OUT_%s'
-NAME_IDENTIFIABLE_PREFIX_LEN = len(PREFIX) + 36 # 36 = length of uuid
+OS_SG_KEY = 'os_sg_rule_id'
+OS_TENANT_ROUTER_RULE_KEY = 'OS_TENANT_ROUTER_RULE'
+SNAT_RULE = 'SNAT'
+SNAT_RULE_PROPERTY = {OS_TENANT_ROUTER_RULE_KEY: SNAT_RULE}
+SUFFIX_IN = '_IN'
+SUFFIX_OUT = '_OUT'
def sg_label(sg_id, sg_name):
"""Construct the security group ID used as chain identifier in MidoNet."""
return PREFIX + str(sg_id) + '_' + sg_name
+
+def sg_rule_properties(os_sg_rule_id):
+ return {OS_SG_KEY: str(os_sg_rule_id)}
+
port_group_name = sg_label
return {'in': in_chain_name, 'out': out_chain_name}
-class ChainManager:
+def router_chain_names(router_id):
+ in_name = OS_ROUTER_IN_CHAIN_NAME_FORMAT % router_id
+ out_name = OS_ROUTER_OUT_CHAIN_NAME_FORMAT % router_id
+ return {'in': in_name, 'out': out_name}
+
+
+def handle_api_error(fn):
+ def wrapped(*args, **kwargs):
+ try:
+ return fn(*args, **kwargs)
+ except w_exc.HTTPException as ex:
+ raise MidonetApiException(msg=ex)
+ return wrapped
+
+
+class MidonetResourceNotFound(q_exc.NotFound):
+ message = _('MidoNet %(resource_type)s %(id)s could not be found')
+
+
+class MidonetApiException(q_exc.QuantumException):
+ message = _("MidoNet API error: %(msg)s")
+
+
+class MidoClient:
def __init__(self, mido_api):
self.mido_api = mido_api
- def create_for_sg(self, tenant_id, sg_id, sg_name):
- """Create a new chain for security group.
+ @handle_api_error
+ def create_bridge(self, tenant_id, name):
+ """Create a new bridge
- Creating a security group creates a pair of chains in MidoNet, one for
- inbound and the other for outbound.
+ :param tenant_id: id of tenant creating the bridge
+ :param name: name of the bridge
+ :returns: newly created bridge
"""
- LOG.debug(_("ChainManager.create_for_sg called: "
- "tenant_id=%(tenant_id)s sg_id=%(sg_id)s "
- "sg_name=%(sg_name)s "),
- {'tenant_id': tenant_id, 'sg_id': sg_id, 'sg_name': sg_name})
+ LOG.debug(_("MidoClient.create_bridge called: "
+ "tenant_id=%(tenant_id)s, name=%(name)s"),
+ {'tenant_id': tenant_id, 'name': name})
+ return self.mido_api.add_bridge().name(name).tenant_id(
+ tenant_id).create()
- cnames = chain_names(sg_id, sg_name)
- self.mido_api.add_chain().tenant_id(tenant_id).name(
- cnames['in']).create()
- self.mido_api.add_chain().tenant_id(tenant_id).name(
- cnames['out']).create()
+ @handle_api_error
+ def delete_bridge(self, id):
+ """Delete a bridge
- def delete_for_sg(self, tenant_id, sg_id, sg_name):
- """Delete a chain mapped to a security group.
+ :param id: id of the bridge
+ """
+ LOG.debug(_("MidoClient.delete_bridge called: id=%(id)s"), {'id': id})
+ return self.mido_api.delete_bridge(id)
- Delete a SG means deleting all the chains (inbound and outbound)
- associated with the SG in MidoNet.
+ @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(_("ChainManager.delete_for_sg called: "
- "tenant_id=%(tenant_id)s sg_id=%(sg_id)s "
- "sg_name=%(sg_name)s "),
- {'tenant_id': tenant_id, 'sg_id': sg_id, 'sg_name': sg_name})
+ 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, name):
+ """Update a bridge of the given id with the new name
+
+ :param id: id of the bridge
+ :param name: name of the bridge to set to
+ :returns: bridge object
+ """
+ LOG.debug(_("MidoClient.update_bridge called: "
+ "id=%(id)s, name=%(name)s"), {'id': id, 'name': name})
+ try:
+ return self.mido_api.get_bridge(id).name(name).update()
+ except w_exc.HTTPNotFound:
+ raise MidonetResourceNotFound(resource_type='Bridge', id=id)
+
+ @handle_api_error
+ def create_dhcp(self, bridge, gateway_ip, net_addr, net_len):
+ """Create a new DHCP entry
+
+ :param bridge: bridge object to add dhcp to
+ :param gateway_ip: IP address of gateway
+ :param net_addr: network IP address
+ :param net_len: network IP address length
+ :returns: newly created dhcp
+ """
+ LOG.debug(_("MidoClient.create_dhcp called: bridge=%s(bridge)s, "
+ "net_addr=%(net_addr)s, net_len=%(net_len)s, "
+ "gateway_ip=%(gateway_ip)s"),
+ {'bridge': bridge, 'net_addr': net_addr, 'net_len': net_len,
+ 'gateway_ip': gateway_ip})
+ return bridge.add_dhcp_subnet().default_gateway(
+ gateway_ip).subnet_prefix(net_addr).subnet_length(
+ net_len).create()
+
+ @handle_api_error
+ def create_dhcp_hosts(self, bridge, ip, mac):
+ """Create DHCP host entries
+
+ :param bridge: bridge of the DHCP
+ :param ip: IP address
+ :param mac: MAC address
+ """
+ LOG.debug(_("MidoClient.create_dhcp_hosts called: bridge=%s(bridge), "
+ "ip=%(ip)s, mac=%(mac)s"), {'bridge': bridge, 'ip': ip,
+ 'mac': mac})
+ dhcp_subnets = bridge.get_dhcp_subnets()
+ if dhcp_subnets:
+ # Add the host to the first subnet as we currently support one
+ # subnet per network.
+ dhcp_subnets[0].add_dhcp_host().ip_addr(ip).mac_addr(mac).create()
+
+ @handle_api_error
+ def delete_dhcp_hosts(self, bridge_id, ip, mac):
+ """Delete DHCP host entries
+
+ :param bridge_id: id of the bridge of the DHCP
+ :param ip: IP address
+ :param mac: MAC address
+ """
+ LOG.debug(_("MidoClient.delete_dhcp_hosts called: "
+ "bridge_id=%s(bridge_id), ip=%(ip)s, mac=%(mac)s"),
+ {'bridge_id': bridge_id, 'ip': ip, 'mac': mac})
+ bridge = self.get_bridge(bridge_id)
+ dhcp_subnets = bridge.get_dhcp_subnets()
+ if dhcp_subnets:
+ for dh in dhcp_subnets[0].get_dhcp_hosts():
+ if dh.get_mac_addr() == mac and dh.get_ip_addr() == ip:
+ dh.delete()
+
+ @handle_api_error
+ def delete_dhcp(self, bridge):
+ """Delete a DHCP entry
+
+ :param bridge: bridge to remove DHCP from
+ """
+ LOG.debug(_("MidoClient.delete_dhcp called: bridge=%s(bridge), "),
+ {'bridge': bridge})
+ dhcp = bridge.get_dhcp_subnets()
+ if not dhcp:
+ raise MidonetApiException(msg="Tried to delete non-existent DHCP")
+ dhcp[0].delete()
+
+ @handle_api_error
+ def delete_port(self, id):
+ """Delete a port
+
+ :param id: id of the port
+ """
+ LOG.debug(_("MidoClient.delete_port called: id=%(id)s"), {'id': id})
+ self.mido_api.delete_port(id)
- cnames = chain_names(sg_id, sg_name)
- chains = self.mido_api.get_chains({'tenant_id': tenant_id})
- for c in chains:
- if c.get_name() == cnames['in'] or c.get_name() == cnames['out']:
- LOG.debug(_('ChainManager.delete_for_sg: deleting chain=%r'),
- c)
- c.delete()
+ @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 create_exterior_bridge_port(self, bridge):
+ """Create a new exterior bridge port
+
+ :param bridge: bridge object to add port to
+ :returns: newly created port
+ """
+ LOG.debug(_("MidoClient.create_exterior_bridge_port called: "
+ "bridge=%(bridge)s"), {'bridge': bridge})
+ return bridge.add_exterior_port().create()
+
+ @handle_api_error
+ def create_interior_bridge_port(self, bridge):
+ """Create a new interior bridge port
+
+ :param bridge: bridge object to add port to
+ :returns: newly created port
+ """
+ LOG.debug(_("MidoClient.create_interior_bridge_port called: "
+ "bridge=%(bridge)s"), {'bridge': bridge})
+ return bridge.add_interior_port().create()
+
+ @handle_api_error
+ def create_router(self, tenant_id, name):
+ """Create a new router
+
+ :param tenant_id: id of tenant creating the router
+ :param name: name of the router
+ :returns: newly created router
+ """
+ LOG.debug(_("MidoClient.create_router called: "
+ "tenant_id=%(tenant_id)s, name=%(name)s"),
+ {'tenant_id': tenant_id, 'name': name})
+ return self.mido_api.add_router().name(name).tenant_id(
+ tenant_id).create()
+
+ @handle_api_error
+ def create_tenant_router(self, tenant_id, name, metadata_router):
+ """Create a new tenant router
+
+ :param tenant_id: id of tenant creating the router
+ :param name: name of the router
+ :param metadata_router: metadata router
+ :returns: newly created router
+ """
+ LOG.debug(_("MidoClient.create_tenant_router called: "
+ "tenant_id=%(tenant_id)s, name=%(name)s"
+ "metadata_router=%(metadata_router)s"),
+ {'tenant_id': tenant_id, 'name': name,
+ 'metadata_router': metadata_router})
+ router = self.create_router(tenant_id, name)
+ self.link_router_to_metadata_router(router, metadata_router)
+ return router
+
+ @handle_api_error
+ def delete_tenant_router(self, id, metadata_router):
+ """Delete a tenant router
+
+ :param id: id of router
+ :param metadata_router: metadata router
+ """
+ LOG.debug(_("MidoClient.delete_tenant_router called: "
+ "id=%(id)s, metadata_router=%(metadata_router)s"),
+ {'id': id, 'metadata_router': metadata_router})
+ self.unlink_router_from_metadata_router(id, metadata_router)
+ self.destroy_router_chains(id)
+
+ # delete the router
+ self.delete_router(id)
+
+ @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, name):
+ """Update a router of the given id with the new name
+
+ :param id: id of the router
+ :param name: name of the router to set to
+ :returns: router object
+ """
+ LOG.debug(_("MidoClient.update_router called: "
+ "id=%(id)s, name=%(name)s"), {'id': id, 'name': name})
+ try:
+ return self.mido_api.get_router(id).name(name).update()
+ except w_exc.HTTPNotFound:
+ raise MidonetResourceNotFound(resource_type='Router', id=id)
+
+ @handle_api_error
+ def link_bridge_port_to_router(self, port_id, router_id, gateway_ip,
+ net_addr, net_len, metadata_router):
+ """Link a tenant bridge port to the router
+
+ :param port_id: port ID
+ :param router_id: router id to link to
+ :param gateway_ip: IP address of gateway
+ :param net_addr: network IP address
+ :param net_len: network IP address length
+ :param metadata_router: metadata router instance
+ """
+ LOG.debug(_("MidoClient.link_bridge_port_to_router called: "
+ "port_id=%(port_id)s, router_id=%(router_id)s, "
+ "gateway_ip=%(gateway_ip)s net_addr=%(net_addr)s, "
+ "net_len=%(net_len)s, "
+ "metadata_router=%(metadata_router)s"),
+ {'port_id': port_id, 'router_id': router_id,
+ 'gateway_ip': gateway_ip, 'net_addr': net_addr,
+ 'net_len': net_len, 'metadata_router': metadata_router})
+ router = self.get_router(router_id)
+
+ # create an interior port on the router
+ in_port = router.add_interior_port()
+ router_port = in_port.port_address(gateway_ip).network_address(
+ net_addr).network_length(net_len).create()
+
+ br_port = self.get_port(port_id)
+ router_port.link(br_port.get_id())
+
+ # add a route for the subnet in the provider router
+ router.add_route().type('Normal').src_network_addr(
+ '0.0.0.0').src_network_length(0).dst_network_addr(
+ net_addr).dst_network_length(net_len).weight(
+ 100).next_hop_port(router_port.get_id()).create()
+
+ # add a route for the subnet in metadata router; forward
+ # packets destined to the subnet to the tenant router
+ for pp in metadata_router.get_peer_ports():
+ if pp.get_device_id() == router.get_id():
+ mdr_port_id = pp.get_peer_id()
+ break
+ else:
+ raise Exception(
+ _("Couldn't find a md router port for the router=%r"), router)
+
+ metadata_router.add_route().type('Normal').src_network_addr(
+ '0.0.0.0').src_network_length(0).dst_network_addr(
+ net_addr).dst_network_length(net_len).weight(
+ 100).next_hop_port(mdr_port_id).create()
+
+ @handle_api_error
+ def unlink_bridge_port_from_router(self, port_id, net_addr, net_len,
+ metadata_router):
+ """Unlink a tenant bridge port from the router
+
+ :param bridge_id: bridge ID
+ :param net_addr: network IP address
+ :param net_len: network IP address length
+ :param metadata_router: metadata router instance
+ """
+ LOG.debug(_("MidoClient.unlink_bridge_port_from_router called: "
+ "port_id=%(port_id)s, net_addr=%(net_addr)s, "
+ "net_len=%(net_len)s, "
+ "metadata_router=%(metadata_router)s"),
+ {'port_id': port_id, 'net_addr': net_addr,
+ 'net_len': net_len, 'metadata_router': metadata_router})
+ port = self.get_port(port_id)
+ port.unlink()
+ self.delete_port(port.get_peer_id())
+ self.delete_port(port.get_id())
+
+ # delete the route for the subnet in the metadata router
+ for r in metadata_router.get_routes():
+ if (r.get_dst_network_addr() == net_addr and
+ r.get_dst_network_length() == net_len):
+ LOG.debug(_('Deleting route=%r ...'), r)
+ self.mido_api.delete_route(r.get_id())
+ break
+
+ @handle_api_error
+ def link_bridge_to_provider_router(self, bridge, provider_router,
+ gateway_ip, net_addr, net_len):
+ """Link a tenant bridge to the provider router
+
+ :param bridge: tenant bridge
+ :param provider_router: provider router to link to
+ :param gateway_ip: IP address of gateway
+ :param net_addr: network IP address
+ :param net_len: network IP address length
+ """
+ LOG.debug(_("MidoClient.link_bridge_to_provider_router called: "
+ "bridge=%(bridge)s, provider_router=%(provider_router)s, "
+ "gateway_ip=%(gateway_ip)s, net_addr=%(net_addr)s, "
+ "net_len=%(net_len)s"),
+ {'bridge': bridge, 'provider_router': provider_router,
+ 'gateway_ip': gateway_ip, 'net_addr': net_addr,
+ 'net_len': net_len})
+ # create an interior port on the provider router
+ in_port = provider_router.add_interior_port()
+ pr_port = in_port.port_address(gateway_ip).network_address(
+ net_addr).network_length(net_len).create()
+
+ # create an interior bridge port, then link it to the router.
+ br_port = bridge.add_interior_port().create()
+ pr_port.link(br_port.get_id())
+
+ # add a route for the subnet in the provider router
+ provider_router.add_route().type('Normal').src_network_addr(
+ '0.0.0.0').src_network_length(0).dst_network_addr(
+ net_addr).dst_network_length(net_len).weight(
+ 100).next_hop_port(pr_port.get_id()).create()
+
+ @handle_api_error
+ def unlink_bridge_from_provider_router(self, bridge, provider_router):
+ """Unlink a tenant bridge from the provider router
+
+ :param bridge: tenant bridge
+ :param provider_router: provider router to link to
+ """
+ LOG.debug(_("MidoClient.unlink_bridge_from_provider_router called: "
+ "bridge=%(bridge)s, provider_router=%(provider_router)s"),
+ {'bridge': bridge, 'provider_router': provider_router})
+ # Delete routes and unlink the router and the bridge.
+ routes = provider_router.get_routes()
+
+ bridge_ports_to_delete = [
+ p for p in provider_router.get_peer_ports()
+ if p.get_device_id() == bridge.get_id()]
+
+ for p in bridge.get_peer_ports():
+ if p.get_device_id() == provider_router.get_id():
+ # delete the routes going to the bridge
+ for r in routes:
+ if r.get_next_hop_port() == p.get_id():
+ self.mido_api.delete_route(r.get_id())
+ p.unlink()
+ self.mido_api.delete_port(p.get_id())
+
+ # delete bridge port
+ for port in bridge_ports_to_delete:
+ self.mido_api.delete_port(port.get_id())
+
+ @handle_api_error
+ def set_router_external_gateway(self, id, provider_router, snat_ip):
+ """Set router external gateway
+
+ :param ID: ID of the tenant router
+ :param provider_router: provider router
+ :param snat_ip: SNAT IP address
+ """
+ LOG.debug(_("MidoClient.set_router_external_gateway called: "
+ "id=%(id)s, provider_router=%(provider_router)s, "
+ "snat_ip=%s(snat_ip)s)"),
+ {'id': id, 'provider_router': provider_router,
+ 'snat_ip': snat_ip})
+ tenant_router = self.get_router(id)
+
+ # Create a interior port in the provider router
+ in_port = provider_router.add_interior_port()
+ pr_port = in_port.network_address(
+ '169.254.255.0').network_length(30).port_address(
+ '169.254.255.1').create()
+
+ # Create a port in the tenant router
+ tr_port = tenant_router.add_interior_port().network_address(
+ '169.254.255.0').network_length(30).port_address(
+ '169.254.255.2').create()
+
+ # Link them
+ pr_port.link(tr_port.get_id())
+
+ # Add a route for snat_ip to bring it down to tenant
+ provider_router.add_route().type(
+ 'Normal').src_network_addr('0.0.0.0').src_network_length(
+ 0).dst_network_addr(snat_ip).dst_network_length(
+ 32).weight(100).next_hop_port(
+ pr_port.get_id()).create()
+
+ # Add default route to uplink in the tenant router
+ tenant_router.add_route().type('Normal').src_network_addr(
+ '0.0.0.0').src_network_length(0).dst_network_addr(
+ '0.0.0.0').dst_network_length(0).weight(
+ 100).next_hop_port(tr_port.get_id()).create()
+
+ # ADD SNAT(masquerade) rules
+ chains = self.get_router_chains(
+ tenant_router.get_tenant_id(), tenant_router.get_id())
+
+ chains['in'].add_rule().nw_dst_address(snat_ip).nw_dst_length(
+ 32).type('rev_snat').flow_action('accept').in_ports(
+ [tr_port.get_id()]).properties(
+ SNAT_RULE_PROPERTY).position(1).create()
+
+ nat_targets = []
+ nat_targets.append(
+ {'addressFrom': snat_ip, 'addressTo': snat_ip,
+ 'portFrom': 1, 'portTo': 65535})
+
+ chains['out'].add_rule().type('snat').flow_action(
+ 'accept').nat_targets(nat_targets).out_ports(
+ [tr_port.get_id()]).properties(
+ SNAT_RULE_PROPERTY).position(1).create()
+
+ @handle_api_error
+ def clear_router_external_gateway(self, id):
+ """Clear router external gateway
+
+ :param ID: ID of the tenant router
+ """
+ LOG.debug(_("MidoClient.clear_router_external_gateway called: "
+ "id=%(id)s"), {'id': id})
+ tenant_router = self.get_router(id)
+
+ # delete the port that is connected to provider router
+ for p in tenant_router.get_ports():
+ if p.get_port_address() == '169.254.255.2':
+ peer_port_id = p.get_peer_id()
+ p.unlink()
+ self.mido_api.delete_port(peer_port_id)
+ self.mido_api.delete_port(p.get_id())
+
+ # delete default route
+ for r in tenant_router.get_routes():
+ if (r.get_dst_network_addr() == '0.0.0.0' and
+ r.get_dst_network_length() == 0):
+ self.mido_api.delete_route(r.get_id())
+
+ # delete SNAT(masquerade) rules
+ chains = self.get_router_chains(
+ tenant_router.get_tenant_id(),
+ tenant_router.get_id())
+
+ for r in chains['in'].get_rules():
+ if OS_TENANT_ROUTER_RULE_KEY in r.get_properties():
+ if r.get_properties()[
+ OS_TENANT_ROUTER_RULE_KEY] == SNAT_RULE:
+ self.mido_api.delete_rule(r.get_id())
+
+ for r in chains['out'].get_rules():
+ if OS_TENANT_ROUTER_RULE_KEY in r.get_properties():
+ if r.get_properties()[
+ OS_TENANT_ROUTER_RULE_KEY] == SNAT_RULE:
+ self.mido_api.delete_rule(r.get_id())
+
+ @handle_api_error
def get_router_chains(self, tenant_id, router_id):
"""Get router chains.
and 'out' respectively, given the tenant_id and the router_id passed
in in the arguments.
"""
- LOG.debug(_("ChainManager.get_router_chains called: "
+ LOG.debug(_("MidoClient.get_router_chains called: "
"tenant_id=%(tenant_id)s router_id=%(router_id)s"),
{'tenant_id': tenant_id, 'router_id': router_id})
- router_chain_names = self._get_router_chain_names(router_id)
+ chain_names = router_chain_names(router_id)
chains = {}
for c in self.mido_api.get_chains({'tenant_id': tenant_id}):
- if c.get_name() == router_chain_names['in']:
+ if c.get_name() == chain_names['in']:
chains['in'] = c
- elif c.get_name() == router_chain_names['out']:
+ elif c.get_name() == chain_names['out']:
chains['out'] = c
return chains
- def create_router_chains(self, tenant_id, router_id):
- """Create a new chain on a router.
+ @handle_api_error
+ def create_router_chains(self, router):
+ """Create chains for a new router.
Creates chains for the router and returns the same dictionary as
get_router_chains() returns.
- """
- LOG.debug(_("ChainManager.create_router_chains called: "
- "tenant_id=%(tenant_id)s router_id=%(router_id)s"),
- {'tenant_id': tenant_id, 'router_id': router_id})
+ :param router: router to set chains for
+ """
+ LOG.debug(_("MidoClient.create_router_chains called: "
+ "router=%(router)s"), {'router': router})
chains = {}
- router_chain_names = self._get_router_chain_names(router_id)
+ router_id = router.get_id()
+ tenant_id = router.get_tenant_id()
+ chain_names = router_chain_names(router_id)
chains['in'] = self.mido_api.add_chain().tenant_id(tenant_id).name(
- router_chain_names['in']).create()
+ chain_names['in']).create()
chains['out'] = self.mido_api.add_chain().tenant_id(tenant_id).name(
- router_chain_names['out']).create()
+ chain_names['out']).create()
+
+ # set chains to in/out filters
+ router.inbound_filter_id(
+ chains['in'].get_id()).outbound_filter_id(
+ chains['out'].get_id()).update()
return chains
+ @handle_api_error
+ def destroy_router_chains(self, id):
+ """Deletes chains of a router.
+
+ :param id: router ID to delete chains of
+ """
+ LOG.debug(_("MidoClient.destroy_router_chains called: "
+ "id=%(id)s"), {'id': id})
+ # delete corresponding chains
+ router = self.get_router(id)
+ chains = self.get_router_chains(router.get_tenant_id(), id)
+ self.mido_api.delete_chain(chains['in'].get_id())
+ self.mido_api.delete_chain(chains['out'].get_id())
+
+ @handle_api_error
+ def link_router_to_metadata_router(self, router, metadata_router):
+ """Link a router to the metadata router
+
+ :param router: router to link
+ :param metadata_router: metadata router
+ """
+ LOG.debug(_("MidoClient.link_router_to_metadata_router called: "
+ "router=%(router)s, metadata_router=%(metadata_router)s"),
+ {'router': router, 'metadata_router': metadata_router})
+ # link to metadata router
+ in_port = metadata_router.add_interior_port()
+ mdr_port = in_port.network_address('169.254.255.0').network_length(
+ 30).port_address('169.254.255.1').create()
+
+ tr_port = router.add_interior_port().network_address(
+ '169.254.255.0').network_length(30).port_address(
+ '169.254.255.2').create()
+ mdr_port.link(tr_port.get_id())
+
+ # forward metadata traffic to metadata router
+ router.add_route().type('Normal').src_network_addr(
+ '0.0.0.0').src_network_length(0).dst_network_addr(
+ '169.254.169.254').dst_network_length(32).weight(
+ 100).next_hop_port(tr_port.get_id()).create()
+
+ @handle_api_error
+ def unlink_router_from_metadata_router(self, id, metadata_router):
+ """Unlink a router from the metadata router
+
+ :param id: ID of router
+ :param metadata_router: metadata router
+ """
+ LOG.debug(_("MidoClient.unlink_router_from_metadata_router called: "
+ "id=%(id)s, metadata_router=%(metadata_router)s"),
+ {'id': id, 'metadata_router': metadata_router})
+ # unlink from metadata router and delete the interior ports
+ # that connect metadata router and this router.
+ for pp in metadata_router.get_peer_ports():
+ if pp.get_device_id() == id:
+ mdr_port = self.get_port(pp.get_peer_id())
+ pp.unlink()
+ self.mido_api.delete_port(pp.get_id())
+ self.mido_api.delete_port(mdr_port.get_id())
+
+ @handle_api_error
+ def setup_floating_ip(self, router_id, provider_router, floating_ip,
+ fixed_ip, identifier):
+ """Setup MidoNet for floating IP
+
+ :param router_id: router_id
+ :param provider_router: provider router
+ :param floating_ip: floating IP address
+ :param fixed_ip: fixed IP address
+ :param identifier: identifier to use to map to MidoNet
+ """
+ LOG.debug(_("MidoClient.setup_floating_ip called: "
+ "router_id=%(router_id)s, "
+ "provider_router=%(provider_router)s"
+ "floating_ip=%(floating_ip)s, fixed_ip=%(fixed_ip)s"
+ "identifier=%(identifier)s"),
+ {'router_id': router_id, 'provider_router': provider_router,
+ 'floating_ip': floating_ip, 'fixed_ip': fixed_ip,
+ 'identifier': identifier})
+ # unlink from metadata router and delete the interior ports
+ router = self.mido_api.get_router(router_id)
+ # find the provider router port that is connected to the tenant
+ # of the floating ip
+ for p in router.get_peer_ports():
+ if p.get_device_id() == provider_router.get_id():
+ pr_port = p
+
+ # get the tenant router port id connected to provider router
+ tr_port_id = pr_port.get_peer_id()
+
+ # add a route for the floating ip to bring it to the tenant
+ provider_router.add_route().type(
+ 'Normal').src_network_addr('0.0.0.0').src_network_length(
+ 0).dst_network_addr(
+ floating_ip).dst_network_length(
+ 32).weight(100).next_hop_port(
+ pr_port.get_id()).create()
+
+ chains = self.get_router_chains(router.get_tenant_id(), router_id)
+
+ # add dnat/snat rule pair for the floating ip
+ nat_targets = []
+ nat_targets.append(
+ {'addressFrom': fixed_ip, 'addressTo': fixed_ip,
+ 'portFrom': 0, 'portTo': 0})
+
+ floating_property = {OS_FLOATING_IP_RULE_KEY: identifier}
+ chains['in'].add_rule().nw_dst_address(
+ floating_ip).nw_dst_length(32).type(
+ 'dnat').flow_action('accept').nat_targets(
+ nat_targets).in_ports([tr_port_id]).position(
+ 1).properties(floating_property).create()
+
+ nat_targets = []
+ nat_targets.append(
+ {'addressFrom': floating_ip, 'addressTo': floating_ip,
+ 'portFrom': 0, 'portTo': 0})
+
+ chains['out'].add_rule().nw_src_address(
+ fixed_ip).nw_src_length(32).type(
+ 'snat').flow_action('accept').nat_targets(
+ nat_targets).out_ports(
+ [tr_port_id]).position(1).properties(
+ floating_property).create()
+
+ @handle_api_error
+ def clear_floating_ip(self, router_id, provider_router, floating_ip,
+ identifier):
+ """Remove floating IP
+
+ :param router_id: router_id
+ :param provider_router: provider router
+ :param floating_ip: floating IP address
+ :param identifier: identifier to use to map to MidoNet
+ """
+ LOG.debug(_("MidoClient.clear_floating_ip called: "
+ "router_id=%(router_id)s, "
+ "provider_router=%(provider_router)s"
+ "floating_ip=%(floating_ip)s, identifier=%(identifier)s"),
+ {'router_id': router_id, 'provider_router': provider_router,
+ 'floating_ip': floating_ip, 'identifier': identifier})
+ router = self.mido_api.get_router(router_id)
+
+ # find the provider router port that is connected to the tenant
+ # delete the route for this floating ip
+ for r in provider_router.get_routes():
+ if (r.get_dst_network_addr() == floating_ip and
+ r.get_dst_network_length() == 32):
+ self.mido_api.delete_route(r.get_id())
+
+ # delete snat/dnat rule pair for this floating ip
+ chains = self.get_router_chains(router.get_tenant_id(), router_id)
+
+ for r in chains['in'].get_rules():
+ if OS_FLOATING_IP_RULE_KEY in r.get_properties():
+ if r.get_properties()[OS_FLOATING_IP_RULE_KEY] == identifier:
+ LOG.debug(_('deleting rule=%r'), r)
+ self.mido_api.delete_rule(r.get_id())
+ break
+
+ for r in chains['out'].get_rules():
+ if OS_FLOATING_IP_RULE_KEY in r.get_properties():
+ if r.get_properties()[OS_FLOATING_IP_RULE_KEY] == identifier:
+ LOG.debug(_('deleting rule=%r'), r)
+ self.mido_api.delete_rule(r.get_id())
+ break
+
+ @handle_api_error
+ def create_for_sg(self, tenant_id, sg_id, sg_name):
+ """Create a new chain for security group.
+
+ Creating a security group creates a pair of chains in MidoNet, one for
+ inbound and the other for outbound.
+ """
+ LOG.debug(_("MidoClient.create_for_sg called: "
+ "tenant_id=%(tenant_id)s sg_id=%(sg_id)s "
+ "sg_name=%(sg_name)s "),
+ {'tenant_id': tenant_id, 'sg_id': sg_id, 'sg_name': sg_name})
+
+ cnames = chain_names(sg_id, sg_name)
+ self.mido_api.add_chain().tenant_id(tenant_id).name(
+ cnames['in']).create()
+ self.mido_api.add_chain().tenant_id(tenant_id).name(
+ cnames['out']).create()
+
+ pg_name = port_group_name(sg_id, sg_name)
+ self.mido_api.add_port_group().tenant_id(tenant_id).name(
+ pg_name).create()
+
+ @handle_api_error
+ def delete_for_sg(self, tenant_id, sg_id, sg_name):
+ """Delete a chain mapped to a security group.
+
+ Delete a SG means deleting all the chains (inbound and outbound)
+ associated with the SG in MidoNet.
+ """
+ LOG.debug(_("MidoClient.delete_for_sg called: "
+ "tenant_id=%(tenant_id)s sg_id=%(sg_id)s "
+ "sg_name=%(sg_name)s "),
+ {'tenant_id': tenant_id, 'sg_id': sg_id, 'sg_name': sg_name})
+
+ cnames = chain_names(sg_id, sg_name)
+ chains = self.mido_api.get_chains({'tenant_id': tenant_id})
+ for c in chains:
+ if c.get_name() == cnames['in'] or c.get_name() == cnames['out']:
+ LOG.debug(_('MidoClient.delete_for_sg: deleting chain=%r'),
+ c.get_id())
+ self.mido_api.delete_chain(c.get_id())
+
+ pg_name = port_group_name(sg_id, sg_name)
+ pgs = self.mido_api.get_port_groups({'tenant_id': tenant_id})
+ for pg in pgs:
+ if pg.get_name() == pg_name:
+ LOG.debug(_("MidoClient.delete_for_sg: deleting pg=%r"),
+ pg)
+ self.mido_api.delete_port_group(pg.get_id())
+
+ @handle_api_error
def get_sg_chains(self, tenant_id, sg_id):
"""Get a list of chains mapped to a security group."""
- LOG.debug(_("ChainManager.get_sg_chains called: "
+ LOG.debug(_("MidoClient.get_sg_chains called: "
"tenant_id=%(tenant_id)s sg_id=%(sg_id)s"),
{'tenant_id': tenant_id, 'sg_id': sg_id})
assert 'out' in chains
return chains
- def _get_router_chain_names(self, router_id):
- LOG.debug(_("ChainManager.get_router_chain_names called: "
- "router_id=%(router_id)s"), {'router_id': router_id})
-
- in_name = OS_ROUTER_IN_CHAIN_NAME_FORMAT % router_id
- out_name = OS_ROUTER_OUT_CHAIN_NAME_FORMAT % router_id
- router_chain_names = {'in': in_name, 'out': out_name}
- return router_chain_names
-
-
-class PortGroupManager:
-
- def __init__(self, mido_api):
- self.mido_api = mido_api
-
- def create(self, tenant_id, sg_id, sg_name):
- LOG.debug(_("PortGroupManager.create called: "
- "tenant_id=%(tenant_id)s sg_id=%(sg_id)s "
- "sg_name=%(sg_name)s"),
- {'tenant_id': tenant_id, 'sg_id': sg_id, 'sg_name': sg_name})
- pg_name = port_group_name(sg_id, sg_name)
- self.mido_api.add_port_group().tenant_id(tenant_id).name(
- pg_name).create()
-
- def delete(self, tenant_id, sg_id, sg_name):
- LOG.debug(_("PortGroupManager.delete called: "
- "tenant_id=%(tenant_id)s sg_id=%(sg_id)s "
- "sg_name=%(sg_name)s"),
- {'tenant_id': tenant_id, 'sg_id': sg_id, 'sg_name': sg_name})
- pg_name = port_group_name(sg_id, sg_name)
- pgs = self.mido_api.get_port_groups({'tenant_id': tenant_id})
- for pg in pgs:
- if pg.get_name() == pg_name:
- LOG.debug(_("PortGroupManager.delete: deleting pg=%r"), pg)
- pg.delete()
-
- def get_for_sg(self, tenant_id, sg_id):
- LOG.debug(_("PortGroupManager.get_for_sg called: "
+ @handle_api_error
+ def get_port_groups_for_sg(self, tenant_id, sg_id):
+ LOG.debug(_("MidoClient.get_port_groups_for_sg called: "
"tenant_id=%(tenant_id)s sg_id=%(sg_id)s"),
{'tenant_id': tenant_id, 'sg_id': sg_id})
port_groups = self.mido_api.get_port_groups({'tenant_id': tenant_id})
for pg in port_groups:
if pg.get_name().startswith(pg_name_prefix):
- LOG.debug(_("PortGroupManager.get_for_sg exiting: pg=%r"), pg)
+ LOG.debug(_(
+ "MidoClient.get_port_groups_for_sg exiting: pg=%r"), pg)
return pg
return None
-
-class RuleManager:
-
- OS_SG_KEY = 'os_sg_rule_id'
-
- def __init__(self, mido_api):
- self.mido_api = mido_api
- self.chain_manager = ChainManager(mido_api)
- self.pg_manager = PortGroupManager(mido_api)
-
- def _properties(self, os_sg_rule_id):
- return {self.OS_SG_KEY: str(os_sg_rule_id)}
-
+ @handle_api_error
def create_for_sg_rule(self, rule):
- LOG.debug(_("RuleManager.create_for_sg_rule called: rule=%r"), rule)
+ LOG.debug(_("MidoClient.create_for_sg_rule called: rule=%r"), rule)
direction = rule['direction']
protocol = rule['protocol']
tp_src_start = tp_src_end = icmp_type
tp_dst_start = tp_dst_end = icmp_code
- chains = self.chain_manager.get_sg_chains(tenant_id, security_group_id)
+ chains = self.get_sg_chains(tenant_id, security_group_id)
chain = None
if direction == 'egress':
chain = chains['in']
raise Exception(_("Don't know what to do with rule=%r"), rule)
# create an accept rule
- properties = self._properties(rule_id)
- LOG.debug(_("RuleManager.create_for_sg_rule: adding accept rule "
+ properties = sg_rule_properties(rule_id)
+ LOG.debug(_("MidoClient.create_for_sg_rule: adding accept rule "
"%(rule_id)s in portgroup %(port_group_id)s"),
{'rule_id': rule_id, 'port_group_id': port_group_id})
chain.add_rule().port_group(port_group_id).type('accept').nw_proto(
tp_src_end).tp_dst_start(tp_dst_start).tp_dst_end(
tp_dst_end).properties(properties).create()
+ @handle_api_error
def delete_for_sg_rule(self, rule):
- LOG.debug(_("RuleManager.delete_for_sg_rule called: rule=%r"), rule)
+ LOG.debug(_("MidoClient.delete_for_sg_rule called: rule=%r"), rule)
tenant_id = rule['tenant_id']
security_group_id = rule['security_group_id']
rule_id = rule['id']
- properties = self._properties(rule_id)
+ properties = sg_rule_properties(rule_id)
# search for the chains to find the rule to delete
- chains = self.chain_manager.get_sg_chains(tenant_id, security_group_id)
+ chains = self.get_sg_chains(tenant_id, security_group_id)
for c in chains['in'], chains['out']:
rules = c.get_rules()
for r in rules:
if r.get_properties() == properties:
- LOG.debug(_("RuleManager.delete_for_sg_rule: deleting "
+ LOG.debug(_("MidoClient.delete_for_sg_rule: deleting "
"rule %r"), r)
- r.delete()
+ self.mido_api.delete_rule(r.get_id())
from midonetclient import api
from oslo.config import cfg
-from webob import exc as w_exc
from quantum.common import exceptions as q_exc
from quantum.db import api as db
LOG = logging.getLogger(__name__)
-OS_TENANT_ROUTER_RULE_KEY = 'OS_TENANT_ROUTER_RULE'
-OS_FLOATING_IP_RULE_KEY = 'OS_FLOATING_IP'
-SNAT_RULE = 'SNAT'
-SNAT_RULE_PROPERTY = {OS_TENANT_ROUTER_RULE_KEY: SNAT_RULE}
-
-
-class MidonetResourceNotFound(q_exc.NotFound):
- message = _('MidoNet %(resource_type)s %(id)s could not be found')
-
class MidonetPluginException(q_exc.QuantumException):
message = _("%(msg)s")
securitygroups_db.SecurityGroupDbMixin):
supported_extension_aliases = ['router', 'security-group']
+ __native_bulk_support = False
def __init__(self):
self.mido_api = api.MidonetApi(midonet_uri, admin_user,
admin_pass,
project_id=admin_project_id)
+ self.client = midonet_lib.MidoClient(self.mido_api)
- # get MidoNet provider router and metadata router
if provider_router_id and metadata_router_id:
- self.provider_router = self.mido_api.get_router(provider_router_id)
- self.metadata_router = self.mido_api.get_router(metadata_router_id)
-
- # for dev purpose only
- elif mode == 'dev':
- msg = _('No provider router and metadata device ids found. '
- 'But skipping because running in dev env.')
- LOG.debug(msg)
- else:
- msg = _('provider_router_id and metadata_router_id '
- 'should be configured in the plugin config file')
- LOG.exception(msg)
- raise MidonetPluginException(msg=msg)
-
- self.chain_manager = midonet_lib.ChainManager(self.mido_api)
- self.pg_manager = midonet_lib.PortGroupManager(self.mido_api)
- self.rule_manager = midonet_lib.RuleManager(self.mido_api)
+ # get MidoNet provider router and metadata router
+ self.provider_router = self.client.get_router(provider_router_id)
+ self.metadata_router = self.client.get_router(metadata_router_id)
+
+ elif not provider_router_id or not metadata_router_id:
+ if mode == 'dev':
+ msg = _('No provider router and metadata device ids found. '
+ 'But skipping because running in dev env.')
+ LOG.debug(msg)
+ else:
+ msg = _('provider_router_id and metadata_router_id '
+ 'should be configured in the plugin config file')
+ LOG.exception(msg)
+ raise MidonetPluginException(msg=msg)
db.configure_db()
with session.begin(subtransactions=True):
sn_entry = super(MidonetPluginV2, self).create_subnet(context,
subnet)
- try:
- bridge = self.mido_api.get_bridge(sn_entry['network_id'])
- except w_exc.HTTPNotFound:
- raise MidonetResourceNotFound(resource_type='Bridge',
- id=sn_entry['network_id'])
+ bridge = self.client.get_bridge(sn_entry['network_id'])
gateway_ip = subnet['subnet']['gateway_ip']
network_address, prefix = subnet['subnet']['cidr'].split('/')
- bridge.add_dhcp_subnet().default_gateway(gateway_ip).subnet_prefix(
- network_address).subnet_length(prefix).create()
+ self.client.create_dhcp(bridge, gateway_ip, network_address,
+ prefix)
- # If the network is external, link the bridge to MidoNet provider
- # router
+ # For external network, link the bridge to the provider router.
self._extend_network_dict_l3(context, net)
if net['router:external']:
gateway_ip = sn_entry['gateway_ip']
network_address, length = sn_entry['cidr'].split('/')
- # create a interior port in the MidoNet provider router
- in_port = self.provider_router.add_interior_port()
- pr_port = in_port.port_address(gateway_ip).network_address(
- network_address).network_length(length).create()
-
- # create a interior port in the bridge, then link
- # it to the provider router.
- br_port = bridge.add_interior_port().create()
- pr_port.link(br_port.get_id())
-
- # add a route for the subnet in the provider router
- self.provider_router.add_route().type(
- 'Normal').src_network_addr('0.0.0.0').src_network_length(
- 0).dst_network_addr(
- network_address).dst_network_length(
- length).weight(100).next_hop_port(
- pr_port.get_id()).create()
+ self.client.link_bridge_to_provider_router(
+ bridge, self.provider_router, gateway_ip, network_address,
+ length)
LOG.debug(_("MidonetPluginV2.create_subnet exiting: sn_entry=%r"),
sn_entry)
return sn_entry
- def get_subnet(self, context, id, fields=None):
- """Get Quantum subnet.
-
- Retrieves a Quantum subnet record but also including the DHCP entry
- data stored in MidoNet.
- """
- LOG.debug(_("MidonetPluginV2.get_subnet called: id=%(id)s "
- "fields=%(fields)s"), {'id': id, 'fields': fields})
-
- qsubnet = super(MidonetPluginV2, self).get_subnet(context, id)
- bridge_id = qsubnet['network_id']
- try:
- bridge = self.mido_api.get_bridge(bridge_id)
- except w_exc.HTTPNotFound:
- raise MidonetResourceNotFound(resource_type='Bridge',
- id=bridge_id)
-
- # get dhcp subnet data from MidoNet bridge.
- dhcps = bridge.get_dhcp_subnets()
- b_network_address = dhcps[0].get_subnet_prefix()
- b_prefix = dhcps[0].get_subnet_length()
-
- # Validate against quantum database.
- network_address, prefix = qsubnet['cidr'].split('/')
- if network_address != b_network_address or int(prefix) != b_prefix:
- raise MidonetResourceNotFound(resource_type='DhcpSubnet',
- id=qsubnet['cidr'])
-
- LOG.debug(_("MidonetPluginV2.get_subnet exiting: qsubnet=%s"), qsubnet)
- return qsubnet
-
- def get_subnets(self, context, filters=None, fields=None):
- """List Quantum subnets.
-
- Retrieves Quantum subnets with some fields populated by the data
- stored in MidoNet.
- """
- LOG.debug(_("MidonetPluginV2.get_subnets called: filters=%(filters)r, "
- "fields=%(fields)r"),
- {'filters': filters, 'fields': fields})
- subnets = super(MidonetPluginV2, self).get_subnets(context, filters,
- fields)
- for sn in subnets:
- if not 'network_id' in sn:
- continue
- try:
- bridge = self.mido_api.get_bridge(sn['network_id'])
- except w_exc.HTTPNotFound:
- raise MidonetResourceNotFound(resource_type='Bridge',
- id=sn['network_id'])
-
- # TODO(tomoe): dedupe this part.
- # get dhcp subnet data from MidoNet bridge.
- dhcps = bridge.get_dhcp_subnets()
- b_network_address = dhcps[0].get_subnet_prefix()
- b_prefix = dhcps[0].get_subnet_length()
-
- # Validate against quantum database.
- if sn.get('cidr'):
- network_address, prefix = sn['cidr'].split('/')
- if network_address != b_network_address or int(
- prefix) != b_prefix:
- raise MidonetResourceNotFound(resource_type='DhcpSubnet',
- id=sn['cidr'])
-
- LOG.debug(_("MidonetPluginV2.create_subnet exiting"))
- return subnets
-
def delete_subnet(self, context, id):
"""Delete Quantum subnet.
net = super(MidonetPluginV2, self).get_network(context,
subnet['network_id'],
fields=None)
- bridge_id = subnet['network_id']
- try:
- bridge = self.mido_api.get_bridge(bridge_id)
- except w_exc.HTTPNotFound:
- raise MidonetResourceNotFound(resource_type='Bridge', id=bridge_id)
-
- dhcp = bridge.get_dhcp_subnets()
- dhcp[0].delete()
+ bridge = self.client.get_bridge(subnet['network_id'])
+ self.client.delete_dhcp(bridge)
# If the network is external, clean up routes, links, ports.
self._extend_network_dict_l3(context, net)
if net['router:external']:
- # Delete routes and unlink the router and the bridge.
- routes = self.provider_router.get_routes()
-
- bridge_ports_to_delete = []
- for p in self.provider_router.get_peer_ports():
- if p.get_device_id() == bridge.get_id():
- bridge_ports_to_delete.append(p)
-
- for p in bridge.get_peer_ports():
- if p.get_device_id() == self.provider_router.get_id():
- # delete the routes going to the brdge
- for r in routes:
- if r.get_next_hop_port() == p.get_id():
- r.delete()
- p.unlink()
- p.delete()
-
- # delete bridge port
- map(lambda x: x.delete(), bridge_ports_to_delete)
+ self.client.unlink_bridge_from_provider_router(
+ bridge, self.provider_router)
super(MidonetPluginV2, self).delete_subnet(context, id)
LOG.debug(_("MidonetPluginV2.delete_subnet exiting"))
network)
if network['network']['admin_state_up'] is False:
- LOG.warning(_('Ignoring admin_state_up=False for network=%r'
- 'Overriding with True'), network)
- network['network']['admin_state_up'] = True
+ LOG.warning(_('Ignoring admin_state_up=False for network=%r '
+ 'because it is not yet supported'), network)
tenant_id = self._get_tenant_id_for_create(context, network['network'])
session = context.session
with session.begin(subtransactions=True):
- bridge = self.mido_api.add_bridge().name(
- network['network']['name']).tenant_id(tenant_id).create()
+ bridge = self.client.create_bridge(tenant_id,
+ network['network']['name'])
# Set MidoNet bridge ID to the quantum DB entry
network['network']['id'] = bridge.get_id()
with session.begin(subtransactions=True):
net = super(MidonetPluginV2, self).update_network(
context, id, network)
- try:
- bridge = self.mido_api.get_bridge(id)
- except w_exc.HTTPNotFound:
- raise MidonetResourceNotFound(resource_type='Bridge', id=id)
- bridge.name(net['name']).update()
+ self.client.update_bridge(id, net['name'])
self._extend_network_dict_l3(context, net)
LOG.debug(_("MidonetPluginV2.update_network exiting: net=%r"), net)
# NOTE: Get network data with all fields (fields=None) for
# _extend_network_dict_l3() method, which needs 'id' field
qnet = super(MidonetPluginV2, self).get_network(context, id, None)
- try:
- self.mido_api.get_bridge(id)
- except w_exc.HTTPNotFound:
- raise MidonetResourceNotFound(resource_type='Bridge', id=id)
+ self.client.get_bridge(id)
self._extend_network_dict_l3(context, qnet)
LOG.debug(_("MidonetPluginV2.get_network exiting: qnet=%r"), qnet)
# _extend_network_dict_l3() method, which needs 'id' field
qnets = super(MidonetPluginV2, self).get_networks(context, filters,
None)
- self.mido_api.get_bridges({'tenant_id': context.tenant_id})
for n in qnets:
- try:
- self.mido_api.get_bridge(n['id'])
- except w_exc.HTTPNotFound:
- raise MidonetResourceNotFound(resource_type='Bridge',
- id=n['id'])
self._extend_network_dict_l3(context, n)
return [self._fields(net, fields) for net in qnets]
def delete_network(self, context, id):
"""Delete a network and its corresponding MidoNet bridge."""
LOG.debug(_("MidonetPluginV2.delete_network called: id=%r"), id)
-
- self.mido_api.get_bridge(id).delete()
+ self.client.delete_bridge(id)
try:
super(MidonetPluginV2, self).delete_network(context, id)
except Exception:
is_compute_interface = False
port_data = port['port']
# get the bridge and create a port on it.
- try:
- bridge = self.mido_api.get_bridge(port_data['network_id'])
- except w_exc.HTTPNotFound:
- raise MidonetResourceNotFound(resource_type='Bridge',
- id=port_data['network_id'])
+ bridge = self.client.get_bridge(port_data['network_id'])
device_owner = port_data['device_owner']
if device_owner.startswith('compute:') or device_owner is '':
is_compute_interface = True
- bridge_port = bridge.add_exterior_port().create()
+ bridge_port = self.client.create_exterior_bridge_port(bridge)
elif device_owner == l3_db.DEVICE_OWNER_ROUTER_INTF:
- bridge_port = bridge.add_interior_port().create()
+ bridge_port = self.client.create_interior_bridge_port(bridge)
elif (device_owner == l3_db.DEVICE_OWNER_ROUTER_GW or
device_owner == l3_db.DEVICE_OWNER_FLOATINGIP):
# This is a dummy port to make l3_db happy.
# This will not be used in MidoNet
- bridge_port = bridge.add_interior_port().create()
+ bridge_port = self.client.create_interior_bridge_port(bridge)
if bridge_port:
# set midonet port id to quantum port id and create a DB record.
fixed_ip = port_db_entry['fixed_ips'][0]['ip_address']
mac = port_db_entry['mac_address']
# create dhcp host entry under the bridge.
- dhcp_subnets = bridge.get_dhcp_subnets()
- if dhcp_subnets:
- dhcp_subnets[0].add_dhcp_host().ip_addr(
- fixed_ip).mac_addr(mac).create()
+ self.client.create_dhcp_hosts(bridge, fixed_ip, mac)
LOG.debug(_("MidonetPluginV2.create_port exiting: port_db_entry=%r"),
port_db_entry)
return port_db_entry
- def update_port(self, context, id, port):
- """Update port."""
- LOG.debug(_("MidonetPluginV2.update_port called: id=%(id)s "
- "port=%(port)r"), {'id': id, 'port': port})
- return super(MidonetPluginV2, self).update_port(context, id, port)
-
def get_port(self, context, id, fields=None):
"""Retrieve port."""
LOG.debug(_("MidonetPluginV2.get_port called: id=%(id)s "
port_db_entry = super(MidonetPluginV2, self).get_port(context,
id, fields)
# verify that corresponding port exists in MidoNet.
- try:
- self.mido_api.get_port(id)
- except w_exc.HTTPNotFound:
- raise MidonetResourceNotFound(resource_type='Port', id=id)
+ self.client.get_port(id)
LOG.debug(_("MidonetPluginV2.get_port exiting: port_db_entry=%r"),
port_db_entry)
filters,
fields)
if ports_db_entry:
- try:
- for port in ports_db_entry:
- self.mido_api.get_port(port['id'])
- except w_exc.HTTPNotFound:
- raise MidonetResourceNotFound(resource_type='Port',
- id=port['id'])
+ for port in ports_db_entry:
+ if 'security_gorups' in port:
+ self._extend_port_dict_security_group(context, port)
return ports_db_entry
def delete_port(self, context, id, l3_port_check=True):
with session.begin(subtransactions=True):
port_db_entry = super(MidonetPluginV2, self).get_port(context,
id, None)
- bridge = self.mido_api.get_bridge(port_db_entry['network_id'])
# Clean up dhcp host entry if needed.
if 'ip_address' in (port_db_entry['fixed_ips'] or [{}])[0]:
# get ip and mac from DB record.
mac = port_db_entry['mac_address']
# create dhcp host entry under the bridge.
- dhcp_subnets = bridge.get_dhcp_subnets()
- if dhcp_subnets:
- for dh in dhcp_subnets[0].get_dhcp_hosts():
- if dh.get_mac_addr() == mac and dh.get_ip_addr() == ip:
- dh.delete()
+ self.client.delete_dhcp_hosts(port_db_entry['network_id'], ip,
+ mac)
- self.mido_api.get_port(id).delete()
+ self.client.delete_port(id)
return super(MidonetPluginV2, self).delete_port(context, id)
#
tenant_id = self._get_tenant_id_for_create(context, router['router'])
session = context.session
with session.begin(subtransactions=True):
- mrouter = self.mido_api.add_router().name(
- router['router']['name']).tenant_id(tenant_id).create()
+ mrouter = self.client.create_tenant_router(
+ tenant_id, router['router']['name'], self.metadata_router)
+
qrouter = super(MidonetPluginV2, self).create_router(context,
router)
- chains = self.chain_manager.create_router_chains(tenant_id,
- mrouter.get_id())
-
- # set chains to in/out filters
- mrouter.inbound_filter_id(
- chains['in'].get_id()).outbound_filter_id(
- chains['out'].get_id()).update()
-
# get entry from the DB and update 'id' with MidoNet router id.
qrouter_entry = self._get_router(context, qrouter['id'])
qrouter['id'] = mrouter.get_id()
qrouter_entry.update(qrouter)
- # link to metadata router
- in_port = self.metadata_router.add_interior_port()
- mdr_port = in_port.network_address('169.254.255.0').network_length(
- 30).port_address('169.254.255.1').create()
-
- tr_port = mrouter.add_interior_port().network_address(
- '169.254.255.0').network_length(30).port_address(
- '169.254.255.2').create()
- mdr_port.link(tr_port.get_id())
-
- # forward metadata traffic to metadata router
- mrouter.add_route().type('Normal').src_network_addr(
- '0.0.0.0').src_network_length(0).dst_network_addr(
- '169.254.169.254').dst_network_length(32).weight(
- 100).next_hop_port(tr_port.get_id()).create()
-
LOG.debug(_("MidonetPluginV2.create_router exiting: qrouter=%r"),
qrouter)
return qrouter
changed_name = router['router'].get('name')
if changed_name:
- self.mido_api.get_router(id).name(changed_name).update()
+ self.client.update_router(id, changed_name)
- tenant_router = self.mido_api.get_router(id)
if op_gateway_set:
# find a qport with the network_id for the router
qports = super(MidonetPluginV2, self).get_ports(
qport = qports[0]
snat_ip = qport['fixed_ips'][0]['ip_address']
- in_port = self.provider_router.add_interior_port()
- pr_port = in_port.network_address(
- '169.254.255.0').network_length(30).port_address(
- '169.254.255.1').create()
-
- # Create a port in the tenant router
- tr_port = tenant_router.add_interior_port().network_address(
- '169.254.255.0').network_length(30).port_address(
- '169.254.255.2').create()
-
- # Link them
- pr_port.link(tr_port.get_id())
-
- # Add a route for snat_ip to bring it down to tenant
- self.provider_router.add_route().type(
- 'Normal').src_network_addr('0.0.0.0').src_network_length(
- 0).dst_network_addr(snat_ip).dst_network_length(
- 32).weight(100).next_hop_port(
- pr_port.get_id()).create()
-
- # Add default route to uplink in the tenant router
- tenant_router.add_route().type('Normal').src_network_addr(
- '0.0.0.0').src_network_length(0).dst_network_addr(
- '0.0.0.0').dst_network_length(0).weight(
- 100).next_hop_port(tr_port.get_id()).create()
-
- # ADD SNAT(masquerade) rules
- chains = self.chain_manager.get_router_chains(
- tenant_router.get_tenant_id(), tenant_router.get_id())
-
- chains['in'].add_rule().nw_dst_address(snat_ip).nw_dst_length(
- 32).type('rev_snat').flow_action('accept').in_ports(
- [tr_port.get_id()]).properties(
- SNAT_RULE_PROPERTY).position(1).create()
-
- nat_targets = []
- nat_targets.append(
- {'addressFrom': snat_ip, 'addressTo': snat_ip,
- 'portFrom': 1, 'portTo': 65535})
-
- chains['out'].add_rule().type('snat').flow_action(
- 'accept').nat_targets(nat_targets).out_ports(
- [tr_port.get_id()]).properties(
- SNAT_RULE_PROPERTY).position(1).create()
+ self.client.set_router_external_gateway(id,
+ self.provider_router,
+ snat_ip)
if op_gateway_clear:
- # delete the port that is connected to provider router
- for p in tenant_router.get_ports():
- if p.get_port_address() == '169.254.255.2':
- peer_port_id = p.get_peer_id()
- p.unlink()
- self.mido_api.get_port(peer_port_id).delete()
- p.delete()
-
- # delete default route
- for r in tenant_router.get_routes():
- if (r.get_dst_network_addr() == '0.0.0.0' and
- r.get_dst_network_length() == 0):
- r.delete()
-
- # delete SNAT(masquerade) rules
- chains = self.chain_manager.get_router_chains(
- tenant_router.get_tenant_id(),
- tenant_router.get_id())
-
- for r in chains['in'].get_rules():
- if OS_TENANT_ROUTER_RULE_KEY in r.get_properties():
- if r.get_properties()[
- OS_TENANT_ROUTER_RULE_KEY] == SNAT_RULE:
- r.delete()
-
- for r in chains['out'].get_rules():
- if OS_TENANT_ROUTER_RULE_KEY in r.get_properties():
- if r.get_properties()[
- OS_TENANT_ROUTER_RULE_KEY] == SNAT_RULE:
- r.delete()
+ self.client.clear_router_external_gateway(id)
LOG.debug(_("MidonetPluginV2.update_router exiting: qrouter=%r"),
qrouter)
def delete_router(self, context, id):
LOG.debug(_("MidonetPluginV2.delete_router called: id=%s"), id)
- mrouter = self.mido_api.get_router(id)
- tenant_id = mrouter.get_tenant_id()
-
- # unlink from metadata router and delete the interior ports
- # that connect metadata router and this router.
- for pp in self.metadata_router.get_peer_ports():
- if pp.get_device_id() == mrouter.get_id():
- mdr_port = self.mido_api.get_port(pp.get_peer_id())
- pp.unlink()
- pp.delete()
- mdr_port.delete()
-
- # delete corresponding chains
- chains = self.chain_manager.get_router_chains(tenant_id,
- mrouter.get_id())
- chains['in'].delete()
- chains['out'].delete()
-
- # delete the router
- mrouter.delete()
+ self.client.delete_tenant_router(id)
result = super(MidonetPluginV2, self).delete_router(context, id)
LOG.debug(_("MidonetPluginV2.delete_router exiting: result=%s"),
result)
return result
- def get_router(self, context, id, fields=None):
- LOG.debug(_("MidonetPluginV2.get_router called: id=%(id)s "
- "fields=%(fields)r"), {'id': id, 'fields': fields})
- qrouter = super(MidonetPluginV2, self).get_router(context, id, fields)
-
- try:
- self.mido_api.get_router(id)
- except w_exc.HTTPNotFound:
- raise MidonetResourceNotFound(resource_type='Router', id=id)
-
- LOG.debug(_("MidonetPluginV2.get_router exiting: qrouter=%r"),
- qrouter)
- return qrouter
-
- def get_routers(self, context, filters=None, fields=None):
- LOG.debug(_("MidonetPluginV2.get_routers called: filters=%(filters)s "
- "fields=%(fields)r"),
- {'filters': filters, 'fields': fields})
-
- qrouters = super(MidonetPluginV2, self).get_routers(
- context, filters, fields)
- for qr in qrouters:
- try:
- self.mido_api.get_router(qr['id'])
- except w_exc.HTTPNotFound:
- raise MidonetResourceNotFound(resource_type='Router',
- id=qr['id'])
- return qrouters
-
def add_router_interface(self, context, router_id, interface_info):
LOG.debug(_("MidonetPluginV2.add_router_interface called: "
"router_id=%(router_id)s "
network_address, length = subnet['cidr'].split('/')
# Link the router and the bridge port.
- mrouter = self.mido_api.get_router(router_id)
- mrouter_port = mrouter.add_interior_port().port_address(
- gateway_ip).network_address(
- network_address).network_length(length).create()
-
- mbridge_port = self.mido_api.get_port(qport['port_id'])
- mrouter_port.link(mbridge_port.get_id())
-
- # Add a route entry to the subnet
- mrouter.add_route().type('Normal').src_network_addr(
- '0.0.0.0').src_network_length(0).dst_network_addr(
- network_address).dst_network_length(length).weight(
- 100).next_hop_port(mrouter_port.get_id()).create()
-
- # add a route for the subnet in metadata router; forward
- # packets destined to the subnet to the tenant router
- found = False
- for pp in self.metadata_router.get_peer_ports():
- if pp.get_device_id() == mrouter.get_id():
- mdr_port_id = pp.get_peer_id()
- found = True
- assert found
-
- self.metadata_router.add_route().type(
- 'Normal').src_network_addr('0.0.0.0').src_network_length(
- 0).dst_network_addr(network_address).dst_network_length(
- length).weight(100).next_hop_port(mdr_port_id).create()
+ self.client.link_bridge_port_to_router(qport['port_id'], router_id,
+ gateway_ip, network_address,
+ length,
+ self.metadata_router)
LOG.debug(_("MidonetPluginV2.add_router_interface exiting: "
"qport=%r"), qport)
"router_id=%(router_id)s "
"interface_info=%(interface_info)r"),
{'router_id': router_id, 'interface_info': interface_info})
+ port_id = None
if 'port_id' in interface_info:
- mbridge_port = self.mido_api.get_port(interface_info['port_id'])
+ port_id = interface_info['port_id']
subnet_id = self.get_port(context,
interface_info['port_id']
)['fixed_ips'][0]['subnet_id']
network_port = p
break
assert network_port
- mbridge_port = self.mido_api.get_port(network_port['id'])
+ port_id = network_port['id']
+
+ assert port_id
# get network information from subnet data
network_addr, network_length = subnet['cidr'].split('/')
network_length = int(network_length)
# Unlink the router and the bridge.
- mrouter = self.mido_api.get_router(router_id)
- mrouter_port = self.mido_api.get_port(mbridge_port.get_peer_id())
- mrouter_port.unlink()
-
- # Delete the route for the subnet.
- found = False
- for r in mrouter.get_routes():
- if r.get_next_hop_port() == mrouter_port.get_id():
- r.delete()
- found = True
- #break # commented out due to issue#314
- assert found
-
- # delete the route for the subnet in the metadata router
- found = False
- for r in self.metadata_router.get_routes():
- if (r.get_dst_network_addr() == network_addr and
- r.get_dst_network_length() == network_length):
- LOG.debug(_('Deleting route=%r ...'), r)
- r.delete()
- found = True
- break
- assert found
+ self.client.unlink_bridge_port_from_router(port_id, network_addr,
+ network_length,
+ self.metadata_router)
info = super(MidonetPluginV2, self).remove_router_interface(
context, router_id, interface_info)
if floatingip['floatingip']['port_id']:
fip = super(MidonetPluginV2, self).update_floatingip(
context, id, floatingip)
- router_id = fip['router_id']
- floating_address = fip['floating_ip_address']
- fixed_address = fip['fixed_ip_address']
-
- tenant_router = self.mido_api.get_router(router_id)
- # find the provider router port that is connected to the tenant
- # of the floating ip
- for p in tenant_router.get_peer_ports():
- if p.get_device_id() == self.provider_router.get_id():
- pr_port = p
-
- # get the tenant router port id connected to provider router
- tr_port_id = pr_port.get_peer_id()
-
- # add a route for the floating ip to bring it to the tenant
- self.provider_router.add_route().type(
- 'Normal').src_network_addr('0.0.0.0').src_network_length(
- 0).dst_network_addr(
- floating_address).dst_network_length(
- 32).weight(100).next_hop_port(
- pr_port.get_id()).create()
-
- chains = self.chain_manager.get_router_chains(fip['tenant_id'],
- fip['router_id'])
- # add dnat/snat rule pair for the floating ip
- nat_targets = []
- nat_targets.append(
- {'addressFrom': fixed_address, 'addressTo': fixed_address,
- 'portFrom': 0, 'portTo': 0})
-
- floating_property = {OS_FLOATING_IP_RULE_KEY: id}
- chains['in'].add_rule().nw_dst_address(
- floating_address).nw_dst_length(32).type(
- 'dnat').flow_action('accept').nat_targets(
- nat_targets).in_ports([tr_port_id]).position(
- 1).properties(floating_property).create()
-
- nat_targets = []
- nat_targets.append(
- {'addressFrom': floating_address,
- 'addressTo': floating_address,
- 'portFrom': 0,
- 'portTo': 0})
-
- chains['out'].add_rule().nw_src_address(
- fixed_address).nw_src_length(32).type(
- 'snat').flow_action('accept').nat_targets(
- nat_targets).out_ports(
- [tr_port_id]).position(1).properties(
- floating_property).create()
+ self.client.setup_floating_ip(fip['router_id'],
+ self.provider_router,
+ fip['floating_ip_address'],
+ fip['fixed_ip_address'], id)
# disassociate floating IP
elif floatingip['floatingip']['port_id'] is None:
fip = super(MidonetPluginV2, self).get_floatingip(context, id)
-
- router_id = fip['router_id']
- floating_address = fip['floating_ip_address']
- fixed_address = fip['fixed_ip_address']
-
- # delete the route for this floating ip
- for r in self.provider_router.get_routes():
- if (r.get_dst_network_addr() == floating_address and
- r.get_dst_network_length() == 32):
- r.delete()
-
- # delete snat/dnat rule pair for this floating ip
- chains = self.chain_manager.get_router_chains(fip['tenant_id'],
- fip['router_id'])
- LOG.debug(_('chains=%r'), chains)
-
- for r in chains['in'].get_rules():
- if OS_FLOATING_IP_RULE_KEY in r.get_properties():
- if r.get_properties()[OS_FLOATING_IP_RULE_KEY] == id:
- LOG.debug(_('deleting rule=%r'), r)
- r.delete()
- break
-
- for r in chains['out'].get_rules():
- if OS_FLOATING_IP_RULE_KEY in r.get_properties():
- if r.get_properties()[OS_FLOATING_IP_RULE_KEY] == id:
- LOG.debug(_('deleting rule=%r'), r)
- r.delete()
- break
-
+ self.client.clear_floating_ip(fip['router_id'],
+ self.provider_router,
+ fip['floating_ip_address'], id)
super(MidonetPluginV2, self).update_floatingip(context, id,
floatingip)
context, security_group, default_sg)
# Create MidoNet chains and portgroup for the SG
- sg_id = sg_db_entry['id']
- sg_name = sg_db_entry['name']
- self.chain_manager.create_for_sg(tenant_id, sg_id, sg_name)
- self.pg_manager.create(tenant_id, sg_id, sg_name)
+ self.client.create_for_sg(tenant_id, sg_db_entry['id'],
+ sg_db_entry['name'])
LOG.debug(_("MidonetPluginV2.create_security_group exiting: "
"sg_db_entry=%r"), sg_db_entry)
raise ext_sg.SecurityGroupInUse(id=sg_id)
# Delete MidoNet Chains and portgroup for the SG
- self.chain_manager.delete_for_sg(tenant_id, sg_id, sg_name)
- self.pg_manager.delete(tenant_id, sg_id, sg_name)
+ self.client.delete_for_sg(tenant_id, sg_id, sg_name)
return super(MidonetPluginV2, self).delete_security_group(
context, id)
MidonetPluginV2, self).create_security_group_rule(
context, security_group_rule)
- self.rule_manager.create_for_sg_rule(rule_db_entry)
+ self.client.create_for_sg_rule(rule_db_entry)
LOG.debug(_("MidonetPluginV2.create_security_group_rule exiting: "
"rule_db_entry=%r"), rule_db_entry)
return rule_db_entry
if not rule_db_entry:
raise ext_sg.SecurityGroupRuleNotFound(id=sgrid)
- self.rule_manager.delete_for_sg_rule(rule_db_entry)
+ self.client.delete_for_sg_rule(rule_db_entry)
return super(MidonetPluginV2,
self).delete_security_group_rule(context, sgrid)
--- /dev/null
+[MIDONET]
+
+# MidoNet API server URI
+midonet_uri = http://localhost:8080/midonet-api
+
+# MidoNet admin username
+username = admin
+
+# MidoNet admin password
+password = passw0rd
+
+# Virtual provider router ID
+provider_router_id = 00112233-0011-0011-0011-001122334455
+
+# Virtual metadata router ID
+metadata_router_id = ffeeddcc-ffee-ffee-ffee-ffeeddccbbaa
--- /dev/null
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# 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: Ryu Ishimoto, Midokura Japan KK
+
+import mock
+import uuid
+
+
+def get_bridge_mock(id=None, tenant_id='test-tenant', name='net'):
+ if id is None:
+ id = str(uuid.uuid4())
+
+ bridge = mock.Mock()
+ bridge.get_id.return_value = id
+ bridge.get_tenant_id.return_value = tenant_id
+ bridge.get_name.return_value = name
+ return bridge
+
+
+def get_bridge_port_mock(id=None, bridge_id=None,
+ type='ExteriorBridge'):
+ if id is None:
+ id = str(uuid.uuid4())
+ if bridge_id is None:
+ bridge_id = str(uuid.uuid4())
+
+ port = mock.Mock()
+ port.get_id.return_value = id
+ port.get_brige_id.return_value = bridge_id
+ port.get_type.return_value = type
+ return port
+
+
+def get_chain_mock(id=None, tenant_id='test-tenant', name='chain',
+ rules=None):
+ if id is None:
+ id = str(uuid.uuid4())
+
+ if rules is None:
+ rules = []
+
+ chain = mock.Mock()
+ chain.get_id.return_value = id
+ chain.get_tenant_id.return_value = tenant_id
+ chain.get_name.return_value = name
+ chain.get_rules.return_value = rules
+ return chain
+
+
+def get_exterior_bridge_port_mock(id=None, bridge_id=None):
+ if id is None:
+ id = str(uuid.uuid4())
+ if bridge_id is None:
+ bridge_id = str(uuid.uuid4())
+
+ return get_bridge_port_mock(id=id, bridge_id=bridge_id,
+ type='ExteriorBridge')
+
+
+def get_interior_bridge_port_mock(id=None, bridge_id=None):
+ if id is None:
+ id = str(uuid.uuid4())
+ if bridge_id is None:
+ bridge_id = str(uuid.uuid4())
+
+ return get_bridge_port_mock(id=id, bridge_id=bridge_id,
+ type='InteriorBridge')
+
+
+def get_port_group_mock(id=None, tenant_id='test-tenant', name='pg'):
+ if id is None:
+ id = str(uuid.uuid4())
+
+ port_group = mock.Mock()
+ port_group.get_id.return_value = id
+ port_group.get_tenant_id.return_value = tenant_id
+ port_group.get_name.return_value = name
+ return port_group
+
+
+def get_router_mock(id=None, tenant_id='test-tenant', name='router'):
+ if id is None:
+ id = str(uuid.uuid4())
+
+ router = mock.Mock()
+ router.get_id.return_value = id
+ router.get_tenant_id.return_value = tenant_id
+ router.get_name.return_value = name
+ return router
+
+
+def get_rule_mock(id=None, chain_id=None, properties=None):
+ if id is None:
+ id = str(uuid.uuid4())
+
+ if chain_id is None:
+ chain_id = str(uuid.uuid4())
+
+ if properties is None:
+ properties = {}
+
+ rule = mock.Mock()
+ rule.get_id.return_value = id
+ rule.get_chain_id.return_value = chain_id
+ rule.get_properties.return_value = properties
+ return rule
+
+
+def get_subnet_mock(bridge_id=None, gateway_ip='10.0.0.1',
+ subnet_prefix='10.0.0.0', subnet_len=int(24)):
+ if bridge_id is None:
+ bridge_id = str(uuid.uuid4())
+
+ subnet = mock.Mock()
+ subnet.get_id.return_value = subnet_prefix + '/' + str(subnet_len)
+ subnet.get_bridge_id.return_value = bridge_id
+ subnet.get_default_gateway.return_value = gateway_ip
+ subnet.get_subnet_prefix.return_value = subnet_prefix
+ subnet.get_subnet_length.return_value = subnet_len
+ return subnet
+
+
+class MidonetLibMockConfig():
+
+ def __init__(self, inst):
+ self.inst = inst
+
+ def _create_bridge(self, tenant_id, name):
+ return get_bridge_mock(tenant_id=tenant_id, name=name)
+
+ def _create_exterior_bridge_port(self, bridge):
+ return get_exterior_bridge_port_mock(bridge_id=bridge.get_id())
+
+ def _create_interior_bridge_port(self, bridge):
+ return get_interior_bridge_port_mock(bridge_id=bridge.get_id())
+
+ def _create_subnet(self, bridge, gateway_ip, subnet_prefix, subnet_len):
+ return get_subnet_mock(bridge.get_id(), gateway_ip=gateway_ip,
+ subnet_prefix=subnet_prefix,
+ subnet_len=subnet_len)
+
+ def _get_bridge(self, id):
+ return get_bridge_mock(id=id)
+
+ def _get_port(self, id):
+ return get_exterior_bridge_port_mock(id=id)
+
+ def _get_router(self, id):
+ return get_router_mock(id=id)
+
+ def _update_bridge(self, id, name):
+ return get_bridge_mock(id=id, name=name)
+
+ def setup(self):
+ # Bridge methods side effects
+ self.inst.create_bridge.side_effect = self._create_bridge
+ self.inst.get_bridge.side_effect = self._get_bridge
+ self.inst.update_bridge.side_effect = self._update_bridge
+
+ # Subnet methods side effects
+ self.inst.create_subnet.side_effect = self._create_subnet
+
+ # Port methods side effects
+ ex_bp = self.inst.create_exterior_bridge_port
+ ex_bp.side_effect = self._create_exterior_bridge_port
+ in_bp = self.inst.create_interior_bridge_port
+ in_bp.side_effect = self._create_interior_bridge_port
+ self.inst.get_port.side_effect = self._get_port
+
+ # Router methods side effects
+ self.inst.get_router.side_effect = self._get_router
+
+
+class MidoClientMockConfig():
+
+ def __init__(self, inst):
+ self.inst = inst
+ self.chains_in = None
+ self.port_groups_in = None
+ self.chains_out = None
+ self.rules_out = None
+ self.port_groups_out = None
+
+ def _get_query_tenant_id(self, query):
+ if query is not None and query['tenant_id']:
+ tenant_id = query['tenant_id']
+ else:
+ tenant_id = 'test-tenant'
+ return tenant_id
+
+ def _get_bridge(self, id):
+ return get_bridge_mock(id=id)
+
+ def _get_chains(self, query=None):
+ if not self.chains_in:
+ return []
+
+ tenant_id = self._get_query_tenant_id(query)
+ self.chains_out = []
+ self.rules_out = []
+ for chain in self.chains_in:
+ chain_id = chain['id']
+
+ rule_mocks = []
+ if 'rules' in chain:
+ for rule in chain['rules']:
+ rule_mocks.append(
+ get_rule_mock(id=rule['id'],
+ chain_id=id,
+ properties=rule['properties']))
+ self.rules_out += rule_mocks
+
+ self.chains_out.append(get_chain_mock(id=chain_id,
+ name=chain['name'],
+ tenant_id=tenant_id,
+ rules=rule_mocks))
+ return self.chains_out
+
+ def _get_port_groups(self, query=None):
+ if not self.port_groups_in:
+ return []
+
+ tenant_id = self._get_query_tenant_id(query)
+ self.port_groups_out = []
+ for port_group in self.port_groups_in:
+ self.port_groups_out.append(get_port_group_mock(
+ id=port_group['id'], name=port_group['name'],
+ tenant_id=tenant_id))
+ return self.port_groups_out
+
+ def _get_router(self, id):
+ return get_router_mock(id=id)
+
+ def setup(self):
+ self.inst.get_bridge.side_effect = self._get_bridge
+ self.inst.get_chains.side_effect = self._get_chains
+ self.inst.get_port_groups.side_effect = self._get_port_groups
+ self.inst.get_router.side_effect = self._get_router
# @author: Ryu Ishimoto, Midokura Japan KK
# @author: Tomoe Sugihara, Midokura Japan KK
-import uuid
import mock
+import testtools
+import webob.exc as w_exc
+from quantum.openstack.common import uuidutils
from quantum.plugins.midonet import midonet_lib
-from quantum.tests import base
+import quantum.tests.unit.midonet.mock_lib as mock_lib
-class MidonetLibTestCase(base.BaseTestCase):
+def _create_test_chain(id, name, tenant_id):
+ return {'id': id, 'name': name, 'tenant_id': tenant_id}
- def setUp(self):
- super(MidonetLibTestCase, self).setUp()
- self.mock_api = mock.Mock()
- def _create_mock_chains(self, sg_id, sg_name):
- mock_in_chain = mock.Mock()
- mock_in_chain.get_name.return_value = "OS_SG_%s_%s_IN" % (sg_id,
- sg_name)
- mock_out_chain = mock.Mock()
- mock_out_chain.get_name.return_value = "OS_SG_%s_%s_OUT" % (sg_id,
- sg_name)
- return (mock_in_chain, mock_out_chain)
+def _create_test_port_group(sg_id, sg_name, id, tenant_id):
+ return {"id": id, "name": "OS_SG_%s_%s" % (sg_id, sg_name),
+ "tenant_id": tenant_id}
- def _create_mock_router_chains(self, router_id):
- mock_in_chain = mock.Mock()
- mock_in_chain.get_name.return_value = "OS_ROUTER_IN_%s" % (router_id)
- mock_out_chain = mock.Mock()
- mock_out_chain.get_name.return_value = "OS_ROUTER_OUT_%s" % (router_id)
- return (mock_in_chain, mock_out_chain)
+def _create_test_router_in_chain(router_id, id, tenant_id):
+ name = "OS_ROUTER_IN_%s" % router_id
+ return _create_test_chain(id, name, tenant_id)
- def _create_mock_port_group(self, sg_id, sg_name):
- mock_pg = mock.Mock()
- mock_pg.get_name.return_value = "OS_SG_%s_%s" % (sg_id, sg_name)
- return mock_pg
- def _create_mock_rule(self, rule_id):
- mock_rule = mock.Mock()
- mock_rule.get_properties.return_value = {"os_sg_rule_id": rule_id}
- return mock_rule
+def _create_test_router_out_chain(router_id, id, tenant_id):
+ name = "OS_ROUTER_OUT_%s" % router_id
+ return _create_test_chain(id, name, tenant_id)
-class MidonetChainManagerTestCase(MidonetLibTestCase):
+def _create_test_rule(id, chain_id, properties):
+ return {"id": id, "chain_id": chain_id, "properties": properties}
- def setUp(self):
- super(MidonetChainManagerTestCase, self).setUp()
- self.mgr = midonet_lib.ChainManager(self.mock_api)
- def test_create_for_sg(self):
- tenant_id = 'test_tenant'
- sg_id = str(uuid.uuid4())
- sg_name = 'test_sg_name'
- calls = [mock.call.add_chain().tenant_id(tenant_id)]
+def _create_test_sg_in_chain(sg_id, sg_name, id, tenant_id):
+ if sg_name:
+ name = "OS_SG_%s_%s_IN" % (sg_id, sg_name)
+ else:
+ name = "OS_SG_%s_IN" % sg_id
+ return _create_test_chain(id, name, tenant_id)
- self.mgr.create_for_sg(tenant_id, sg_id, sg_name)
- self.mock_api.assert_has_calls(calls)
+def _create_test_sg_out_chain(sg_id, sg_name, id, tenant_id):
+ if sg_name:
+ name = "OS_SG_%s_%s_OUT" % (sg_id, sg_name)
+ else:
+ name = "OS_SG_%s_OUT" % sg_id
+ return _create_test_chain(id, name, tenant_id)
- def test_delete_for_sg(self):
- tenant_id = 'test_tenant'
- sg_id = str(uuid.uuid4())
- sg_name = 'test_sg_name'
- in_chain, out_chain = self._create_mock_chains(sg_id, sg_name)
- # Mock get_chains returned values
- self.mock_api.get_chains.return_value = [in_chain, out_chain]
+def _create_test_sg_rule(tenant_id, sg_id, id,
+ direction="egress", protocol="tcp", port_min=1,
+ port_max=65535, src_ip='192.168.1.0/24',
+ src_group_id=None, ethertype=0x0800, properties=None):
+ return {"tenant_id": tenant_id, "security_group_id": sg_id,
+ "id": id, "direction": direction, "protocol": protocol,
+ "remote_ip_prefix": src_ip, "remote_group_id": src_group_id,
+ "port_range_min": port_min, "port_range_max": port_max,
+ "ethertype": ethertype, "external_id": None}
- self.mgr.delete_for_sg(tenant_id, sg_id, sg_name)
- self.mock_api.assert_has_calls(mock.call.get_chains(
- {"tenant_id": tenant_id}))
- in_chain.delete.assert_called_once_with()
- out_chain.delete.assert_called_once_with()
+def _create_test_sg_chain_rule(id, chain_id, sg_rule_id):
+ props = {"os_sg_rule_id": sg_rule_id}
+ return _create_test_rule(id, chain_id, props)
- def test_get_router_chains(self):
- tenant_id = 'test_tenant'
- router_id = str(uuid.uuid4())
- in_chain, out_chain = self._create_mock_router_chains(router_id)
- # Mock get_chains returned values
- self.mock_api.get_chains.return_value = [in_chain, out_chain]
+class MidoClientTestCase(testtools.TestCase):
- chains = self.mgr.get_router_chains(tenant_id, router_id)
+ def setUp(self):
+ super(MidoClientTestCase, self).setUp()
+ self._tenant_id = 'test-tenant'
+ self.mock_api = mock.Mock()
+ self.mock_api_cfg = mock_lib.MidoClientMockConfig(self.mock_api)
+ self.mock_api_cfg.setup()
+ self.client = midonet_lib.MidoClient(self.mock_api)
- self.mock_api.assert_has_calls(mock.call.get_chains(
- {"tenant_id": tenant_id}))
- self.assertEqual(len(chains), 2)
- self.assertEqual(chains['in'], in_chain)
- self.assertEqual(chains['out'], out_chain)
+ def test_create_for_sg(self):
+ sg_id = uuidutils.generate_uuid()
+ sg_name = 'test-sg'
+ calls = [mock.call.add_chain().tenant_id(self._tenant_id),
+ mock.call.add_port_group().tenant_id(self._tenant_id)]
- def test_create_router_chains(self):
- tenant_id = 'test_tenant'
- router_id = str(uuid.uuid4())
- calls = [mock.call.add_chain().tenant_id(tenant_id)]
+ self.client.create_for_sg(self._tenant_id, sg_id, sg_name)
- self.mgr.create_router_chains(tenant_id, router_id)
+ self.mock_api.assert_has_calls(calls, any_order=True)
- self.mock_api.assert_has_calls(calls)
+ def test_create_for_sg_rule(self):
+ sg_id = uuidutils.generate_uuid()
+ sg_name = 'test-sg'
+ in_chain_id = uuidutils.generate_uuid()
+ out_chain_id = uuidutils.generate_uuid()
+ self.mock_api_cfg.chains_in = [
+ _create_test_sg_in_chain(sg_id, sg_name, in_chain_id,
+ self._tenant_id),
+ _create_test_sg_out_chain(sg_id, sg_name, out_chain_id,
+ self._tenant_id)]
+
+ sg_rule_id = uuidutils.generate_uuid()
+ sg_rule = _create_test_sg_rule(self._tenant_id, sg_id, sg_rule_id)
+
+ props = {"os_sg_rule_id": sg_rule_id}
+ calls = [mock.call.add_rule().port_group(None).type(
+ 'accept').nw_proto(6).nw_src_address(
+ '192.168.1.0').nw_src_length(24).tp_src_start(
+ None).tp_src_end(None).tp_dst_start(1).tp_dst_end(
+ 65535).properties(props).create()]
- def test_get_sg_chains(self):
- tenant_id = 'test_tenant'
- sg_id = str(uuid.uuid4())
- in_chain, out_chain = self._create_mock_chains(sg_id, 'foo')
+ self.client.create_for_sg_rule(sg_rule)
- # Mock get_chains returned values
- self.mock_api.get_chains.return_value = [in_chain, out_chain]
+ # Egress chain rule added
+ self.mock_api_cfg.chains_out[0].assert_has_calls(calls)
- chains = self.mgr.get_sg_chains(tenant_id, sg_id)
+ def test_create_router_chains(self):
+ router = mock_lib.get_router_mock(tenant_id=self._tenant_id)
+ api_calls = [mock.call.add_chain().tenant_id(self._tenant_id)]
+ router_calls = [
+ mock.call.inbound_filter_id().outbound_filter_id().update()]
- self.mock_api.assert_has_calls(mock.call.get_chains(
- {"tenant_id": tenant_id}))
- self.assertEqual(len(chains), 2)
- self.assertEqual(chains['in'], in_chain)
- self.assertEqual(chains['out'], out_chain)
+ self.client.create_router_chains(router)
+ self.mock_api.assert_has_calls(api_calls)
+ router.assert_has_calls(router_calls)
-class MidonetPortGroupManagerTestCase(MidonetLibTestCase):
+ def test_delete_for_sg(self):
+ sg_id = uuidutils.generate_uuid()
+ sg_name = 'test-sg'
+ in_chain_id = uuidutils.generate_uuid()
+ out_chain_id = uuidutils.generate_uuid()
+ pg_id = uuidutils.generate_uuid()
+ self.mock_api_cfg.chains_in = [
+ _create_test_sg_in_chain(sg_id, sg_name, in_chain_id,
+ self._tenant_id),
+ _create_test_sg_out_chain(sg_id, sg_name, out_chain_id,
+ self._tenant_id)]
+ self.mock_api_cfg.port_groups_in = [
+ _create_test_port_group(sg_id, sg_name, pg_id, self._tenant_id)]
+
+ calls = [mock.call.get_chains({"tenant_id": self._tenant_id}),
+ mock.call.delete_chain(in_chain_id),
+ mock.call.delete_chain(out_chain_id),
+ mock.call.get_port_groups({"tenant_id": self._tenant_id}),
+ mock.call.delete_port_group(pg_id)]
+
+ self.client.delete_for_sg(self._tenant_id, sg_id, sg_name)
- def setUp(self):
- super(MidonetPortGroupManagerTestCase, self).setUp()
- self.mgr = midonet_lib.PortGroupManager(self.mock_api)
+ self.mock_api.assert_has_calls(calls)
- def test_create(self):
- tenant_id = 'test_tenant'
- sg_id = str(uuid.uuid4())
- sg_name = 'test_sg'
- pg_mock = self._create_mock_port_group(sg_id, sg_name)
- rv = self.mock_api.add_port_group.return_value.tenant_id.return_value
- rv.name.return_value = pg_mock
+ def test_delete_for_sg_rule(self):
+ sg_id = uuidutils.generate_uuid()
+ sg_name = 'test-sg'
+ in_chain_id = uuidutils.generate_uuid()
+ out_chain_id = uuidutils.generate_uuid()
+ self.mock_api_cfg.chains_in = [
+ _create_test_sg_in_chain(sg_id, sg_name, in_chain_id,
+ self._tenant_id),
+ _create_test_sg_out_chain(sg_id, sg_name, out_chain_id,
+ self._tenant_id)]
- self.mgr.create(tenant_id, sg_id, sg_name)
+ rule_id = uuidutils.generate_uuid()
+ sg_rule_id = uuidutils.generate_uuid()
+ rule = _create_test_sg_chain_rule(rule_id, in_chain_id, sg_rule_id)
+ self.mock_api_cfg.chains_in[0]['rules'] = [rule]
+ sg_rule = _create_test_sg_rule(self._tenant_id, sg_id, sg_rule_id)
- pg_mock.create.assert_called_once_with()
+ self.client.delete_for_sg_rule(sg_rule)
- def test_delete(self):
- tenant_id = 'test_tenant'
- sg_id = str(uuid.uuid4())
- sg_name = 'test_sg'
- pg_mock1 = self._create_mock_port_group(sg_id, sg_name)
- pg_mock2 = self._create_mock_port_group(sg_id, sg_name)
- self.mock_api.get_port_groups.return_value = [pg_mock1, pg_mock2]
+ self.mock_api.delete_rule.assert_called_once_with(rule_id)
- self.mgr.delete(tenant_id, sg_id, sg_name)
+ def test_get_bridge(self):
+ bridge_id = uuidutils.generate_uuid()
- self.mock_api.assert_has_calls(mock.call.get_port_groups(
- {"tenant_id": tenant_id}))
- pg_mock1.delete.assert_called_once_with()
- pg_mock2.delete.assert_called_once_with()
+ bridge = self.client.get_bridge(bridge_id)
- def test_get_for_sg(self):
- tenant_id = 'test_tenant'
- sg_id = str(uuid.uuid4())
- pg_mock = self._create_mock_port_group(sg_id, 'foo')
- self.mock_api.get_port_groups.return_value = [pg_mock]
+ self.assertIsNotNone(bridge)
+ self.assertEqual(bridge.get_id(), bridge_id)
- pg = self.mgr.get_for_sg(tenant_id, sg_id)
+ def test_get_bridge_error(self):
+ self.mock_api.get_bridge.side_effect = w_exc.HTTPInternalServerError()
+ self.assertRaises(midonet_lib.MidonetApiException,
+ self.client.get_bridge, uuidutils.generate_uuid())
- self.assertEqual(pg, pg_mock)
+ def test_get_bridge_not_found(self):
+ self.mock_api.get_bridge.side_effect = w_exc.HTTPNotFound()
+ self.assertRaises(midonet_lib.MidonetResourceNotFound,
+ self.client.get_bridge, uuidutils.generate_uuid())
+ def test_get_port_groups_for_sg(self):
+ sg_id = uuidutils.generate_uuid()
+ pg_id = uuidutils.generate_uuid()
+ self.mock_api_cfg.port_groups_in = [
+ _create_test_port_group(sg_id, 'test-sg', pg_id, self._tenant_id)]
-class MidonetRuleManagerTestCase(MidonetLibTestCase):
+ pg = self.client.get_port_groups_for_sg(self._tenant_id, sg_id)
- def setUp(self):
- super(MidonetRuleManagerTestCase, self).setUp()
- self.mgr = midonet_lib.RuleManager(self.mock_api)
- self.mgr.chain_manager = mock.Mock()
- self.mgr.pg_manager = mock.Mock()
+ self.assertIsNotNone(pg)
+ self.assertEqual(pg.get_id(), pg_id)
def _create_test_rule(self, tenant_id, sg_id, rule_id, direction="egress",
protocol="tcp", port_min=1, port_max=65535,
"port_range_min": port_min, "port_range_max": port_max,
"ethertype": ethertype, "id": rule_id, "external_id": None}
- def test_create_for_sg_rule(self):
- tenant_id = 'test_tenant'
- sg_id = str(uuid.uuid4())
- rule_id = str(uuid.uuid4())
- in_chain, out_chain = self._create_mock_chains(sg_id, 'foo')
- self.mgr.chain_manager.get_sg_chains.return_value = {"in": in_chain,
- "out": out_chain}
- props = {"os_sg_rule_id": rule_id}
- rule = self._create_test_rule(tenant_id, sg_id, rule_id)
- calls = [mock.call.add_rule().port_group(None).type(
- 'accept').nw_proto(6).nw_src_address(
- '192.168.1.0').nw_src_length(24).tp_src_start(
- None).tp_src_end(None).tp_dst_start(1).tp_dst_end(
- 65535).properties(props).create()]
+ def test_get_router_error(self):
+ self.mock_api.get_router.side_effect = w_exc.HTTPInternalServerError()
+ self.assertRaises(midonet_lib.MidonetApiException,
+ self.client.get_router, uuidutils.generate_uuid())
- self.mgr.create_for_sg_rule(rule)
+ def test_get_router_not_found(self):
+ self.mock_api.get_router.side_effect = w_exc.HTTPNotFound()
+ self.assertRaises(midonet_lib.MidonetResourceNotFound,
+ self.client.get_router, uuidutils.generate_uuid())
- in_chain.assert_has_calls(calls)
+ def test_get_router_chains(self):
+ router_id = uuidutils.generate_uuid()
+ in_chain_id = uuidutils.generate_uuid()
+ out_chain_id = uuidutils.generate_uuid()
+ self.mock_api_cfg.chains_in = [
+ _create_test_router_in_chain(router_id, in_chain_id,
+ self._tenant_id),
+ _create_test_router_out_chain(router_id, out_chain_id,
+ self._tenant_id)]
- def test_delete_for_sg_rule(self):
- tenant_id = 'test_tenant'
- sg_id = str(uuid.uuid4())
- rule_id = str(uuid.uuid4())
- in_chain, out_chain = self._create_mock_chains(sg_id, 'foo')
- self.mgr.chain_manager.get_sg_chains.return_value = {"in": in_chain,
- "out": out_chain}
-
- # Mock the rules returned for each chain
- mock_rule_in = self._create_mock_rule(rule_id)
- mock_rule_out = self._create_mock_rule(rule_id)
- in_chain.get_rules.return_value = [mock_rule_in]
- out_chain.get_rules.return_value = [mock_rule_out]
-
- rule = self._create_test_rule(tenant_id, sg_id, rule_id)
- self.mgr.delete_for_sg_rule(rule)
-
- mock_rule_in.delete.assert_called_once_with()
- mock_rule_out.delete.assert_called_once_with()
+ chains = self.client.get_router_chains(self._tenant_id, router_id)
+
+ self.mock_api.assert_has_calls(mock.call.get_chains(
+ {"tenant_id": self._tenant_id}))
+ self.assertEqual(len(chains), 2)
+ self.assertIn('in', chains)
+ self.assertIn('out', chains)
+ self.assertEqual(chains['in'].get_id(), in_chain_id)
+ self.assertEqual(chains['out'].get_id(), out_chain_id)
+
+ def test_get_sg_chains(self):
+ sg_id = uuidutils.generate_uuid()
+ sg_name = 'test-sg'
+ in_chain_id = uuidutils.generate_uuid()
+ out_chain_id = uuidutils.generate_uuid()
+ self.mock_api_cfg.chains_in = [
+ _create_test_sg_in_chain(sg_id, sg_name, in_chain_id,
+ self._tenant_id),
+ _create_test_sg_out_chain(sg_id, sg_name, out_chain_id,
+ self._tenant_id)]
+
+ chains = self.client.get_sg_chains(self._tenant_id, sg_id)
+
+ self.mock_api.assert_has_calls(mock.call.get_chains(
+ {"tenant_id": self._tenant_id}))
+ self.assertEqual(len(chains), 2)
+ self.assertIn('in', chains)
+ self.assertIn('out', chains)
+ self.assertEqual(chains['in'].get_id(), in_chain_id)
+ self.assertEqual(chains['out'].get_id(), out_chain_id)
# @author: Ryu Ishimoto, Midokura Japan KK
# @author: Tomoe Sugihara, Midokura Japan KK
-import sys
-import uuid
-
import mock
+import os
+import sys
+import quantum.common.test_lib as test_lib
+import quantum.tests.unit.midonet.mock_lib as mock_lib
import quantum.tests.unit.test_db_plugin as test_plugin
MIDOKURA_PKG_PATH = "quantum.plugins.midonet.plugin"
+
# Need to mock the midonetclient module since the plugin will try to load it.
sys.modules["midonetclient"] = mock.Mock()
_plugin_name = ('%s.MidonetPluginV2' % MIDOKURA_PKG_PATH)
def setUp(self):
- self.mock_api = mock.patch('midonetclient.api.MidonetApi')
+ self.mock_api = mock.patch(
+ 'quantum.plugins.midonet.midonet_lib.MidoClient')
+ etc_path = os.path.join(os.path.dirname(__file__), 'etc')
+ test_lib.test_config['config_files'] = [os.path.join(
+ etc_path, 'midonet.ini.test')]
+
self.instance = self.mock_api.start()
+ mock_cfg = mock_lib.MidonetLibMockConfig(self.instance.return_value)
+ mock_cfg.setup()
super(MidonetPluginV2TestCase, self).setUp(self._plugin_name)
def tearDown(self):
super(MidonetPluginV2TestCase, self).tearDown()
self.mock_api.stop()
- def _setup_bridge_mock(self, bridge_id=str(uuid.uuid4()), name='net'):
- # Set up mocks needed for the parent network() method
- bridge = mock.Mock()
- bridge.get_id.return_value = bridge_id
- bridge.get_name.return_value = name
-
- self.instance.return_value.add_bridge.return_value.name.return_value\
- .tenant_id.return_value.create.return_value = bridge
- self.instance.return_value.get_bridges.return_value = [bridge]
- self.instance.return_value.get_bridge.return_value = bridge
- return bridge
-
- def _setup_subnet_mocks(self, subnet_id=str(uuid.uuid4()),
- subnet_prefix='10.0.0.0', subnet_len=int(24)):
- # Set up mocks needed for the parent subnet() method
- bridge = self._setup_bridge_mock()
- subnet = mock.Mock()
- subnet.get_subnet_prefix.return_value = subnet_prefix
- subnet.get_subnet_length.return_value = subnet_len
- subnet.get_id.return_value = subnet_prefix + '/' + str(subnet_len)
- bridge.add_dhcp_subnet.return_value.default_gateway\
- .return_value.subnet_prefix.return_value.subnet_length\
- .return_value.create.return_value = subnet
- bridge.get_dhcp_subnets.return_value = [subnet]
- return (bridge, subnet)
-
- def _setup_port_mocks(self, port_id=str(uuid.uuid4())):
- # Set up mocks needed for the parent port() method
- bridge, subnet = self._setup_subnet_mocks()
- port = mock.Mock()
- port.get_id.return_value = port_id
- self.instance.return_value.create_port.return_value = port
- self.instance.return_value.get_port.return_value = port
- bridge.add_exterior_port.return_value.create.return_value = (
- port
- )
-
- dhcp_host = mock.Mock()
- rv1 = subnet.add_dhcp_host.return_value.ip_addr.return_value
- rv1.mac_addr.return_value.create.return_value = dhcp_host
-
- subnet.get_dhcp_hosts.return_value = [dhcp_host]
- return (bridge, subnet, port, dhcp_host)
-
class TestMidonetNetworksV2(test_plugin.TestNetworksV2,
MidonetPluginV2TestCase):
-
- def test_create_network(self):
- self._setup_bridge_mock()
- super(TestMidonetNetworksV2, self).test_create_network()
-
- def test_create_public_network(self):
- self._setup_bridge_mock()
- super(TestMidonetNetworksV2, self).test_create_public_network()
-
- def test_create_public_network_no_admin_tenant(self):
- self._setup_bridge_mock()
- super(TestMidonetNetworksV2,
- self).test_create_public_network_no_admin_tenant()
-
- def test_update_network(self):
- self._setup_bridge_mock()
- super(TestMidonetNetworksV2, self).test_update_network()
-
- def test_list_networks(self):
- self._setup_bridge_mock()
- with self.network(name='net1') as net1:
- req = self.new_list_request('networks')
- res = self.deserialize('json', req.get_response(self.api))
- self.assertEqual(res['networks'][0]['name'],
- net1['network']['name'])
-
- def test_show_network(self):
- self._setup_bridge_mock()
- super(TestMidonetNetworksV2, self).test_show_network()
-
- def test_update_shared_network_noadmin_returns_403(self):
- self._setup_bridge_mock()
- super(TestMidonetNetworksV2,
- self).test_update_shared_network_noadmin_returns_403()
-
- def test_update_network_set_shared(self):
- pass
-
- def test_update_network_with_subnet_set_shared(self):
- pass
-
- def test_update_network_set_not_shared_single_tenant(self):
- pass
-
- def test_update_network_set_not_shared_other_tenant_returns_409(self):
- pass
-
- def test_update_network_set_not_shared_multi_tenants_returns_409(self):
- pass
-
- def test_update_network_set_not_shared_multi_tenants2_returns_409(self):
- pass
-
- def test_create_networks_bulk_native(self):
- pass
-
- def test_create_networks_bulk_native_quotas(self):
- pass
-
- def test_create_networks_bulk_tenants_and_quotas(self):
- pass
-
- def test_create_networks_bulk_tenants_and_quotas_fail(self):
- pass
-
- def test_create_networks_bulk_emulated(self):
- pass
-
- def test_create_networks_bulk_wrong_input(self):
- pass
-
- def test_create_networks_bulk_emulated_plugin_failure(self):
- pass
-
- def test_create_networks_bulk_native_plugin_failure(self):
- pass
-
- def test_list_networks_with_parameters(self):
- pass
-
- def test_list_networks_with_fields(self):
- pass
-
- def test_list_networks_with_parameters_invalid_values(self):
- pass
-
- def test_list_shared_networks_with_non_admin_user(self):
- pass
-
- def test_show_network_with_subnet(self):
- pass
-
- def test_invalid_admin_status(self):
- pass
-
- def test_list_networks_with_pagination_emulated(self):
- pass
-
- def test_list_networks_with_pagination_reverse_emulated(self):
- pass
-
- def test_list_networks_with_sort_emulated(self):
- pass
-
- def test_list_networks_without_pk_in_fields_pagination_emulated(self):
- pass
+ pass
class TestMidonetSubnetsV2(test_plugin.TestSubnetsV2,
MidonetPluginV2TestCase):
- def test_create_subnet(self):
- self._setup_subnet_mocks()
- super(TestMidonetSubnetsV2, self).test_create_subnet()
-
- def test_create_two_subnets(self):
- pass
-
- def test_create_two_subnets_same_cidr_returns_400(self):
- pass
-
- def test_create_subnet_bad_V4_cidr(self):
- self._setup_subnet_mocks()
- super(TestMidonetSubnetsV2, self).test_create_subnet_bad_V4_cidr()
-
- def test_create_subnet_bad_V6_cidr(self):
- self._setup_subnet_mocks()
- super(TestMidonetSubnetsV2, self).test_create_subnet_bad_V4_cidr()
-
- def test_create_2_subnets_overlapping_cidr_allowed_returns_200(self):
- pass
-
- def test_create_2_subnets_overlapping_cidr_not_allowed_returns_400(self):
- pass
-
- def test_create_subnets_bulk_native(self):
- pass
-
- def test_create_subnets_bulk_emulated(self):
- pass
-
- def test_create_subnets_bulk_emulated_plugin_failure(self):
- pass
-
- def test_create_subnets_bulk_native_plugin_failure(self):
- pass
-
- def test_delete_subnet(self):
- _bridge, subnet = self._setup_subnet_mocks()
- super(TestMidonetSubnetsV2, self).test_delete_subnet()
- subnet.delete.assert_called_once_with()
-
- def test_delete_subnet_port_exists_owned_by_network(self):
- _bridge, subnet = self._setup_subnet_mocks()
- super(TestMidonetSubnetsV2,
- self).test_delete_subnet_port_exists_owned_by_network()
-
- def test_delete_subnet_port_exists_owned_by_other(self):
- pass
-
- def test_delete_network(self):
- bridge, _subnet = self._setup_subnet_mocks()
- super(TestMidonetSubnetsV2, self).test_delete_network()
- bridge.delete.assert_called_once_with()
-
- def test_create_subnet_bad_tenant(self):
- self._setup_subnet_mocks()
- super(TestMidonetSubnetsV2, self).test_create_subnet_bad_tenant()
-
- def test_create_subnet_bad_ip_version(self):
- self._setup_subnet_mocks()
- super(TestMidonetSubnetsV2, self).test_create_subnet_bad_ip_version()
-
- def test_create_subnet_bad_ip_version_null(self):
- self._setup_subnet_mocks()
- super(TestMidonetSubnetsV2,
- self).test_create_subnet_bad_ip_version_null()
-
- def test_create_subnet_bad_uuid(self):
- self._setup_subnet_mocks()
- super(TestMidonetSubnetsV2, self).test_create_subnet_bad_uuid()
-
- def test_create_subnet_bad_boolean(self):
- self._setup_subnet_mocks()
- super(TestMidonetSubnetsV2, self).test_create_subnet_bad_boolean()
-
- def test_create_subnet_bad_pools(self):
- self._setup_subnet_mocks()
- super(TestMidonetSubnetsV2, self).test_create_subnet_bad_pools()
-
- def test_create_subnet_bad_nameserver(self):
- self._setup_subnet_mocks()
- super(TestMidonetSubnetsV2, self).test_create_subnet_bad_nameserver()
-
- def test_create_subnet_bad_hostroutes(self):
- self._setup_subnet_mocks()
- super(TestMidonetSubnetsV2, self).test_create_subnet_bad_hostroutes()
-
- def test_create_subnet_defaults(self):
- self._setup_subnet_mocks()
- super(TestMidonetSubnetsV2, self).test_create_subnet_defaults()
-
- def test_create_subnet_gw_values(self):
- self._setup_subnet_mocks()
- super(TestMidonetSubnetsV2, self).test_create_subnet_gw_values()
-
- def test_create_subnet_gw_outside_cidr_force_on_returns_400(self):
- self._setup_subnet_mocks()
- super(TestMidonetSubnetsV2,
- self).test_create_subnet_gw_outside_cidr_force_on_returns_400()
-
- def test_create_subnet_gw_of_network_force_on_returns_400(self):
- self._setup_subnet_mocks()
- super(TestMidonetSubnetsV2,
- self).test_create_subnet_gw_of_network_force_on_returns_400()
-
- def test_create_subnet_gw_bcast_force_on_returns_400(self):
- self._setup_subnet_mocks()
- super(TestMidonetSubnetsV2,
- self).test_create_subnet_gw_bcast_force_on_returns_400()
-
- def test_create_subnet_with_allocation_pool(self):
- self._setup_subnet_mocks()
- super(TestMidonetSubnetsV2,
- self).test_create_subnet_with_allocation_pool()
-
- def test_create_subnet_with_none_gateway(self):
- self._setup_subnet_mocks()
- super(TestMidonetSubnetsV2,
- self).test_create_subnet_with_none_gateway()
-
- def test_create_subnet_with_none_gateway_fully_allocated(self):
- self._setup_subnet_mocks()
- super(TestMidonetSubnetsV2,
- self).test_create_subnet_with_none_gateway_fully_allocated()
-
- def test_subnet_with_allocation_range(self):
- pass
-
- def test_create_subnet_with_none_gateway_allocation_pool(self):
- self._setup_subnet_mocks()
- super(TestMidonetSubnetsV2,
- self).test_create_subnet_with_none_gateway_allocation_pool()
-
- def test_create_subnet_with_v6_allocation_pool(self):
- pass
-
- def test_create_subnet_with_large_allocation_pool(self):
- pass
-
- def test_create_subnet_multiple_allocation_pools(self):
- pass
-
- def test_create_subnet_with_dhcp_disabled(self):
- pass
-
- def test_create_subnet_default_gw_conflict_allocation_pool_returns_409(
- self):
- pass
-
- def test_create_subnet_gateway_in_allocation_pool_returns_409(self):
- self._setup_subnet_mocks()
- super(TestMidonetSubnetsV2, self)\
- .test_create_subnet_gateway_in_allocation_pool_returns_409()
-
- def test_create_subnet_overlapping_allocation_pools_returns_409(self):
- self._setup_subnet_mocks()
- super(TestMidonetSubnetsV2, self)\
- .test_create_subnet_overlapping_allocation_pools_returns_409()
-
- def test_create_subnet_invalid_allocation_pool_returns_400(self):
- self._setup_subnet_mocks()
- super(TestMidonetSubnetsV2,
- self).test_create_subnet_invalid_allocation_pool_returns_400()
-
- def test_create_subnet_out_of_range_allocation_pool_returns_400(self):
- self._setup_subnet_mocks()
- super(TestMidonetSubnetsV2, self)\
- .test_create_subnet_out_of_range_allocation_pool_returns_400()
-
- def test_create_subnet_shared_returns_400(self):
- self._setup_subnet_mocks()
- super(TestMidonetSubnetsV2,
- self).test_create_subnet_shared_returns_400()
-
+ # IPv6 is not supported by MidoNet yet. Ignore tests that attempt to
+ # create IPv6 subnet.
def test_create_subnet_inconsistent_ipv6_cidrv4(self):
pass
- def test_create_subnet_inconsistent_ipv4_cidrv6(self):
- pass
-
- def test_create_subnet_inconsistent_ipv4_gatewayv6(self):
- pass
-
- def test_create_subnet_inconsistent_ipv6_gatewayv4(self):
- pass
-
def test_create_subnet_inconsistent_ipv6_dns_v4(self):
pass
- def test_create_subnet_inconsistent_ipv4_hostroute_dst_v6(self):
- pass
-
- def test_create_subnet_inconsistent_ipv4_hostroute_np_v6(self):
- pass
-
- def test_update_subnet(self):
- _bridge, _subnet = self._setup_subnet_mocks()
- super(TestMidonetSubnetsV2, self).test_update_subnet()
-
- def test_update_subnet_shared_returns_400(self):
- self._setup_subnet_mocks()
- super(TestMidonetSubnetsV2,
- self).test_update_subnet_shared_returns_400()
-
- def test_update_subnet_gw_outside_cidr_force_on_returns_400(self):
- pass
-
- def test_update_subnet_inconsistent_ipv4_gatewayv6(self):
+ def test_create_subnet_with_v6_allocation_pool(self):
pass
def test_update_subnet_inconsistent_ipv6_gatewayv4(self):
pass
- def test_update_subnet_inconsistent_ipv4_dns_v6(self):
- pass
-
def test_update_subnet_inconsistent_ipv6_hostroute_dst_v4(self):
pass
def test_update_subnet_inconsistent_ipv6_hostroute_np_v4(self):
pass
- def test_show_subnet(self):
- _bridge, _subnet = self._setup_subnet_mocks()
- super(TestMidonetSubnetsV2, self).test_show_subnet()
-
- def test_list_subnets(self):
+ def test_create_subnet_inconsistent_ipv6_gatewayv4(self):
pass
- def test_list_subnets_shared(self):
+ # Multiple subnets in a network is not supported by MidoNet yet. Ignore
+ # tests that attempt to create them.
+
+ def test_create_subnets_bulk_emulated(self):
pass
- def test_list_subnets_with_parameter(self):
+ def test_create_two_subnets(self):
pass
- def test_invalid_ip_version(self):
- _bridge, _subnet = self._setup_subnet_mocks()
- super(TestMidonetSubnetsV2, self).test_invalid_ip_version()
-
- def test_invalid_subnet(self):
- _bridge, _subnet = self._setup_subnet_mocks()
- super(TestMidonetSubnetsV2, self).test_invalid_subnet()
-
- def test_invalid_ip_address(self):
- _bridge, _subnet = self._setup_subnet_mocks()
- super(TestMidonetSubnetsV2, self).test_invalid_ip_address()
-
- def test_invalid_uuid(self):
- _bridge, _subnet = self._setup_subnet_mocks()
- super(TestMidonetSubnetsV2, self).test_invalid_uuid()
-
- def test_create_subnet_with_one_dns(self):
- _bridge, _subnet = self._setup_subnet_mocks()
- super(TestMidonetSubnetsV2, self).test_create_subnet_with_one_dns()
-
- def test_create_subnet_with_two_dns(self):
- _bridge, _subnet = self._setup_subnet_mocks()
- super(TestMidonetSubnetsV2, self).test_create_subnet_with_two_dns()
-
- def test_create_subnet_with_too_many_dns(self):
- _bridge, _subnet = self._setup_subnet_mocks()
- super(TestMidonetSubnetsV2,
- self).test_create_subnet_with_too_many_dns()
-
- def test_create_subnet_with_one_host_route(self):
- _bridge, _subnet = self._setup_subnet_mocks()
- super(TestMidonetSubnetsV2,
- self).test_create_subnet_with_one_host_route()
-
- def test_create_subnet_with_two_host_routes(self):
- _bridge, _subnet = self._setup_subnet_mocks()
- super(TestMidonetSubnetsV2,
- self).test_create_subnet_with_two_host_routes()
-
- def test_create_subnet_with_too_many_routes(self):
- _bridge, _subnet = self._setup_subnet_mocks()
- super(TestMidonetSubnetsV2,
- self).test_create_subnet_with_too_many_routes()
-
- def test_update_subnet_dns(self):
- _bridge, _subnet = self._setup_subnet_mocks()
- super(TestMidonetSubnetsV2, self).test_update_subnet_dns()
-
- def test_update_subnet_dns_to_None(self):
- _bridge, _subnet = self._setup_subnet_mocks()
- super(TestMidonetSubnetsV2, self).test_update_subnet_dns_to_None()
-
- def test_update_subnet_dns_with_too_many_entries(self):
- _bridge, _subnet = self._setup_subnet_mocks()
- super(TestMidonetSubnetsV2,
- self).test_update_subnet_dns_with_too_many_entries()
-
- def test_update_subnet_route(self):
- _bridge, _subnet = self._setup_subnet_mocks()
- super(TestMidonetSubnetsV2, self).test_update_subnet_route()
-
- def test_update_subnet_route_to_None(self):
- _bridge, _subnet = self._setup_subnet_mocks()
- super(TestMidonetSubnetsV2,
- self).test_update_subnet_route_to_None()
-
- def test_update_subnet_route_with_too_many_entries(self):
- _bridge, _subnet = self._setup_subnet_mocks()
- super(TestMidonetSubnetsV2,
- self).test_update_subnet_route_with_too_many_entries()
-
- def test_delete_subnet_with_dns(self):
- _bridge, subnet = self._setup_subnet_mocks()
- super(TestMidonetSubnetsV2, self).test_delete_subnet_with_dns()
- subnet.delete.assert_called_once_with()
-
- def test_delete_subnet_with_route(self):
- _bridge, subnet = self._setup_subnet_mocks()
- super(TestMidonetSubnetsV2, self).test_delete_subnet_with_route()
- subnet.delete.assert_called_once_with()
-
- def test_delete_subnet_with_dns_and_route(self):
- _bridge, subnet = self._setup_subnet_mocks()
- super(TestMidonetSubnetsV2,
- self).test_delete_subnet_with_dns_and_route()
- subnet.delete.assert_called_once_with()
-
- def test_update_subnet_gateway_in_allocation_pool_returns_409(self):
- self._setup_port_mocks()
- super(TestMidonetSubnetsV2, self)\
- .test_update_subnet_gateway_in_allocation_pool_returns_409()
-
- def test_list_subnets_with_pagination_emulated(self):
+ def test_list_subnets(self):
pass
- def test_list_subnets_with_pagination_reverse_emulated(self):
+ def test_list_subnets_with_parameter(self):
pass
- def test_list_subnets_with_sort_emulated(self):
+ def test_create_two_subnets_same_cidr_returns_400(self):
pass
class TestMidonetPortsV2(test_plugin.TestPortsV2,
MidonetPluginV2TestCase):
- def test_create_port_json(self):
- self._setup_port_mocks()
- super(TestMidonetPortsV2, self).test_create_port_json()
-
- def test_create_port_bad_tenant(self):
- self._setup_port_mocks()
- super(TestMidonetPortsV2, self).test_create_port_bad_tenant()
-
- def test_create_port_public_network(self):
- self._setup_port_mocks()
- super(TestMidonetPortsV2, self).test_create_port_public_network()
-
- def test_create_port_public_network_with_ip(self):
- self._setup_port_mocks()
- super(TestMidonetPortsV2,
- self).test_create_port_public_network_with_ip()
-
- def test_create_ports_bulk_native(self):
- pass
-
- def test_create_ports_bulk_emulated(self):
- pass
-
- def test_create_ports_bulk_wrong_input(self):
- pass
-
- def test_create_ports_bulk_emulated_plugin_failure(self):
- pass
-
- def test_create_ports_bulk_native_plugin_failure(self):
- pass
-
- def test_list_ports(self):
- pass
-
- def test_list_ports_filtered_by_fixed_ip(self):
- pass
-
- def test_list_ports_public_network(self):
- pass
-
- def test_show_port(self):
- self._setup_port_mocks()
- super(TestMidonetPortsV2, self).test_show_port()
-
- def test_delete_port(self):
- _bridge, _subnet, port, _dhcp = self._setup_port_mocks()
- super(TestMidonetPortsV2, self).test_delete_port()
- port.delete.assert_called_once_with()
-
- def test_delete_port_public_network(self):
- _bridge, _subnet, port, _dhcp = self._setup_port_mocks()
- super(TestMidonetPortsV2, self).test_delete_port_public_network()
- port.delete.assert_called_once_with()
-
- def test_update_port(self):
- self._setup_port_mocks()
- super(TestMidonetPortsV2, self).test_update_port()
-
- def test_update_device_id_null(self):
- self._setup_port_mocks()
- super(TestMidonetPortsV2, self).test_update_device_id_null()
-
- def test_delete_network_if_port_exists(self):
- self._setup_port_mocks()
- super(TestMidonetPortsV2, self).test_delete_network_if_port_exists()
-
- def test_delete_network_port_exists_owned_by_network(self):
- self._setup_port_mocks()
- super(TestMidonetPortsV2,
- self).test_delete_network_port_exists_owned_by_network()
-
- def test_update_port_delete_ip(self):
- pass
-
- def test_no_more_port_exception(self):
- pass
-
- def test_update_port_update_ip(self):
- self._setup_port_mocks()
- super(TestMidonetPortsV2, self).test_update_port_update_ip()
-
- def test_update_port_update_ip_address_only(self):
- self._setup_port_mocks()
- super(TestMidonetPortsV2,
- self).test_update_port_update_ip_address_only()
-
- def test_update_port_update_ips(self):
- self._setup_port_mocks()
- super(TestMidonetPortsV2, self).test_update_port_update_ips()
-
- def test_update_port_add_additional_ip(self):
- self._setup_port_mocks()
- super(TestMidonetPortsV2, self).test_update_port_add_additional_ip()
-
- def test_requested_duplicate_mac(self):
- self._setup_port_mocks()
- super(TestMidonetPortsV2, self).test_requested_duplicate_mac()
-
- def test_mac_generation(self):
- self._setup_port_mocks()
- super(TestMidonetPortsV2, self).test_mac_generation()
-
- def test_mac_generation_4octet(self):
- self._setup_port_mocks()
- super(TestMidonetPortsV2, self).test_mac_generation_4octet()
-
- def test_bad_mac_format(self):
- self._setup_port_mocks()
- super(TestMidonetPortsV2, self).test_bad_mac_format()
-
- def test_mac_exhaustion(self):
- self._setup_port_mocks()
- super(TestMidonetPortsV2, self).test_mac_exhaustion()
-
- def test_requested_duplicate_ip(self):
- self._setup_port_mocks()
- super(TestMidonetPortsV2, self).test_requested_duplicate_ip()
-
- def test_requested_subnet_delete(self):
- self._setup_port_mocks()
- super(TestMidonetPortsV2, self).test_requested_subnet_delete()
-
- def test_requested_subnet_id(self):
- pass
-
- def test_requested_subnet_id_not_on_network(self):
- pass
-
- def test_overlapping_subnets(self):
- pass
+ # IPv6 is not supported by MidoNet yet. Ignore tests that attempt to
+ # create IPv6 subnet.
def test_requested_subnet_id_v4_and_v6(self):
pass
- def test_range_allocation(self):
- pass
-
- def test_requested_invalid_fixed_ips(self):
- pass
-
- def test_invalid_ip(self):
- self._setup_port_mocks()
- super(TestMidonetPortsV2, self).test_invalid_ip()
-
- def test_requested_split(self):
- pass
-
- def test_duplicate_ips(self):
- self._setup_port_mocks()
- super(TestMidonetPortsV2, self).test_duplicate_ips()
-
- def test_fixed_ip_invalid_subnet_id(self):
- self._setup_port_mocks()
- super(TestMidonetPortsV2, self).test_fixed_ip_invalid_subnet_id()
-
- def test_fixed_ip_invalid_ip(self):
- self._setup_port_mocks()
- super(TestMidonetPortsV2, self).test_fixed_ip_invalid_ip()
-
- def test_requested_ips_only(self):
- pass
-
- def test_recycling(self):
- pass
-
- def test_invalid_admin_state(self):
- self._setup_port_mocks()
- super(TestMidonetPortsV2, self).test_invalid_admin_state()
-
- def test_invalid_mac_address(self):
- self._setup_port_mocks()
- super(TestMidonetPortsV2, self).test_invalid_mac_address()
-
- def test_default_allocation_expiration(self):
- self._setup_port_mocks()
- super(TestMidonetPortsV2, self).test_default_allocation_expiration()
-
- def test_update_fixed_ip_lease_expiration(self):
- self._setup_port_mocks()
- super(TestMidonetPortsV2,
- self).test_update_fixed_ip_lease_expiration()
-
- def test_port_delete_holds_ip(self):
- self._setup_port_mocks()
- super(TestMidonetPortsV2, self).test_port_delete_holds_ip()
-
- def test_update_fixed_ip_lease_expiration_invalid_address(self):
- self._setup_port_mocks()
- super(TestMidonetPortsV2,
- self).test_update_fixed_ip_lease_expiration_invalid_address()
-
- def test_hold_ip_address(self):
- self._setup_port_mocks()
- super(TestMidonetPortsV2, self).test_hold_ip_address()
-
- def test_recycle_held_ip_address(self):
- self._setup_port_mocks()
- super(TestMidonetPortsV2, self).test_recycle_held_ip_address()
-
- def test_recycle_expired_previously_run_within_context(self):
- pass
-
- def test_update_port_not_admin(self):
- self._setup_port_mocks()
- super(TestMidonetPortsV2, self).test_update_port_not_admin()
-
- def test_list_ports_with_pagination_emulated(self):
- pass
-
- def test_list_ports_with_pagination_reverse_emulated(self):
- pass
+ # Multiple subnets in a network is not supported by MidoNet yet. Ignore
+ # tests that attempt to create them.
- def test_list_ports_with_sort_emulated(self):
- pass
-
- def test_max_fixed_ips_exceeded(self):
- pass
-
- def test_update_max_fixed_ips_exceeded(self):
- pass
+ def test_overlapping_subnets(self):
+ pass