Implemented get and get all methods for floating IPs

This commit is contained in:
Alan Quillin
2015-04-27 19:05:59 -05:00
parent bf8a781b81
commit 9bae3dd79c
7 changed files with 310 additions and 16 deletions

View File

@@ -323,6 +323,12 @@ def ip_address_find(context, lock_mode=False, **filters):
return query.filter(*model_filters)
def ip_address_count_all(context, **filters):
query = context.session.query(sql_func.count(models.IPAddress.id))
model_filters = _model_query(context, models.IPAddress, filters)
return query.filter(*model_filters).scalar()
@scoped
def ip_address_reallocate(context, update_kwargs, **filters):
LOG.debug("ip_address_reallocate %s", filters)
@@ -830,3 +836,29 @@ def transaction_create(context):
transaction = models.Transaction()
context.session.add(transaction)
return transaction
@scoped
def floating_ip_find(context, lock_mode=False, limit=None, sorts=None,
marker=None, page_reverse=False, fields=None, **filters):
query = context.session.query(models.IPAddress)
if lock_mode:
query = query.with_lockmode("update")
model_filters = _model_query(context, models.IPAddress, filters)
if filters.get("port_id"):
model_filters.append(models.IPAddress.ports.any(
models.Port.id == filters['port_id']))
if filters.get("address_type"):
model_filters.append(
models.IPAddress.address_type == filters['address_type'])
if filters.get("transaction_id"):
model_filters.append(
models.IPAddress.transaction_id == filters['transaction_id'])
return paginate_query(query.filter(*model_filters), models.IPAddress,
limit, sorts, marker)

View File

@@ -133,3 +133,7 @@ class RedisSlaveWritesForbidden(exceptions.NeutronException):
class NoBackendConnectionsDefined(exceptions.NeutronException):
message = _("This driver cannot be used without a backend connection "
"definition. %(msg)")
class FloatingIpNotFound(exceptions.NeutronException):
message = _("Floating IP %(id)s not found.")

View File

@@ -25,11 +25,13 @@ from oslo_log import log as logging
from quark.api import extensions
from quark import ip_availability
from quark.plugin_modules import floating_ips
from quark.plugin_modules import ip_addresses
from quark.plugin_modules import ip_policies
from quark.plugin_modules import mac_address_ranges
from quark.plugin_modules import networks
from quark.plugin_modules import ports
from quark.plugin_modules import router
from quark.plugin_modules import routes
from quark.plugin_modules import security_groups
from quark.plugin_modules import subnets
@@ -359,49 +361,60 @@ class Plugin(neutron_plugin_base_v2.NeutronPluginBaseV2,
# they're extensions in Neutron, Nova still expects to be
# able to call some of these as if they aren't
def create_router(self, context, router):
pass
raise NotImplementedError()
def update_router(self, context, id, router):
pass
raise NotImplementedError()
def get_router(self, context, id, fields=None):
pass
return router.get_router(context, id, fields)
def delete_router(self, context, id):
pass
raise NotImplementedError()
def get_routers(self, context, filters=None, fields=None,
sorts=None, limit=None, marker=None, page_reverse=False):
pass
return router.get_routers(context, filters=filters, fields=fields,
sorts=sorts, limit=limit, marker=marker,
page_reverse=page_reverse)
def add_router_interface(self, context, router_id, interface_info):
pass
raise NotImplementedError()
def remove_router_interface(self, context, router_id, interface_info):
pass
raise NotImplementedError()
@sessioned
def create_floatingip(self, context, floatingip):
pass
return floating_ips.create_floatingip(context, floatingip)
@sessioned
def update_floatingip(self, context, id, floatingip):
pass
return floating_ips.update_floatingip(context, id, floatingip)
@sessioned
def get_floatingip(self, context, id, fields=None):
return None
return floating_ips.get_floatingip(context, id, fields)
@sessioned
def delete_floatingip(self, context, id):
pass
return floating_ips.delete_floatingip(context, id)
@sessioned
def get_floatingips(self, context, filters=None, fields=None,
sorts=None, limit=None, marker=None,
page_reverse=False):
return []
return floating_ips.get_floatingips(context, filters=filters,
fields=fields, sorts=sorts,
limit=limit, marker=marker,
page_reverse=page_reverse)
def get_routers_count(self, context, filters=None):
raise NotImplementedError()
@sessioned
def get_floatingips_count(self, context, filters=None):
raise NotImplementedError()
raise floating_ips.get_floatingips_count(context, filters)
def get_ip_availability(self, **kwargs):
return ip_availability.get_ip_availability(**kwargs)

View File

@@ -0,0 +1,164 @@
# Copyright 2013 Openstack Foundation
# 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.
from oslo.config import cfg
from oslo_log import log as logging
from quark.db import api as db_api
from quark.db import ip_types
from quark import exceptions as quark_exceptions
from quark import plugin_views as v
CONF = cfg.CONF
LOG = logging.getLogger(__name__)
quark_router_opts = [
cfg.StrOpt('floating_ip_base_url',
default='http://localhost/',
help=_('floating ips base url'))
]
CONF.register_opts(quark_router_opts, "QUARK")
def create_floatingip(context, body):
LOG.info("create_floatingip %s for tenant %s and body %s" %
(id, context.tenant_id, body))
# floating_ip_dict = body.get("ip_address")
# tenant_id = floating_ip_dict.get("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()
def update_floatingip(context, id, body):
LOG.info("update_floatingip %s for tenant %s and body %s" %
(id, context.tenant_id, body))
# floating_ip_dict = body.get("ip_address")
#
# if "port_id" not in floating_ip_dict:
# raise exceptions.BadRequest(resource="floating_ip",
# msg="port_id is required.")
# port_id = floating_ip_dict.get("port_id")
raise NotImplementedError()
def delete_floatingip(context, id):
LOG.info("delete_floatingip %s for tenant %s" % (id, context.tenant_id))
raise NotImplementedError()
def get_floatingip(context, id, fields=None):
"""Retrieve a floating IP.
:param context: neutron api request context.
:param id: The UUID of the floating IP.
:param fields: a list of strings that are valid keys in a
floating IP dictionary as listed in the RESOURCE_ATTRIBUTE_MAP
object in neutron/api/v2/attributes.py. Only these fields
will be returned.
:returns: Dictionary containing details for the floating IP. If values
are declared in the fields parameter, then only those keys will be
present.
"""
LOG.info("get_floatingip %s for tenant %s" % (id, context.tenant_id))
filters = {"address_type": ip_types.FLOATING}
addr = db_api.floating_ip_find(context, id=id, scope=db_api.ONE, **filters)
if not addr:
raise quark_exceptions.FloatingIpNotFound(id=id)
return v._make_floating_ip_dict(addr)
def get_floatingips(context, filters=None, fields=None, sorts=None, limit=None,
marker=None, page_reverse=False):
"""Retrieve a list of floating ips.
:param context: neutron api request context.
:param filters: a dictionary with keys that are valid keys for
a floating ip as listed in the RESOURCE_ATTRIBUTE_MAP object
in neutron/api/v2/attributes.py. Values in this dictionary
are an iterable containing values that will be used for an exact
match comparison for that value. Each result returned by this
function will have matched one of the values for each key in
filters.
:param fields: a list of strings that are valid keys in a
floating IP dictionary as listed in the RESOURCE_ATTRIBUTE_MAP
object in neutron/api/v2/attributes.py. Only these fields
will be returned.
:returns: List of floating IPs that are accessible to the tenant who
submits the request (as indicated by the tenant id of the context)
as well as any filters.
"""
LOG.info("get_floatingips for tenant %s filters %s fields %s" %
(context.tenant_id, filters, fields))
if filters is None:
filters = {}
filters["_deallocated"] = False
filters["address_type"] = ip_types.FLOATING
addrs = db_api.floating_ip_find(context, scope=db_api.ALL, **filters)
return [v._make_floating_ip_dict(ip) for ip in addrs]
def get_floatingips_count(context, filters=None):
"""Return the number of floating IPs.
:param context: neutron api request context
:param filters: a dictionary with keys that are valid keys for
a floating IP as listed in the RESOURCE_ATTRIBUTE_MAP object
in neutron/api/v2/attributes.py. Values in this dictionary
are an iterable containing values that will be used for an exact
match comparison for that value. Each result returned by this
function will have matched one of the values for each key in
filters.
:returns: The number of floating IPs that are accessible to the tenant who
submits the request (as indicated by the tenant id of the context)
as well as any filters.
NOTE: this method is optional, as it was not part of the originally
defined plugin API.
"""
LOG.info("get_floatingips_count for tenant %s filters" %
(context.tenant_id, filters))
raise NotImplementedError()

View File

@@ -434,7 +434,7 @@ def get_ports(context, limit=None, sorts=None, marker=None, page_reverse=False,
: param context: neutron api request context
: param filters: a dictionary with keys that are valid keys for
a port as listed in the RESOURCE_ATTRIBUTE_MAP object
in neutron/api/v2/attributes.py. Values in this dictiontary
in neutron/api/v2/attributes.py. Values in this dictionary
are an iterable containing values that will be used for an exact
match comparison for that value. Each result returned by this
function will have matched one of the values for each key in
@@ -472,8 +472,8 @@ def get_ports_count(context, filters=None):
(as indicated by the context) as well as any filters.
: param context: neutron api request context
: param filters: a dictionary with keys that are valid keys for
a network as listed in the RESOURCE_ATTRIBUTE_MAP object
in neutron/api/v2/attributes.py. Values in this dictiontary
a port as listed in the RESOURCE_ATTRIBUTE_MAP object
in neutron/api/v2/attributes.py. Values in this dictionary
are an iterable containing values that will be used for an exact
match comparison for that value. Each result returned by this
function will have matched one of the values for each key in

View File

@@ -0,0 +1,52 @@
# Copyright 2013 Openstack Foundation
# 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.
from oslo.config import cfg
from oslo_log import log as logging
CONF = cfg.CONF
LOG = logging.getLogger(__name__)
quark_router_opts = [
cfg.StrOpt('floating_ip_router_id',
default='00000000-0000-0000-0000-000000000000',
help=_('floating ips default public router id'))
]
CONF.register_opts(quark_router_opts, "QUARK")
def get_router(context, id, fields):
LOG.info("get_router for %s for tenant %s fields %s" %
(context.tenant_id, fields))
if id != CONF.QUARK.floating_ip_router_id:
return None
return _get_floating_ip_default_router(context.tenant_id)
def get_routers(context, filters=None, fields=None, sorts=None, limit=None,
marker=None, page_reverse=False):
LOG.info("get_routers for tenant %s filters %s fields %s" %
(context.tenant_id, filters, fields))
return [_get_floating_ip_default_router(context.tenant_id)]
def _get_floating_ip_default_router(tenant_id):
return {"id": CONF.QUARK.floating_ip_router_id,
"status": "ACTIVE",
"tenant_id": tenant_id,
"name": "Floating IP Public Router",
"admin_state_up": True}

View File

@@ -21,6 +21,7 @@ import netaddr
from oslo.config import cfg
from oslo_log import log as logging
from quark.db import ip_types
from quark import network_strategy
from quark import protocols
@@ -241,3 +242,31 @@ def _make_ip_policy_dict(ipp):
"subnet_ids": [s["id"] for s in ipp["subnets"]],
"network_ids": [n["id"] for n in ipp["networks"]],
"exclude": [ippc["cidr"] for ippc in ipp["exclude"]]}
def _make_floating_ip_dict(flip):
# Note(Alan Quillin) A floating IP should only be associated with a single
# port so we need to get the first port from the list if any exist.
port_id = None
fixed_ip = None
if flip.ports and len(flip.ports) > 0:
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)
return {"id": flip.get("id"),
"floating_network_id": flip.get("network_id"),
"router_id": CONF.QUARK.floating_ip_router_id,
"fixed_ip_address": fixed_ip,
"floating_ip_address": flip.formatted(),
"tenant_id": flip.get("tenant_id"),
"status": flip.get("status"),
"port_id": port_id}