¡@

Home 

OpenStack Study: api_v2.py

OpenStack Index

**** CubicPower OpenStack Study ****

# vim: tabstop=4 shiftwidth=4 softtabstop=4

# Copyright 2012 Isaku Yamahata

# 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 sqlalchemy import exc as sa_exc

from sqlalchemy import func

from sqlalchemy.orm import exc as orm_exc

from neutron.common import exceptions as n_exc

import neutron.db.api as db

from neutron.db import models_v2

from neutron.db import securitygroups_db as sg_db

from neutron.extensions import securitygroup as ext_sg

from neutron import manager

from neutron.openstack.common import log as logging

from neutron.plugins.ryu.db import models_v2 as ryu_models_v2

LOG = logging.getLogger(__name__)

**** CubicPower OpenStack Study ****

def network_all_tenant_list():

    session = db.get_session()

    return session.query(models_v2.Network).all()

**** CubicPower OpenStack Study ****

def get_port_from_device(port_id):

    LOG.debug(_("get_port_from_device() called:port_id=%s"), port_id)

    session = db.get_session()

    sg_binding_port = sg_db.SecurityGroupPortBinding.port_id

    query = session.query(models_v2.Port,

                          sg_db.SecurityGroupPortBinding.security_group_id)

    query = query.outerjoin(sg_db.SecurityGroupPortBinding,

                            models_v2.Port.id == sg_binding_port)

    query = query.filter(models_v2.Port.id == port_id)

    port_and_sgs = query.all()

    if not port_and_sgs:

        return None

    port = port_and_sgs[0][0]

    plugin = manager.NeutronManager.get_plugin()

    port_dict = plugin._make_port_dict(port)

    port_dict[ext_sg.SECURITYGROUPS] = [

        sg_id for port_, sg_id in port_and_sgs if sg_id]

    port_dict['security_group_rules'] = []

    port_dict['security_group_source_groups'] = []

    port_dict['fixed_ips'] = [ip['ip_address'] for ip in port['fixed_ips']]

    return port_dict

**** CubicPower OpenStack Study ****

class TunnelKey(object):

# VLAN: 12 bits

# GRE, VXLAN: 24bits

# TODO(yamahata): STT: 64bits

_KEY_MIN_HARD = 1

_KEY_MAX_HARD = 0xffffffff

**** CubicPower OpenStack Study ****

    def __init__(self, key_min=_KEY_MIN_HARD, key_max=_KEY_MAX_HARD):

        self.key_min = key_min

        self.key_max = key_max

        if (key_min < self._KEY_MIN_HARD or key_max > self._KEY_MAX_HARD or

                key_min > key_max):

            raise ValueError(_('Invalid tunnel key options '

                               'tunnel_key_min: %(key_min)d '

                               'tunnel_key_max: %(key_max)d. '

                               'Using default value') % {'key_min': key_min,

                                                         'key_max': key_max})

**** CubicPower OpenStack Study ****

    def _last_key(self, session):

        try:

            return session.query(ryu_models_v2.TunnelKeyLast).one()

        except orm_exc.MultipleResultsFound:

            max_key = session.query(

                func.max(ryu_models_v2.TunnelKeyLast.last_key))

            if max_key > self.key_max:

                max_key = self.key_min

            session.query(ryu_models_v2.TunnelKeyLast).delete()

            last_key = ryu_models_v2.TunnelKeyLast(last_key=max_key)

        except orm_exc.NoResultFound:

            last_key = ryu_models_v2.TunnelKeyLast(last_key=self.key_min)

        session.add(last_key)

        session.flush()

        return session.query(ryu_models_v2.TunnelKeyLast).one()

**** CubicPower OpenStack Study ****

    def _find_key(self, session, last_key):

        """Try to find unused tunnel key.

        Trying to find unused tunnel key in TunnelKey table starting

        from last_key + 1.

        When all keys are used, raise sqlalchemy.orm.exc.NoResultFound

        """

        # key 0 is used for special meanings. So don't allocate 0.

        # sqlite doesn't support

        # '(select order by limit) union all (select order by limit) '

        # 'order by limit'

        # So do it manually

        # new_key = session.query("new_key").from_statement(

        #     # If last_key + 1 isn't used, it's the result

        #     'SELECT new_key '

        #     'FROM (SELECT :last_key + 1 AS new_key) q1 '

        #     'WHERE NOT EXISTS '

        #     '(SELECT 1 FROM tunnelkeys WHERE tunnel_key = :last_key + 1) '

        #

        #     'UNION ALL '

        #

        #     # if last_key + 1 used,

        #     # find the least unused key from last_key + 1

        #     '(SELECT t.tunnel_key + 1 AS new_key '

        #     'FROM tunnelkeys t '

        #     'WHERE NOT EXISTS '

        #     '(SELECT 1 FROM tunnelkeys ti '

        #     ' WHERE ti.tunnel_key = t.tunnel_key + 1) '

        #     'AND t.tunnel_key >= :last_key '

        #     'ORDER BY new_key LIMIT 1) '

        #

        #     'ORDER BY new_key LIMIT 1'

        # ).params(last_key=last_key).one()

        try:

            new_key = session.query("new_key").from_statement(

                # If last_key + 1 isn't used, it's the result

                'SELECT new_key '

                'FROM (SELECT :last_key + 1 AS new_key) q1 '

                'WHERE NOT EXISTS '

                '(SELECT 1 FROM tunnelkeys WHERE tunnel_key = :last_key + 1) '

            ).params(last_key=last_key).one()

        except orm_exc.NoResultFound:

            new_key = session.query("new_key").from_statement(

                # if last_key + 1 used,

                # find the least unused key from last_key + 1

                '(SELECT t.tunnel_key + 1 AS new_key '

                'FROM tunnelkeys t '

                'WHERE NOT EXISTS '

                '(SELECT 1 FROM tunnelkeys ti '

                ' WHERE ti.tunnel_key = t.tunnel_key + 1) '

                'AND t.tunnel_key >= :last_key '

                'ORDER BY new_key LIMIT 1) '

            ).params(last_key=last_key).one()

        new_key = new_key[0]  # the result is tuple.

        LOG.debug(_("last_key %(last_key)s new_key %(new_key)s"),

                  {'last_key': last_key, 'new_key': new_key})

        if new_key > self.key_max:

            LOG.debug(_("No key found"))

            raise orm_exc.NoResultFound()

        return new_key

**** CubicPower OpenStack Study ****

    def _allocate(self, session, network_id):

        last_key = self._last_key(session)

        try:

            new_key = self._find_key(session, last_key.last_key)

        except orm_exc.NoResultFound:

            new_key = self._find_key(session, self.key_min)

        tunnel_key = ryu_models_v2.TunnelKey(network_id=network_id,

                                             tunnel_key=new_key)

        last_key.last_key = new_key

        session.add(tunnel_key)

        return new_key

    _TRANSACTION_RETRY_MAX = 16

**** CubicPower OpenStack Study ****

    def allocate(self, session, network_id):

        count = 0

        while True:

            session.begin(subtransactions=True)

            try:

                new_key = self._allocate(session, network_id)

                session.commit()

                break

            except sa_exc.SQLAlchemyError:

                session.rollback()

            count += 1

            if count > self._TRANSACTION_RETRY_MAX:

                # if this happens too often, increase _TRANSACTION_RETRY_MAX

                LOG.warn(_("Transaction retry exhausted (%d). "

                           "Abandoned tunnel key allocation."), count)

                raise n_exc.ResourceExhausted()

        return new_key

**** CubicPower OpenStack Study ****

    def delete(self, session, network_id):

        session.query(ryu_models_v2.TunnelKey).filter_by(

            network_id=network_id).delete()

        session.flush()

**** CubicPower OpenStack Study ****

    def all_list(self):

        session = db.get_session()

        return session.query(ryu_models_v2.TunnelKey).all()

def set_port_status(session, port_id, status):

    try:

        port = session.query(models_v2.Port).filter_by(id=port_id).one()

        port['status'] = status

        session.merge(port)

        session.flush()

    except orm_exc.NoResultFound:

        raise n_exc.PortNotFound(port_id=port_id)

**** CubicPower OpenStack Study ****

def set_port_status(session, port_id, status):

    try:

        port = session.query(models_v2.Port).filter_by(id=port_id).one()

        port['status'] = status

        session.merge(port)

        session.flush()

    except orm_exc.NoResultFound:

        raise n_exc.PortNotFound(port_id=port_id)