Implemented the floating ip create api method
This commit is contained in:
@@ -319,7 +319,7 @@ def ip_address_find(context, lock_mode=False, **filters):
|
|||||||
return query.filter(*model_filters)
|
return query.filter(*model_filters)
|
||||||
|
|
||||||
|
|
||||||
def ip_address_count_all(context, **filters):
|
def ip_address_count_all(context, filters):
|
||||||
query = context.session.query(sql_func.count(models.IPAddress.id))
|
query = context.session.query(sql_func.count(models.IPAddress.id))
|
||||||
model_filters = _model_query(context, models.IPAddress, filters)
|
model_filters = _model_query(context, models.IPAddress, filters)
|
||||||
return query.filter(*model_filters).scalar()
|
return query.filter(*model_filters).scalar()
|
||||||
@@ -892,3 +892,14 @@ def floating_ip_find(context, lock_mode=False, limit=None, sorts=None,
|
|||||||
|
|
||||||
return paginate_query(query.filter(*model_filters), models.IPAddress,
|
return paginate_query(query.filter(*model_filters), models.IPAddress,
|
||||||
limit, sorts, marker)
|
limit, sorts, marker)
|
||||||
|
|
||||||
|
|
||||||
|
def floating_ip_associate_fixed_ip(context, floating_ip, fixed_ip,
|
||||||
|
enable=True):
|
||||||
|
assoc = models.FloatingToFixedIPAssociation()
|
||||||
|
assoc.floating_ip_address_id = floating_ip.id
|
||||||
|
assoc.fixed_ip_address_id = fixed_ip.id
|
||||||
|
assoc.enabled = enable
|
||||||
|
context.session.add(assoc)
|
||||||
|
floating_ip.fixed_ip = fixed_ip
|
||||||
|
return floating_ip
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
"""Added Floating IP to Fixed IP mapping table
|
||||||
|
|
||||||
|
Revision ID: 33e9e23ba761
|
||||||
|
Revises: 356d6c0623c8
|
||||||
|
Create Date: 2015-05-11 14:14:23.619952
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = '33e9e23ba761'
|
||||||
|
down_revision = '356d6c0623c8'
|
||||||
|
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
op.create_table('quark_floating_to_fixed_ip_address_associations',
|
||||||
|
sa.Column('floating_ip_address_id', sa.String(length=36),
|
||||||
|
nullable=False),
|
||||||
|
sa.Column('fixed_ip_address_id', sa.String(length=36),
|
||||||
|
nullable=False),
|
||||||
|
sa.Column('enabled', sa.Boolean(), server_default='1',
|
||||||
|
nullable=False),
|
||||||
|
sa.ForeignKeyConstraint(['fixed_ip_address_id'],
|
||||||
|
['quark_ip_addresses.id'], ),
|
||||||
|
sa.ForeignKeyConstraint(['floating_ip_address_id'],
|
||||||
|
['quark_ip_addresses.id'], ),
|
||||||
|
sa.PrimaryKeyConstraint('floating_ip_address_id',
|
||||||
|
'fixed_ip_address_id'),
|
||||||
|
mysql_engine='InnoDB')
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
op.drop_table('quark_floating_to_fixed_ip_address_associations')
|
||||||
@@ -50,13 +50,17 @@ def _foreign_keys_dropped(op, table):
|
|||||||
|
|
||||||
|
|
||||||
def upgrade():
|
def upgrade():
|
||||||
op.alter_column('quark_port_ip_address_associations', 'ip_address_id',
|
metadata = sa.MetaData(bind=op.get_bind())
|
||||||
existing_type=sa.String(36), nullable=False)
|
table = sa.Table('quark_port_ip_address_associations', metadata,
|
||||||
op.alter_column('quark_port_ip_address_associations', 'port_id',
|
autoload=True)
|
||||||
existing_type=sa.String(36), nullable=False)
|
with _foreign_keys_dropped(op, table):
|
||||||
op.create_primary_key("pk_quark_port_ip_address_associations",
|
op.alter_column('quark_port_ip_address_associations', 'ip_address_id',
|
||||||
"quark_port_ip_address_associations",
|
existing_type=sa.String(36), nullable=False)
|
||||||
['port_id', 'ip_address_id'])
|
op.alter_column('quark_port_ip_address_associations', 'port_id',
|
||||||
|
existing_type=sa.String(36), nullable=False)
|
||||||
|
op.create_primary_key("pk_quark_port_ip_address_associations",
|
||||||
|
"quark_port_ip_address_associations",
|
||||||
|
['port_id', 'ip_address_id'])
|
||||||
|
|
||||||
|
|
||||||
def downgrade():
|
def downgrade():
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
356d6c0623c8
|
33e9e23ba761
|
||||||
@@ -197,6 +197,40 @@ class IPAddress(BASEV2, models.HasId):
|
|||||||
return str(ip.ipv6())
|
return str(ip.ipv6())
|
||||||
|
|
||||||
deallocated_at = sa.Column(sa.DateTime(), index=True)
|
deallocated_at = sa.Column(sa.DateTime(), index=True)
|
||||||
|
fixed_ip = None
|
||||||
|
|
||||||
|
|
||||||
|
class FloatingToFixedIPAssociation(object):
|
||||||
|
pass
|
||||||
|
|
||||||
|
flip_to_fixed_ip_assoc_tbl = sa.Table(
|
||||||
|
"quark_floating_to_fixed_ip_address_associations",
|
||||||
|
BASEV2.metadata,
|
||||||
|
sa.Column("floating_ip_address_id", sa.String(36),
|
||||||
|
sa.ForeignKey("quark_ip_addresses.id"), nullable=False,
|
||||||
|
primary_key=True),
|
||||||
|
sa.Column("fixed_ip_address_id", sa.String(36),
|
||||||
|
sa.ForeignKey("quark_ip_addresses.id"), nullable=False,
|
||||||
|
primary_key=True),
|
||||||
|
sa.Column("enabled", sa.Boolean(), default=True, nullable=False,
|
||||||
|
server_default='1'),
|
||||||
|
**TABLE_KWARGS)
|
||||||
|
|
||||||
|
orm.mapper(FloatingToFixedIPAssociation, flip_to_fixed_ip_assoc_tbl)
|
||||||
|
|
||||||
|
IPAddress.fixed_ip = orm.relationship("IPAddress",
|
||||||
|
secondary=flip_to_fixed_ip_assoc_tbl,
|
||||||
|
primaryjoin=(IPAddress.id ==
|
||||||
|
flip_to_fixed_ip_assoc_tbl
|
||||||
|
.c.floating_ip_address_id
|
||||||
|
and
|
||||||
|
flip_to_fixed_ip_assoc_tbl
|
||||||
|
.c.floating_ip_address_id ==
|
||||||
|
1),
|
||||||
|
secondaryjoin=(IPAddress.id ==
|
||||||
|
flip_to_fixed_ip_assoc_tbl
|
||||||
|
.c.fixed_ip_address_id),
|
||||||
|
uselist=False)
|
||||||
|
|
||||||
|
|
||||||
class Route(BASEV2, models.HasTenant, models.HasId, IsHazTags):
|
class Route(BASEV2, models.HasTenant, models.HasId, IsHazTags):
|
||||||
@@ -391,6 +425,7 @@ class Port(BASEV2, models.HasTenant, models.HasId):
|
|||||||
secondary=port_group_association_table,
|
secondary=port_group_association_table,
|
||||||
backref="ports")
|
backref="ports")
|
||||||
|
|
||||||
|
|
||||||
# Indices tailored specifically to get_instance_nw_info calls from nova
|
# Indices tailored specifically to get_instance_nw_info calls from nova
|
||||||
sa.Index("idx_ports_1", Port.__table__.c.device_id, Port.__table__.c.tenant_id)
|
sa.Index("idx_ports_1", Port.__table__.c.device_id, Port.__table__.c.tenant_id)
|
||||||
sa.Index("idx_ports_2", Port.__table__.c.device_owner,
|
sa.Index("idx_ports_2", Port.__table__.c.device_owner,
|
||||||
|
|||||||
@@ -17,6 +17,8 @@
|
|||||||
Unicorn driver for Quark
|
Unicorn driver for Quark
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import json
|
||||||
|
import netaddr
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
from oslo.config import cfg
|
from oslo.config import cfg
|
||||||
@@ -44,21 +46,41 @@ class UnicornDriver(object):
|
|||||||
def get_name(cls):
|
def get_name(cls):
|
||||||
return "Unicorn"
|
return "Unicorn"
|
||||||
|
|
||||||
def register_floating_ip(self, floating_ip):
|
def register_floating_ip(self, floating_ip, port, fixed_ip):
|
||||||
pass
|
url = CONF.QUARK.floating_ip_base_url
|
||||||
|
req = self._build_request_body(floating_ip, port, fixed_ip)
|
||||||
|
|
||||||
|
LOG.info("Calling unicorn to register floating ip: %s %s" % (url, req))
|
||||||
|
r = requests.post(url, data=json.dumps(req))
|
||||||
|
|
||||||
|
if r.status_code != 200:
|
||||||
|
msg = "Unexpected status from unicorn API: Status Code %s, " \
|
||||||
|
"Message: %s" % (r.status_code, r.json())
|
||||||
|
LOG.error("register_floating_ip: %s" % msg)
|
||||||
|
raise ex.RegisterFloatingIpFailure(id=floating_ip.id)
|
||||||
|
|
||||||
def update_floating_ip(self, floating_ip):
|
def update_floating_ip(self, floating_ip):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def remove_floating_ip(self, floating_ip):
|
def remove_floating_ip(self, floating_ip):
|
||||||
url = "%s/%s" % (CONF.QUARK.floating_ip_base_url,
|
url = "%s/%s" % (CONF.QUARK.floating_ip_base_url,
|
||||||
floating_ip.formatted())
|
floating_ip.address_readable)
|
||||||
|
|
||||||
LOG.info("Calling unicorn to remove floating ip: %s" % url)
|
LOG.info("Calling unicorn to remove floating ip: %s" % url)
|
||||||
r = requests.delete(url)
|
r = requests.delete(url)
|
||||||
|
|
||||||
if r.status_code != 204:
|
if r.status_code != 204:
|
||||||
msg = "Unexpected status from unicorn API: Status Code %s, " \
|
msg = "Unexpected status from unicorn API: Status Code %s, " \
|
||||||
"Message: %s" % (r.status_code,)
|
"Message: %s" % (r.status_code, r.json())
|
||||||
LOG.error("remove_floating_ip: %s" % msg)
|
LOG.error("remove_floating_ip: %s" % msg)
|
||||||
raise ex.RemoveFloatingIpFailure(id=floating_ip["id"], msg=msg)
|
raise ex.RemoveFloatingIpFailure(id=floating_ip.id)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _build_request_body(floating_ip, port, fixed_ip):
|
||||||
|
mac_addr = netaddr.EUI(port.mac_address)
|
||||||
|
content = {"public_ip": floating_ip["address_readable"],
|
||||||
|
"network_uuid": port.id,
|
||||||
|
"destinations": [
|
||||||
|
{"private_ip": fixed_ip.address_readable,
|
||||||
|
"private_mac": str(mac_addr)}]}
|
||||||
|
return {"floating_ip": content}
|
||||||
|
|||||||
@@ -140,5 +140,26 @@ class FloatingIpNotFound(exceptions.NeutronException):
|
|||||||
|
|
||||||
|
|
||||||
class RemoveFloatingIpFailure(exceptions.NeutronException):
|
class RemoveFloatingIpFailure(exceptions.NeutronException):
|
||||||
message = _("An error occured when trying to remove the floating IP %(id)."
|
message = _("An error occurred when trying to remove the "
|
||||||
" %(msg)")
|
"floating IP %(id).")
|
||||||
|
|
||||||
|
|
||||||
|
class RegisterFloatingIpFailure(exceptions.NeutronException):
|
||||||
|
message = _("An error occurred when trying to register the floating IP "
|
||||||
|
"%(id).")
|
||||||
|
|
||||||
|
|
||||||
|
class PortAlreadyContainsFloatingIp(exceptions.Conflict):
|
||||||
|
message = _("Port %(port_id) already has an associated floating IP.")
|
||||||
|
|
||||||
|
|
||||||
|
class FixedIpDoesNotExistsForPort(exceptions.BadRequest):
|
||||||
|
message = _("Fixed IP %(fixed_ip) does not exist on Port %(port_id)")
|
||||||
|
|
||||||
|
|
||||||
|
class NoAvailableFixedIPsForPort(exceptions.Conflict):
|
||||||
|
message = _("There are no available fixed IPs for port %(port_id)")
|
||||||
|
|
||||||
|
|
||||||
|
class PortDoesNotHaveAGateway(exceptions.Conflict):
|
||||||
|
message = _("Port %(port_id) does not have a gateway")
|
||||||
|
|||||||
@@ -386,7 +386,9 @@ class Plugin(neutron_plugin_base_v2.NeutronPluginBaseV2,
|
|||||||
|
|
||||||
@sessioned
|
@sessioned
|
||||||
def create_floatingip(self, context, floatingip):
|
def create_floatingip(self, context, floatingip):
|
||||||
return floating_ips.create_floatingip(context, floatingip)
|
self._fix_missing_tenant_id(context, floatingip["floatingip"])
|
||||||
|
return floating_ips.create_floatingip(context,
|
||||||
|
floatingip["floatingip"])
|
||||||
|
|
||||||
@sessioned
|
@sessioned
|
||||||
def update_floatingip(self, context, id, floatingip):
|
def update_floatingip(self, context, id, floatingip):
|
||||||
@@ -412,9 +414,8 @@ class Plugin(neutron_plugin_base_v2.NeutronPluginBaseV2,
|
|||||||
def get_routers_count(self, context, filters=None):
|
def get_routers_count(self, context, filters=None):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
@sessioned
|
|
||||||
def get_floatingips_count(self, context, filters=None):
|
def get_floatingips_count(self, context, filters=None):
|
||||||
raise floating_ips.get_floatingips_count(context, filters)
|
return floating_ips.get_floatingips_count(context, filters)
|
||||||
|
|
||||||
def get_ip_availability(self, **kwargs):
|
def get_ip_availability(self, **kwargs):
|
||||||
return ip_availability.get_ip_availability(**kwargs)
|
return ip_availability.get_ip_availability(**kwargs)
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
from neutron.common import exceptions
|
||||||
from oslo.config import cfg
|
from oslo.config import cfg
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
|
|
||||||
@@ -30,34 +31,95 @@ LOG = logging.getLogger(__name__)
|
|||||||
quark_router_opts = [
|
quark_router_opts = [
|
||||||
cfg.StrOpt('default_floating_ip_driver',
|
cfg.StrOpt('default_floating_ip_driver',
|
||||||
default='Unicorn',
|
default='Unicorn',
|
||||||
help=_('Driver for floating IP'))
|
help=_('Driver for floating IP')),
|
||||||
|
cfg.StrOpt('floating_ip_segment_name', default='floating_ip',
|
||||||
|
help=_('Segment name for floating IP subnets'))
|
||||||
]
|
]
|
||||||
|
|
||||||
CONF.register_opts(quark_router_opts, "QUARK")
|
CONF.register_opts(quark_router_opts, "QUARK")
|
||||||
|
|
||||||
|
|
||||||
def create_floatingip(context, body):
|
def create_floatingip(context, content):
|
||||||
LOG.info("create_floatingip %s for tenant %s and body %s" %
|
LOG.info("create_floatingip %s for tenant %s and body %s" %
|
||||||
(id, context.tenant_id, body))
|
(id, context.tenant_id, content))
|
||||||
|
tenant_id = content.get("tenant_id")
|
||||||
|
network_id = content.get("floating_network_id")
|
||||||
|
fixed_ip_address = content.get("fixed_ip_address")
|
||||||
|
ip_address = content.get("floating_ip_address")
|
||||||
|
port_id = content.get("port_id")
|
||||||
|
|
||||||
# floating_ip_dict = body.get("ip_address")
|
if not tenant_id:
|
||||||
# tenant_id = floating_ip_dict.get("tenant_id")
|
tenant_id = context.tenant_id
|
||||||
# network_id = floating_ip_dict.get("floating_network_id")
|
|
||||||
# # fixed_ip_address = floating_ip_dict.get("fixed_ip_address")
|
|
||||||
# # ip_address = floating_ip_dict.get("floating_ip_address")
|
|
||||||
# port_id = floating_ip_dict.get("port_id")
|
|
||||||
#
|
|
||||||
# if not tenant_id:
|
|
||||||
# raise exceptions.BadRequest(resource="floating_ip",
|
|
||||||
# msg="tenant_id is required.")
|
|
||||||
# if not network_id:
|
|
||||||
# raise exceptions.BadRequest(resource="floating_ip",
|
|
||||||
# msg="floating_network_id is required.")
|
|
||||||
# if not port_id:
|
|
||||||
# raise exceptions.BadRequest(resource="floating_ip",
|
|
||||||
# msg="port_id is required.")
|
|
||||||
|
|
||||||
raise NotImplementedError()
|
if not network_id:
|
||||||
|
raise exceptions.BadRequest(resource="floating_ip",
|
||||||
|
msg="floating_network_id is required.")
|
||||||
|
|
||||||
|
network = db_api.network_find(context, id=network_id, scope=db_api.ONE)
|
||||||
|
|
||||||
|
if not network:
|
||||||
|
raise exceptions.NetworkNotFound(net_id=network_id)
|
||||||
|
|
||||||
|
fixed_ip = None
|
||||||
|
port = None
|
||||||
|
if port_id:
|
||||||
|
port = db_api.port_find(context, id=port_id, scope=db_api.ONE)
|
||||||
|
|
||||||
|
if not port:
|
||||||
|
raise exceptions.PortNotFound(port_id=port_id)
|
||||||
|
|
||||||
|
if not port.ip_addresses or len(port.ip_addresses) == 0:
|
||||||
|
raise quark_exceptions.NoAvailableFixedIPsForPort(port_id=port_id)
|
||||||
|
|
||||||
|
if not fixed_ip_address:
|
||||||
|
fixed_ip = _get_next_available_fixed_ip(port)
|
||||||
|
if not fixed_ip:
|
||||||
|
raise quark_exceptions.NoAvailableFixedIPsForPort(
|
||||||
|
port_id=port_id)
|
||||||
|
else:
|
||||||
|
fixed_ip = next((ip for ip in port.ip_addresses
|
||||||
|
if (ip["address_readable"] == fixed_ip_address and
|
||||||
|
ip.get("address_type") == ip_types.FIXED)),
|
||||||
|
None)
|
||||||
|
|
||||||
|
if not fixed_ip:
|
||||||
|
raise quark_exceptions.FixedIpDoesNotExistsForPort(
|
||||||
|
fixed_ip=fixed_ip_address, port_id=port_id)
|
||||||
|
|
||||||
|
if any(ip for ip in port.ip_addresses
|
||||||
|
if (ip.get("address_type") == ip_types.FLOATING and
|
||||||
|
ip.fixed_ip["address_readable"] == fixed_ip_address)):
|
||||||
|
raise quark_exceptions.PortAlreadyContainsFloatingIp(
|
||||||
|
port_id=port_id)
|
||||||
|
|
||||||
|
new_addresses = []
|
||||||
|
ip_addresses = []
|
||||||
|
if ip_address:
|
||||||
|
ip_addresses.append(ip_address)
|
||||||
|
|
||||||
|
seg_name = CONF.QUARK.floating_ip_segment_name
|
||||||
|
strategy_name = network.get("ipam_strategy")
|
||||||
|
ipam_driver = ipam.IPAM_REGISTRY.get_strategy(strategy_name)
|
||||||
|
ipam_driver.allocate_ip_address(context, new_addresses, network_id,
|
||||||
|
port_id, CONF.QUARK.ipam_reuse_after,
|
||||||
|
seg_name, version=4,
|
||||||
|
ip_addresses=ip_addresses,
|
||||||
|
address_type=ip_types.FLOATING)
|
||||||
|
|
||||||
|
floating_ip = new_addresses[0]
|
||||||
|
|
||||||
|
if fixed_ip and port:
|
||||||
|
with context.session.begin():
|
||||||
|
floating_ip = db_api.floating_ip_associate_fixed_ip(context,
|
||||||
|
floating_ip,
|
||||||
|
fixed_ip)
|
||||||
|
|
||||||
|
flip_driver_type = CONF.QUARK.default_floating_ip_driver
|
||||||
|
flip_driver = registry.DRIVER_REGISTRY.get_driver(flip_driver_type)
|
||||||
|
|
||||||
|
flip_driver.register_floating_ip(floating_ip, port, fixed_ip)
|
||||||
|
|
||||||
|
return v._make_floating_ip_dict(floating_ip)
|
||||||
|
|
||||||
|
|
||||||
def update_floatingip(context, id, body):
|
def update_floatingip(context, id, body):
|
||||||
@@ -80,18 +142,19 @@ def delete_floatingip(context, id):
|
|||||||
|
|
||||||
filters = {"address_type": ip_types.FLOATING, "_deallocated": False}
|
filters = {"address_type": ip_types.FLOATING, "_deallocated": False}
|
||||||
|
|
||||||
addr = db_api.floating_ip_find(context, id=id, scope=db_api.ONE, **filters)
|
floating_ip = db_api.floating_ip_find(context, id=id, scope=db_api.ONE,
|
||||||
if not addr:
|
**filters)
|
||||||
|
if not floating_ip:
|
||||||
raise quark_exceptions.FloatingIpNotFound(id=id)
|
raise quark_exceptions.FloatingIpNotFound(id=id)
|
||||||
|
|
||||||
driver_type = CONF.QUARK.default_floating_ip_driver
|
driver_type = CONF.QUARK.default_floating_ip_driver
|
||||||
driver = registry.DRIVER_REGISTRY.get_driver(driver_type)
|
driver = registry.DRIVER_REGISTRY.get_driver(driver_type)
|
||||||
|
|
||||||
driver.remove_floating_ip(addr)
|
driver.remove_floating_ip(floating_ip)
|
||||||
|
|
||||||
strategy_name = addr.network["ipam_strategy"]
|
strategy_name = floating_ip.network.get("ipam_strategy")
|
||||||
ipam_driver = ipam.IPAM_REGISTRY.get_strategy(strategy_name)
|
ipam_driver = ipam.IPAM_REGISTRY.get_strategy(strategy_name)
|
||||||
ipam_driver.deallocate_ip_address(context, addr)
|
ipam_driver.deallocate_ip_address(context, floating_ip)
|
||||||
|
|
||||||
|
|
||||||
def get_floatingip(context, id, fields=None):
|
def get_floatingip(context, id, fields=None):
|
||||||
@@ -112,12 +175,13 @@ def get_floatingip(context, id, fields=None):
|
|||||||
|
|
||||||
filters = {"address_type": ip_types.FLOATING, "_deallocated": False}
|
filters = {"address_type": ip_types.FLOATING, "_deallocated": False}
|
||||||
|
|
||||||
addr = db_api.floating_ip_find(context, id=id, scope=db_api.ONE, **filters)
|
floating_ip = db_api.floating_ip_find(context, id=id, scope=db_api.ONE,
|
||||||
|
**filters)
|
||||||
|
|
||||||
if not addr:
|
if not floating_ip:
|
||||||
raise quark_exceptions.FloatingIpNotFound(id=id)
|
raise quark_exceptions.FloatingIpNotFound(id=id)
|
||||||
|
|
||||||
return v._make_floating_ip_dict(addr)
|
return v._make_floating_ip_dict(floating_ip)
|
||||||
|
|
||||||
|
|
||||||
def get_floatingips(context, filters=None, fields=None, sorts=None, limit=None,
|
def get_floatingips(context, filters=None, fields=None, sorts=None, limit=None,
|
||||||
@@ -150,9 +214,10 @@ def get_floatingips(context, filters=None, fields=None, sorts=None, limit=None,
|
|||||||
filters["_deallocated"] = False
|
filters["_deallocated"] = False
|
||||||
filters["address_type"] = ip_types.FLOATING
|
filters["address_type"] = ip_types.FLOATING
|
||||||
|
|
||||||
addrs = db_api.floating_ip_find(context, scope=db_api.ALL, **filters)
|
floating_ips = db_api.floating_ip_find(context, scope=db_api.ALL,
|
||||||
|
**filters)
|
||||||
|
|
||||||
return [v._make_floating_ip_dict(ip) for ip in addrs]
|
return [v._make_floating_ip_dict(flip) for flip in floating_ips]
|
||||||
|
|
||||||
|
|
||||||
def get_floatingips_count(context, filters=None):
|
def get_floatingips_count(context, filters=None):
|
||||||
@@ -174,7 +239,7 @@ def get_floatingips_count(context, filters=None):
|
|||||||
NOTE: this method is optional, as it was not part of the originally
|
NOTE: this method is optional, as it was not part of the originally
|
||||||
defined plugin API.
|
defined plugin API.
|
||||||
"""
|
"""
|
||||||
LOG.info("get_floatingips_count for tenant %s filters" %
|
LOG.info("get_floatingips_count for tenant %s filters %s" %
|
||||||
(context.tenant_id, filters))
|
(context.tenant_id, filters))
|
||||||
|
|
||||||
if filters is None:
|
if filters is None:
|
||||||
@@ -184,3 +249,20 @@ def get_floatingips_count(context, filters=None):
|
|||||||
filters["address_type"] = ip_types.FLOATING
|
filters["address_type"] = ip_types.FLOATING
|
||||||
|
|
||||||
return db_api.ip_address_count_all(context, filters)
|
return db_api.ip_address_count_all(context, filters)
|
||||||
|
|
||||||
|
|
||||||
|
def _get_next_available_fixed_ip(port):
|
||||||
|
floating_ips = [ip for ip in port.ip_addresses
|
||||||
|
if ip.get("address_type") == ip_types.FLOATING]
|
||||||
|
fixed_ips = [ip for ip in port.ip_addresses
|
||||||
|
if ip.get("address_type") == ip_types.FIXED]
|
||||||
|
|
||||||
|
if not fixed_ips or len(fixed_ips) == 0:
|
||||||
|
return None
|
||||||
|
|
||||||
|
used = [ip.fixed_ip.address for ip in floating_ips
|
||||||
|
if ip and ip.fixed_ip]
|
||||||
|
|
||||||
|
return next((ip for ip in sorted(fixed_ips,
|
||||||
|
key=lambda ip: ip.get("allocated_at"))
|
||||||
|
if ip.address not in used), None)
|
||||||
|
|||||||
@@ -188,7 +188,9 @@ def _make_port_address_dict(ip, port, fields=None):
|
|||||||
def _make_port_dict(port, fields=None):
|
def _make_port_dict(port, fields=None):
|
||||||
res = _port_dict(port)
|
res = _port_dict(port)
|
||||||
res["fixed_ips"] = [_make_port_address_dict(ip, port, fields)
|
res["fixed_ips"] = [_make_port_address_dict(ip, port, fields)
|
||||||
for ip in port.ip_addresses]
|
for ip in port.ip_addresses
|
||||||
|
if (not ip.get("address_type") or
|
||||||
|
ip.get("address_type") == ip_types.FIXED)]
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
|
||||||
@@ -196,8 +198,11 @@ def _make_ports_list(query, fields=None):
|
|||||||
ports = []
|
ports = []
|
||||||
for port in query:
|
for port in query:
|
||||||
port_dict = _port_dict(port, fields)
|
port_dict = _port_dict(port, fields)
|
||||||
port_dict["fixed_ips"] = [_make_port_address_dict(addr, port, fields)
|
port_dict["fixed_ips"] = [_make_port_address_dict(ip, port, fields)
|
||||||
for addr in port.ip_addresses]
|
for ip in port.ip_addresses
|
||||||
|
if (not ip.get("address_type") or
|
||||||
|
ip.get("address_type") == ip_types.FIXED)
|
||||||
|
]
|
||||||
ports.append(port_dict)
|
ports.append(port_dict)
|
||||||
return ports
|
return ports
|
||||||
|
|
||||||
@@ -245,27 +250,16 @@ def _make_ip_policy_dict(ipp):
|
|||||||
|
|
||||||
|
|
||||||
def _make_floating_ip_dict(flip):
|
def _make_floating_ip_dict(flip):
|
||||||
# Note(Alan Quillin) A floating IP should only be associated with a single
|
ports = flip.ports
|
||||||
# port so we need to get the first port from the list if any exist.
|
|
||||||
|
|
||||||
port_id = None
|
port_id = None
|
||||||
fixed_ip = None
|
if ports and len(ports) > 0:
|
||||||
if flip.ports and len(flip.ports) > 0:
|
port_id = None if not ports[0] else ports[0].id
|
||||||
port = flip.ports[0]
|
|
||||||
port_id = flip.ports[0].id
|
|
||||||
if port.ip_addresses and len(port.ip_addresses) > 0:
|
|
||||||
# Note(Alan Quillin) If the associated port has multiple fixed IP
|
|
||||||
# addresses, the first one found is used (based on allocated_at)
|
|
||||||
fixed_ip = next(ip.formatted() if ip else None
|
|
||||||
for ip in sorted(port.ip_addresses,
|
|
||||||
key=lambda ip:
|
|
||||||
ip.get("allocated_at"))
|
|
||||||
if ip.get("address_type") == ip_types.FIXED)
|
|
||||||
|
|
||||||
|
fixed_ip = flip.fixed_ip
|
||||||
return {"id": flip.get("id"),
|
return {"id": flip.get("id"),
|
||||||
"floating_network_id": flip.get("network_id"),
|
"floating_network_id": flip.get("network_id"),
|
||||||
"router_id": CONF.QUARK.floating_ip_router_id,
|
"router_id": CONF.QUARK.floating_ip_router_id,
|
||||||
"fixed_ip_address": fixed_ip,
|
"fixed_ip_address": None if not fixed_ip else fixed_ip.formatted(),
|
||||||
"floating_ip_address": flip.formatted(),
|
"floating_ip_address": flip.formatted(),
|
||||||
"tenant_id": flip.get("tenant_id"),
|
"tenant_id": flip.get("tenant_id"),
|
||||||
"status": flip.get("status"),
|
"status": flip.get("status"),
|
||||||
|
|||||||
@@ -15,20 +15,24 @@
|
|||||||
|
|
||||||
import contextlib
|
import contextlib
|
||||||
|
|
||||||
|
import datetime
|
||||||
import mock
|
import mock
|
||||||
|
import netaddr
|
||||||
|
from neutron.common import exceptions
|
||||||
|
|
||||||
from quark.db import models
|
from quark.db import models
|
||||||
from quark import exceptions as quark_exceptions
|
from quark import exceptions as quark_exceptions
|
||||||
|
from quark.plugin_modules import floating_ips
|
||||||
from quark.tests import test_quark_plugin
|
from quark.tests import test_quark_plugin
|
||||||
|
|
||||||
|
|
||||||
class TestRemoveFloatingIPs(test_quark_plugin.TestQuarkPlugin):
|
class TestRemoveFloatingIPs(test_quark_plugin.TestQuarkPlugin):
|
||||||
@contextlib.contextmanager
|
@contextlib.contextmanager
|
||||||
def _stubs(self, addr):
|
def _stubs(self, flip=None):
|
||||||
addr_model = None
|
flip_model = None
|
||||||
if addr:
|
if flip:
|
||||||
addr_model = models.IPAddress()
|
flip_model = models.IPAddress()
|
||||||
addr_model.update(addr)
|
flip_model.update(flip)
|
||||||
|
|
||||||
with contextlib.nested(
|
with contextlib.nested(
|
||||||
mock.patch("quark.db.api.floating_ip_find"),
|
mock.patch("quark.db.api.floating_ip_find"),
|
||||||
@@ -36,17 +40,412 @@ class TestRemoveFloatingIPs(test_quark_plugin.TestQuarkPlugin):
|
|||||||
mock.patch("quark.drivers.unicorn_driver.UnicornDriver"
|
mock.patch("quark.drivers.unicorn_driver.UnicornDriver"
|
||||||
".remove_floating_ip")
|
".remove_floating_ip")
|
||||||
) as (flip_find, mock_dealloc, mock_remove_flip):
|
) as (flip_find, mock_dealloc, mock_remove_flip):
|
||||||
flip_find.return_value = addr_model
|
flip_find.return_value = flip_model
|
||||||
yield
|
yield
|
||||||
|
|
||||||
def test_delete_floating_by_ip_address_id(self):
|
def test_delete_floating_by_ip_address_id(self):
|
||||||
addr = dict(id=1, address=3232235876, address_readable="192.168.1.100",
|
flip = dict(id=1, address=3232235876, address_readable="192.168.1.100",
|
||||||
subnet_id=1, network_id=2, version=4, used_by_tenant_id=1,
|
subnet_id=1, network_id=2, version=4, used_by_tenant_id=1,
|
||||||
network=dict(ipam_strategy="ANY"))
|
network=dict(ipam_strategy="ANY"))
|
||||||
with self._stubs(addr=addr):
|
with self._stubs(flip=flip):
|
||||||
self.plugin.delete_floatingip(self.context, 1)
|
self.plugin.delete_floatingip(self.context, 1)
|
||||||
|
|
||||||
def test_delete_floating_by_when_ip_address_does_not_exists_fails(self):
|
def test_delete_floating_by_when_ip_address_does_not_exists_fails(self):
|
||||||
with self._stubs(addr=None):
|
with self._stubs():
|
||||||
with self.assertRaises(quark_exceptions.FloatingIpNotFound):
|
with self.assertRaises(quark_exceptions.FloatingIpNotFound):
|
||||||
self.plugin.delete_floatingip(self.context, 1)
|
self.plugin.delete_floatingip(self.context, 1)
|
||||||
|
|
||||||
|
|
||||||
|
class TestFloatingIPUtilityMethods(test_quark_plugin.TestQuarkPlugin):
|
||||||
|
def test_get_next_available_fixed_ip_with_single_fixed_ip(self):
|
||||||
|
port = models.Port()
|
||||||
|
port.update(dict(id=1))
|
||||||
|
|
||||||
|
fixed_ip_addr = netaddr.IPAddress('192.168.0.1')
|
||||||
|
fixed_ip = models.IPAddress()
|
||||||
|
fixed_ip.update(dict(address_type="fixed", address=int(fixed_ip_addr),
|
||||||
|
version=4, address_readable=str(fixed_ip_addr),
|
||||||
|
allocated_at=datetime.datetime.now()))
|
||||||
|
|
||||||
|
port.ip_addresses.append(fixed_ip)
|
||||||
|
|
||||||
|
next_fixed_ip = floating_ips._get_next_available_fixed_ip(port)
|
||||||
|
|
||||||
|
self.assertEqual(next_fixed_ip["address_readable"], '192.168.0.1')
|
||||||
|
|
||||||
|
def test_get_next_available_fixed_ip_with_mult_fixed_ips(self):
|
||||||
|
port = models.Port()
|
||||||
|
port.update(dict(id=1))
|
||||||
|
|
||||||
|
for ip_addr in ["192.168.0.1", "192.168.0.2", "192.168.0.3"]:
|
||||||
|
fixed_ip_addr = netaddr.IPAddress(ip_addr)
|
||||||
|
fixed_ip = models.IPAddress()
|
||||||
|
fixed_ip.update(dict(address_type="fixed",
|
||||||
|
address=int(fixed_ip_addr),
|
||||||
|
version=4,
|
||||||
|
address_readable=str(fixed_ip_addr),
|
||||||
|
allocated_at=datetime.datetime.now()))
|
||||||
|
|
||||||
|
port.ip_addresses.append(fixed_ip)
|
||||||
|
|
||||||
|
next_fixed_ip = floating_ips._get_next_available_fixed_ip(port)
|
||||||
|
|
||||||
|
self.assertEqual(next_fixed_ip["address_readable"], '192.168.0.1')
|
||||||
|
|
||||||
|
def test_get_next_available_fixed_ip_with_no_avail_fixed_ips(self):
|
||||||
|
port = models.Port()
|
||||||
|
port.update(dict(id=1))
|
||||||
|
|
||||||
|
fixed_ip_addr = netaddr.IPAddress("192.168.0.1")
|
||||||
|
fixed_ip = models.IPAddress()
|
||||||
|
fixed_ip.update(dict(address_type="fixed",
|
||||||
|
address=int(fixed_ip_addr),
|
||||||
|
version=4,
|
||||||
|
address_readable=str(fixed_ip_addr),
|
||||||
|
allocated_at=datetime.datetime.now()))
|
||||||
|
|
||||||
|
flip_addr = netaddr.IPAddress("10.0.0.1")
|
||||||
|
flip = models.IPAddress()
|
||||||
|
flip.update(dict(address_type="floating",
|
||||||
|
address=int(flip_addr),
|
||||||
|
version=4,
|
||||||
|
address_readable=str(flip_addr),
|
||||||
|
allocated_at=datetime.datetime.now()))
|
||||||
|
flip.fixed_ip = fixed_ip
|
||||||
|
|
||||||
|
port.ip_addresses.append(fixed_ip)
|
||||||
|
port.ip_addresses.append(flip)
|
||||||
|
|
||||||
|
fixed_ip_addr = netaddr.IPAddress("192.168.0.2")
|
||||||
|
fixed_ip = models.IPAddress()
|
||||||
|
fixed_ip.update(dict(address_type="fixed",
|
||||||
|
address=int(fixed_ip_addr),
|
||||||
|
version=4,
|
||||||
|
address_readable=str(fixed_ip_addr),
|
||||||
|
allocated_at=datetime.datetime.now()))
|
||||||
|
|
||||||
|
flip_addr = netaddr.IPAddress("10.0.0.2")
|
||||||
|
flip = models.IPAddress()
|
||||||
|
flip.update(dict(address_type="floating",
|
||||||
|
address=int(flip_addr),
|
||||||
|
version=4,
|
||||||
|
address_readable=str(flip_addr),
|
||||||
|
allocated_at=datetime.datetime.now()))
|
||||||
|
flip.fixed_ip = fixed_ip
|
||||||
|
|
||||||
|
port.ip_addresses.append(fixed_ip)
|
||||||
|
port.ip_addresses.append(flip)
|
||||||
|
|
||||||
|
next_fixed_ip = floating_ips._get_next_available_fixed_ip(port)
|
||||||
|
|
||||||
|
self.assertEqual(next_fixed_ip, None)
|
||||||
|
|
||||||
|
def test_get_next_available_fixed_ip_with_avail_fixed_ips(self):
|
||||||
|
port = models.Port()
|
||||||
|
port.update(dict(id=1))
|
||||||
|
|
||||||
|
fixed_ip_addr = netaddr.IPAddress("192.168.0.1")
|
||||||
|
fixed_ip = models.IPAddress()
|
||||||
|
fixed_ip.update(dict(address_type="fixed",
|
||||||
|
address=int(fixed_ip_addr),
|
||||||
|
version=4,
|
||||||
|
address_readable=str(fixed_ip_addr),
|
||||||
|
allocated_at=datetime.datetime.now()))
|
||||||
|
|
||||||
|
flip_addr = netaddr.IPAddress("10.0.0.1")
|
||||||
|
flip = models.IPAddress()
|
||||||
|
flip.update(dict(address_type="floating",
|
||||||
|
address=int(flip_addr),
|
||||||
|
version=4,
|
||||||
|
address_readable=str(flip_addr),
|
||||||
|
allocated_at=datetime.datetime.now()))
|
||||||
|
flip.fixed_ip = fixed_ip
|
||||||
|
|
||||||
|
port.ip_addresses.append(fixed_ip)
|
||||||
|
port.ip_addresses.append(flip)
|
||||||
|
|
||||||
|
fixed_ip_addr = netaddr.IPAddress("192.168.0.2")
|
||||||
|
fixed_ip = models.IPAddress()
|
||||||
|
fixed_ip.update(dict(address_type="fixed",
|
||||||
|
address=int(fixed_ip_addr),
|
||||||
|
version=4,
|
||||||
|
address_readable=str(fixed_ip_addr),
|
||||||
|
allocated_at=datetime.datetime.now()))
|
||||||
|
|
||||||
|
port.ip_addresses.append(fixed_ip)
|
||||||
|
port.ip_addresses.append(flip)
|
||||||
|
|
||||||
|
next_fixed_ip = floating_ips._get_next_available_fixed_ip(port)
|
||||||
|
|
||||||
|
self.assertEqual(next_fixed_ip["address_readable"], "192.168.0.2")
|
||||||
|
|
||||||
|
|
||||||
|
class TestCreateFloatingIPs(test_quark_plugin.TestQuarkPlugin):
|
||||||
|
@contextlib.contextmanager
|
||||||
|
def _stubs(self, flip=None, port=None, ips=None, network=None):
|
||||||
|
port_model = None
|
||||||
|
if port:
|
||||||
|
port_model = models.Port()
|
||||||
|
port_model.update(dict(port=port))
|
||||||
|
if ips:
|
||||||
|
for ip in ips:
|
||||||
|
ip_model = models.IPAddress()
|
||||||
|
ip_model.update(ip)
|
||||||
|
if (ip["address_type"] == "floating"
|
||||||
|
and "fixed_ip_addr" in ip):
|
||||||
|
fixed_ip = models.IPAddress()
|
||||||
|
fixed_ip.update(next(ip_addr for ip_addr in ips
|
||||||
|
if (ip_addr["address_readable"] ==
|
||||||
|
ip["fixed_ip_addr"])))
|
||||||
|
ip_model.fixed_ip = fixed_ip
|
||||||
|
port_model.ip_addresses.append(ip_model)
|
||||||
|
|
||||||
|
flip_model = None
|
||||||
|
if flip:
|
||||||
|
flip_model = models.IPAddress()
|
||||||
|
flip_model.update(flip)
|
||||||
|
|
||||||
|
net_model = None
|
||||||
|
if network:
|
||||||
|
net_model = models.Network()
|
||||||
|
net_model.update(network)
|
||||||
|
|
||||||
|
def _alloc_ip(context, new_addr, net_id, port_m, *args, **kwargs):
|
||||||
|
new_addr.append(flip_model)
|
||||||
|
|
||||||
|
def _flip_fixed_ip_assoc(context, addr, fixed_ip):
|
||||||
|
addr.fixed_ip = fixed_ip
|
||||||
|
return addr
|
||||||
|
|
||||||
|
with contextlib.nested(
|
||||||
|
mock.patch("quark.db.api.floating_ip_find"),
|
||||||
|
mock.patch("quark.db.api.network_find"),
|
||||||
|
mock.patch("quark.db.api.port_find"),
|
||||||
|
mock.patch("quark.ipam.QuarkIpam.allocate_ip_address"),
|
||||||
|
mock.patch("quark.drivers.unicorn_driver.UnicornDriver"
|
||||||
|
".register_floating_ip"),
|
||||||
|
mock.patch("quark.db.api.floating_ip_associate_fixed_ip")
|
||||||
|
) as (flip_find, net_find, port_find, alloc_ip, mock_reg_flip, assoc):
|
||||||
|
flip_find.return_value = flip_model
|
||||||
|
net_find.return_value = net_model
|
||||||
|
port_find.return_value = port_model
|
||||||
|
alloc_ip.side_effect = _alloc_ip
|
||||||
|
assoc.side_effect = _flip_fixed_ip_assoc
|
||||||
|
yield
|
||||||
|
|
||||||
|
def test_create_with_a_port(self):
|
||||||
|
floating_ip_addr = netaddr.IPAddress("10.0.0.1")
|
||||||
|
floating_ip = dict(id=1, address=int(floating_ip_addr), version=4,
|
||||||
|
address_readable=str(floating_ip_addr), subnet_id=1,
|
||||||
|
network_id=2, used_by_tenant_id=1)
|
||||||
|
network = dict(id="00000000-0000-0000-0000-000000000000",
|
||||||
|
ipam_strategy="ANY")
|
||||||
|
|
||||||
|
fixed_ip_addr = netaddr.IPAddress("192.168.0.1")
|
||||||
|
fixed_ips = [dict(address_type="fixed", address=int(fixed_ip_addr),
|
||||||
|
version=4, address_readable=str(fixed_ip_addr),
|
||||||
|
allocated_at=datetime.datetime.now())]
|
||||||
|
port = dict(id="abcdefgh-1111-2222-3333-1234567890ab")
|
||||||
|
|
||||||
|
with self._stubs(flip=floating_ip, port=port,
|
||||||
|
ips=fixed_ips, network=network):
|
||||||
|
request = dict(floating_network_id=network["id"],
|
||||||
|
port_id=port["id"])
|
||||||
|
flip = self.plugin.create_floatingip(self.context,
|
||||||
|
dict(floatingip=request))
|
||||||
|
self.assertEqual(flip["floating_ip_address"], "10.0.0.1")
|
||||||
|
self.assertEqual(flip["fixed_ip_address"], "192.168.0.1")
|
||||||
|
|
||||||
|
def test_create_without_a_port(self):
|
||||||
|
floating_ip_addr = netaddr.IPAddress("10.0.0.1")
|
||||||
|
floating_ip = dict(id=1, address=int(floating_ip_addr), version=4,
|
||||||
|
address_readable=str(floating_ip_addr), subnet_id=1,
|
||||||
|
network_id=2, used_by_tenant_id=1)
|
||||||
|
network = dict(id="00000000-0000-0000-0000-000000000000",
|
||||||
|
ipam_strategy="ANY")
|
||||||
|
|
||||||
|
fixed_ip_addr = netaddr.IPAddress("192.168.0.1")
|
||||||
|
fixed_ips = [dict(address_type="fixed", address=int(fixed_ip_addr),
|
||||||
|
version=4, address_readable=str(fixed_ip_addr),
|
||||||
|
allocated_at=datetime.datetime.now())]
|
||||||
|
|
||||||
|
with self._stubs(flip=floating_ip, port=None,
|
||||||
|
ips=fixed_ips, network=network):
|
||||||
|
request = dict(floating_network_id=network["id"], port_id=None)
|
||||||
|
flip = self.plugin.create_floatingip(self.context,
|
||||||
|
dict(floatingip=request))
|
||||||
|
self.assertEqual(flip["floating_ip_address"], "10.0.0.1")
|
||||||
|
self.assertEqual(flip.get("fixed_ip_address"), None)
|
||||||
|
|
||||||
|
def test_create_with_fixed_ip_specified(self):
|
||||||
|
floating_ip_addr = netaddr.IPAddress("10.0.0.1")
|
||||||
|
floating_ip = dict(id=1, address=int(floating_ip_addr), version=4,
|
||||||
|
address_readable=str(floating_ip_addr), subnet_id=1,
|
||||||
|
network_id=2, used_by_tenant_id=1)
|
||||||
|
network = dict(id="00000000-0000-0000-0000-000000000000",
|
||||||
|
ipam_strategy="ANY")
|
||||||
|
|
||||||
|
fixed_ips = []
|
||||||
|
for ip_addr in ["192.168.0.1", "192.168.0.2"]:
|
||||||
|
fixed_ip_addr = netaddr.IPAddress(ip_addr)
|
||||||
|
fixed_ips.append(dict(address_type="fixed", version=4,
|
||||||
|
address=int(fixed_ip_addr),
|
||||||
|
address_readable=str(fixed_ip_addr),
|
||||||
|
allocated_at=datetime.datetime.now()))
|
||||||
|
|
||||||
|
port = dict(id="abcdefgh-1111-2222-3333-1234567890ab")
|
||||||
|
|
||||||
|
with self._stubs(flip=floating_ip, port=port,
|
||||||
|
ips=fixed_ips, network=network):
|
||||||
|
request = dict(floating_network_id=network["id"],
|
||||||
|
port_id=port["id"], fixed_ip_address="192.168.0.2")
|
||||||
|
flip = self.plugin.create_floatingip(self.context,
|
||||||
|
dict(floatingip=request))
|
||||||
|
self.assertEqual(flip["floating_ip_address"], "10.0.0.1")
|
||||||
|
self.assertEqual(flip["fixed_ip_address"], "192.168.0.2")
|
||||||
|
|
||||||
|
def test_create_with_floating_ip_specified(self):
|
||||||
|
floating_ip_addr = netaddr.IPAddress("10.0.0.1")
|
||||||
|
floating_ip = dict(id=1, address=int(floating_ip_addr), version=4,
|
||||||
|
address_readable=str(floating_ip_addr), subnet_id=1,
|
||||||
|
network_id=2, used_by_tenant_id=1)
|
||||||
|
network = dict(id="00000000-0000-0000-0000-000000000000",
|
||||||
|
ipam_strategy="ANY")
|
||||||
|
|
||||||
|
fixed_ip_addr = netaddr.IPAddress("192.168.0.1")
|
||||||
|
fixed_ips = [dict(address_type="fixed", address=int(fixed_ip_addr),
|
||||||
|
version=4, address_readable=str(fixed_ip_addr),
|
||||||
|
allocated_at=datetime.datetime.now())]
|
||||||
|
port = dict(id=2)
|
||||||
|
|
||||||
|
with self._stubs(flip=floating_ip, port=port,
|
||||||
|
ips=fixed_ips, network=network):
|
||||||
|
request = dict(floating_network_id=network["id"],
|
||||||
|
port_id=port["id"], floating_ip_address="10.0.0.1")
|
||||||
|
flip = self.plugin.create_floatingip(self.context,
|
||||||
|
dict(floatingip=request))
|
||||||
|
self.assertEqual(flip["floating_ip_address"], "10.0.0.1")
|
||||||
|
self.assertEqual(flip["fixed_ip_address"], "192.168.0.1")
|
||||||
|
|
||||||
|
def test_create_without_network_id_fails(self):
|
||||||
|
with self._stubs():
|
||||||
|
with self.assertRaises(exceptions.BadRequest):
|
||||||
|
request = dict(port_id=2, floating_ip_address="10.0.0.1")
|
||||||
|
self.plugin.create_floatingip(self.context,
|
||||||
|
dict(floatingip=request))
|
||||||
|
|
||||||
|
def test_create_with_invalid_network_fails(self):
|
||||||
|
with self._stubs():
|
||||||
|
with self.assertRaises(exceptions.NetworkNotFound):
|
||||||
|
request = dict(floating_network_id=123,
|
||||||
|
port_id=2, floating_ip_address="10.0.0.1")
|
||||||
|
self.plugin.create_floatingip(self.context,
|
||||||
|
dict(floatingip=request))
|
||||||
|
|
||||||
|
def test_create_with_invalid_port_fails(self):
|
||||||
|
network = dict(id="00000000-0000-0000-0000-000000000000",
|
||||||
|
ipam_strategy="ANY")
|
||||||
|
|
||||||
|
with self._stubs(network=network):
|
||||||
|
with self.assertRaises(exceptions.PortNotFound):
|
||||||
|
request = dict(floating_network_id=network["id"],
|
||||||
|
port_id=2, floating_ip_address="10.0.0.1")
|
||||||
|
self.plugin.create_floatingip(self.context,
|
||||||
|
dict(floatingip=request))
|
||||||
|
|
||||||
|
def test_create_with_invalid_fixed_ip_for_port_fails(self):
|
||||||
|
network = dict(id="00000000-0000-0000-0000-000000000000",
|
||||||
|
ipam_strategy="ANY")
|
||||||
|
|
||||||
|
fixed_ip_addr = netaddr.IPAddress("192.168.0.1")
|
||||||
|
fixed_ips = [dict(address_type="fixed", version=4,
|
||||||
|
address=int(fixed_ip_addr),
|
||||||
|
address_readable=str(fixed_ip_addr),
|
||||||
|
allocated_at=datetime.datetime.now())]
|
||||||
|
|
||||||
|
port = dict(id="abcdefgh-1111-2222-3333-1234567890ab")
|
||||||
|
|
||||||
|
with self._stubs(port=port, ips=fixed_ips, network=network):
|
||||||
|
with self.assertRaises(
|
||||||
|
quark_exceptions.FixedIpDoesNotExistsForPort):
|
||||||
|
request = dict(floating_network_id=network["id"],
|
||||||
|
port_id=port["id"],
|
||||||
|
fixed_ip_address="192.168.0.2")
|
||||||
|
flip = self.plugin.create_floatingip(self.context,
|
||||||
|
dict(floatingip=request))
|
||||||
|
self.assertEqual(flip["address_readable"], "10.0.0.1")
|
||||||
|
self.assertEqual(flip.fixed_ip["address_readable"],
|
||||||
|
"192.168.0.2")
|
||||||
|
|
||||||
|
def test_create_with_port_and_fixed_ip_with_existing_flip_fails(self):
|
||||||
|
network = dict(id="00000000-0000-0000-0000-000000000000",
|
||||||
|
ipam_strategy="ANY")
|
||||||
|
|
||||||
|
fixed_ip_addr = netaddr.IPAddress("192.168.0.1")
|
||||||
|
fixed_ip = dict(address_type="fixed", version=4,
|
||||||
|
address=int(fixed_ip_addr),
|
||||||
|
address_readable=str(fixed_ip_addr),
|
||||||
|
allocated_at=datetime.datetime.now())
|
||||||
|
|
||||||
|
floating_ip_addr = netaddr.IPAddress("10.0.0.1")
|
||||||
|
floating_ip = dict(address_type="floating", version=4,
|
||||||
|
address=int(floating_ip_addr),
|
||||||
|
address_readable=str(floating_ip_addr),
|
||||||
|
allocated_at=datetime.datetime.now(),
|
||||||
|
fixed_ip_addr="192.168.0.1")
|
||||||
|
|
||||||
|
ips = [fixed_ip, floating_ip]
|
||||||
|
|
||||||
|
port = dict(id="abcdefgh-1111-2222-3333-1234567890ab")
|
||||||
|
|
||||||
|
with self._stubs(port=port, ips=ips, network=network):
|
||||||
|
with self.assertRaises(
|
||||||
|
quark_exceptions.PortAlreadyContainsFloatingIp):
|
||||||
|
request = dict(floating_network_id=network["id"],
|
||||||
|
port_id=port["id"],
|
||||||
|
fixed_ip_address="192.168.0.1")
|
||||||
|
self.plugin.create_floatingip(self.context,
|
||||||
|
dict(floatingip=request))
|
||||||
|
|
||||||
|
def test_create_when_port_has_no_fixed_ips_fails(self):
|
||||||
|
network = dict(id="00000000-0000-0000-0000-000000000000",
|
||||||
|
ipam_strategy="ANY")
|
||||||
|
|
||||||
|
port = dict(id="abcdefgh-1111-2222-3333-1234567890ab")
|
||||||
|
|
||||||
|
with self._stubs(port=port, network=network):
|
||||||
|
with self.assertRaises(
|
||||||
|
quark_exceptions.NoAvailableFixedIPsForPort):
|
||||||
|
request = dict(floating_network_id=network["id"],
|
||||||
|
port_id=port["id"])
|
||||||
|
self.plugin.create_floatingip(self.context,
|
||||||
|
dict(floatingip=request))
|
||||||
|
|
||||||
|
def test_create_when_port_has_no_available_fixed_ips_fails(self):
|
||||||
|
network = dict(id="00000000-0000-0000-0000-000000000000",
|
||||||
|
ipam_strategy="ANY")
|
||||||
|
|
||||||
|
fixed_ip_addr = netaddr.IPAddress("192.168.0.1")
|
||||||
|
fixed_ip = dict(address_type="fixed", version=4,
|
||||||
|
address=int(fixed_ip_addr),
|
||||||
|
address_readable=str(fixed_ip_addr),
|
||||||
|
allocated_at=datetime.datetime.now())
|
||||||
|
|
||||||
|
floating_ip_addr = netaddr.IPAddress("10.0.0.1")
|
||||||
|
floating_ip = dict(address_type="floating", version=4,
|
||||||
|
address=int(floating_ip_addr),
|
||||||
|
address_readable=str(floating_ip_addr),
|
||||||
|
allocated_at=datetime.datetime.now(),
|
||||||
|
fixed_ip_addr="192.168.0.1")
|
||||||
|
|
||||||
|
ips = [fixed_ip, floating_ip]
|
||||||
|
|
||||||
|
port = dict(id="abcdefgh-1111-2222-3333-1234567890ab")
|
||||||
|
|
||||||
|
with self._stubs(port=port, ips=ips, network=network):
|
||||||
|
with self.assertRaises(
|
||||||
|
quark_exceptions.NoAvailableFixedIPsForPort):
|
||||||
|
request = dict(floating_network_id=network["id"],
|
||||||
|
port_id=port["id"])
|
||||||
|
self.plugin.create_floatingip(self.context,
|
||||||
|
dict(floatingip=request))
|
||||||
|
|||||||
@@ -1557,6 +1557,19 @@ class QuarkNewIPAddressAllocation(QuarkIpamBaseTest):
|
|||||||
self.ipam.allocate_ip_address(
|
self.ipam.allocate_ip_address(
|
||||||
self.context, [], 0, 0, 0, ip_addresses=["0.0.0.240"])
|
self.context, [], 0, 0, 0, ip_addresses=["0.0.0.240"])
|
||||||
|
|
||||||
|
def test_allocate_new_ip_address_with_floating_address_type(self):
|
||||||
|
subnet = dict(id=1, first_ip=0, last_ip=255,
|
||||||
|
cidr="0.0.0.0/24", ip_version=4,
|
||||||
|
next_auto_assign_ip=0,
|
||||||
|
ip_policy=dict(size=1, exclude=[
|
||||||
|
models.IPPolicyCIDR(cidr="0.0.0.0/32")]))
|
||||||
|
with self._stubs(subnets=[(subnet, 0)], addresses=[None, None]):
|
||||||
|
address = []
|
||||||
|
self.ipam.allocate_ip_address(self.context, address, 0, 0, 0,
|
||||||
|
version=4,
|
||||||
|
address_type='floating')
|
||||||
|
self.assertEqual(address[0]["address_type"], 'floating')
|
||||||
|
|
||||||
|
|
||||||
class QuarkIPAddressAllocationTestRetries(QuarkIpamBaseTest):
|
class QuarkIPAddressAllocationTestRetries(QuarkIpamBaseTest):
|
||||||
@contextlib.contextmanager
|
@contextlib.contextmanager
|
||||||
|
|||||||
Reference in New Issue
Block a user