¡@

Home 

OpenStack Study: routerrule.py

OpenStack Index

**** CubicPower OpenStack Study ****

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

# Copyright 2013 Big Switch Networks, Inc.

# 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: Kevin Benton, Big Switch Networks, Inc.

from neutron.api.v2 import attributes as attr

from neutron.common import exceptions as qexception

from neutron.openstack.common import log as logging

LOG = logging.getLogger(__name__)

# Router Rules Exceptions

**** CubicPower OpenStack Study ****

class InvalidRouterRules(qexception.InvalidInput):

message = _("Invalid format for router rules: %(rule)s, %(reason)s")

**** CubicPower OpenStack Study ****

class RulesExhausted(qexception.BadRequest):

message = _("Unable to complete rules update for %(router_id)s. "

"The number of rules exceeds the maximum %(quota)s.")

**** CubicPower OpenStack Study ****

def convert_to_valid_router_rules(data):

    """

    Validates and converts router rules to the appropriate data structure

    Example argument = [{'source': 'any', 'destination': 'any',

                         'action':'deny'},

                        {'source': '1.1.1.1/32', 'destination': 'external',

                         'action':'permit',

                         'nexthops': ['1.1.1.254', '1.1.1.253']}

                       ]

    """

    V4ANY = '0.0.0.0/0'

    CIDRALL = ['any', 'external']

    if not isinstance(data, list):

        emsg = _("Invalid data format for router rule: '%s'") % data

        LOG.debug(emsg)

        raise qexception.InvalidInput(error_message=emsg)

    _validate_uniquerules(data)

    rules = []

    expected_keys = ['source', 'destination', 'action']

    for rule in data:

        rule['nexthops'] = rule.get('nexthops', [])

        if not isinstance(rule['nexthops'], list):

            rule['nexthops'] = rule['nexthops'].split('+')

        src = V4ANY if rule['source'] in CIDRALL else rule['source']

        dst = V4ANY if rule['destination'] in CIDRALL else rule['destination']

        errors = [attr._verify_dict_keys(expected_keys, rule, False),

                  attr._validate_subnet(dst),

                  attr._validate_subnet(src),

                  _validate_nexthops(rule['nexthops']),

                  _validate_action(rule['action'])]

        errors = [m for m in errors if m]

        if errors:

            LOG.debug(errors)

            raise qexception.InvalidInput(error_message=errors)

        rules.append(rule)

    return rules

**** CubicPower OpenStack Study ****

def _validate_nexthops(nexthops):

    seen = []

    for ip in nexthops:

        msg = attr._validate_ip_address(ip)

        if ip in seen:

            msg = _("Duplicate nexthop in rule '%s'") % ip

        seen.append(ip)

        if msg:

            return msg

**** CubicPower OpenStack Study ****

def _validate_action(action):

    if action not in ['permit', 'deny']:

        return _("Action must be either permit or deny."

                 " '%s' was provided") % action

**** CubicPower OpenStack Study ****

def _validate_uniquerules(rules):

    pairs = []

    for r in rules:

        if 'source' not in r or 'destination' not in r:

            continue

        pairs.append((r['source'], r['destination']))

    if len(set(pairs)) != len(pairs):

        error = _("Duplicate router rules (src,dst)  found '%s'") % pairs

        LOG.debug(error)

        raise qexception.InvalidInput(error_message=error)

**** CubicPower OpenStack Study ****

class Routerrule(object):

@classmethod

**** CubicPower OpenStack Study ****

    def get_name(cls):

        return "Neutron Router Rule"

    @classmethod

**** CubicPower OpenStack Study ****

    def get_alias(cls):

        return "router_rules"

    @classmethod

**** CubicPower OpenStack Study ****

    def get_description(cls):

        return "Router rule configuration for L3 router"

    @classmethod

**** CubicPower OpenStack Study ****

    def get_namespace(cls):

        return "http://docs.openstack.org/ext/neutron/routerrules/api/v1.0"

    @classmethod

**** CubicPower OpenStack Study ****

    def get_updated(cls):

        return "2013-05-23T10:00:00-00:00"

**** CubicPower OpenStack Study ****

    def get_extended_resources(self, version):

        if version == "2.0":

            return EXTENDED_ATTRIBUTES_2_0

        else:

            return {}

# Attribute Map

EXTENDED_ATTRIBUTES_2_0 = {

    'routers': {

        'router_rules': {'allow_post': False, 'allow_put': True,

                         'convert_to': convert_to_valid_router_rules,

                         'is_visible': True,

                         'default': attr.ATTR_NOT_SPECIFIED},

    }

}