¡@

Home 

OpenStack Study: router.py

OpenStack Index

**** CubicPower OpenStack Study ****

def _prepare_lrouter_body(name, neutron_router_id, tenant_id,

                          router_type, distributed=None, **kwargs):

    body = {

        "display_name": utils.check_and_truncate(name),

        "tags": utils.get_tags(os_tid=tenant_id,

                               q_router_id=neutron_router_id),

        "routing_config": {

            "type": router_type

        },

        "type": "LogicalRouterConfig",

        "replication_mode": cfg.CONF.NSX.replication_mode,

    }

    # add the distributed key only if not None (ie: True or False)

    if distributed is not None:

        body['distributed'] = distributed

    if kwargs:

        body["routing_config"].update(kwargs)

    return body

**** CubicPower OpenStack Study ****

def _create_implicit_routing_lrouter(cluster, neutron_router_id, tenant_id,

                                     display_name, nexthop, distributed=None):

    implicit_routing_config = {

        "default_route_next_hop": {

            "gateway_ip_address": nexthop,

            "type": "RouterNextHop"

        },

    }

    lrouter_obj = _prepare_lrouter_body(

        display_name, neutron_router_id, tenant_id,

        "SingleDefaultRouteImplicitRoutingConfig",

        distributed=distributed,

        **implicit_routing_config)

    return do_request(HTTP_POST, _build_uri_path(LROUTER_RESOURCE),

                      jsonutils.dumps(lrouter_obj), cluster=cluster)

**** CubicPower OpenStack Study ****

def create_implicit_routing_lrouter(cluster, neutron_router_id, tenant_id,

                                    display_name, nexthop):

    """Create a NSX logical router on the specified cluster.

        :param cluster: The target NSX cluster

        :param tenant_id: Identifier of the Openstack tenant for which

        the logical router is being created

        :param display_name: Descriptive name of this logical router

        :param nexthop: External gateway IP address for the logical router

        :raise NsxApiException: if there is a problem while communicating

        with the NSX controller

    """

    return _create_implicit_routing_lrouter(

        cluster, neutron_router_id, tenant_id, display_name, nexthop)

**** CubicPower OpenStack Study ****

def create_implicit_routing_lrouter_with_distribution(

    cluster, neutron_router_id, tenant_id, display_name,

    nexthop, distributed=None):

    """Create a NSX logical router on the specified cluster.

    This function also allows for creating distributed lrouters

    :param cluster: The target NSX cluster

    :param tenant_id: Identifier of the Openstack tenant for which

    the logical router is being created

    :param display_name: Descriptive name of this logical router

    :param nexthop: External gateway IP address for the logical router

    :param distributed: True for distributed logical routers

    :raise NsxApiException: if there is a problem while communicating

    with the NSX controller

    """

    return _create_implicit_routing_lrouter(

        cluster, neutron_router_id, tenant_id,

        display_name, nexthop, distributed)

**** CubicPower OpenStack Study ****

def create_explicit_routing_lrouter(cluster, neutron_router_id, tenant_id,

                                    display_name, nexthop, distributed=None):

    lrouter_obj = _prepare_lrouter_body(

        display_name, neutron_router_id, tenant_id,

        "RoutingTableRoutingConfig", distributed=distributed)

    router = do_request(HTTP_POST, _build_uri_path(LROUTER_RESOURCE),

                        jsonutils.dumps(lrouter_obj), cluster=cluster)

    default_gw = {'prefix': '0.0.0.0/0', 'next_hop_ip': nexthop}

    create_explicit_route_lrouter(cluster, router['uuid'], default_gw)

    return router

**** CubicPower OpenStack Study ****

def delete_lrouter(cluster, lrouter_id):

    do_request(HTTP_DELETE, _build_uri_path(LROUTER_RESOURCE,

                                            resource_id=lrouter_id),

               cluster=cluster)

**** CubicPower OpenStack Study ****

def get_lrouter(cluster, lrouter_id):

    return do_request(HTTP_GET,

                      _build_uri_path(LROUTER_RESOURCE,

                                      resource_id=lrouter_id,

                                      relations='LogicalRouterStatus'),

                      cluster=cluster)

**** CubicPower OpenStack Study ****

def query_lrouters(cluster, fields=None, filters=None):

    return get_all_query_pages(

        _build_uri_path(LROUTER_RESOURCE,

                        fields=fields,

                        relations='LogicalRouterStatus',

                        filters=filters),

        cluster)

**** CubicPower OpenStack Study ****

def get_lrouters(cluster, tenant_id, fields=None, filters=None):

    # FIXME(salv-orlando): Fields parameter is ignored in this routine

    actual_filters = {}

    if filters:

        actual_filters.update(filters)

    if tenant_id:

        actual_filters['tag'] = tenant_id

        actual_filters['tag_scope'] = 'os_tid'

    lrouter_fields = "uuid,display_name,fabric_status,tags"

    return query_lrouters(cluster, lrouter_fields, actual_filters)

**** CubicPower OpenStack Study ****

def update_implicit_routing_lrouter(cluster, r_id, display_name, nexthop):

    lrouter_obj = get_lrouter(cluster, r_id)

    if not display_name and not nexthop:

        # Nothing to update

        return lrouter_obj

    # It seems that this is faster than the doing an if on display_name

    lrouter_obj["display_name"] = (utils.check_and_truncate(display_name) or

                                   lrouter_obj["display_name"])

    if nexthop:

        nh_element = lrouter_obj["routing_config"].get(

            "default_route_next_hop")

        if nh_element:

            nh_element["gateway_ip_address"] = nexthop

    return do_request(HTTP_PUT, _build_uri_path(LROUTER_RESOURCE,

                                                resource_id=r_id),

                      jsonutils.dumps(lrouter_obj),

                      cluster=cluster)

**** CubicPower OpenStack Study ****

def get_explicit_routes_lrouter(cluster, router_id, protocol_type='static'):

    static_filter = {'protocol': protocol_type}

    existing_routes = do_request(

        HTTP_GET,

        _build_uri_path(LROUTERRIB_RESOURCE,

                        filters=static_filter,

                        fields="*",

                        parent_resource_id=router_id),

        cluster=cluster)['results']

    return existing_routes

**** CubicPower OpenStack Study ****

def delete_explicit_route_lrouter(cluster, router_id, route_id):

    do_request(HTTP_DELETE,

               _build_uri_path(LROUTERRIB_RESOURCE,

                               resource_id=route_id,

                               parent_resource_id=router_id),

               cluster=cluster)

**** CubicPower OpenStack Study ****

def create_explicit_route_lrouter(cluster, router_id, route):

    next_hop_ip = route.get("nexthop") or route.get("next_hop_ip")

    prefix = route.get("destination") or route.get("prefix")

    uuid = do_request(

        HTTP_POST,

        _build_uri_path(LROUTERRIB_RESOURCE,

                        parent_resource_id=router_id),

        jsonutils.dumps({

            "action": "accept",

            "next_hop_ip": next_hop_ip,

            "prefix": prefix,

            "protocol": "static"

        }),

        cluster=cluster)['uuid']

    return uuid

**** CubicPower OpenStack Study ****

def update_explicit_routes_lrouter(cluster, router_id, routes):

    # Update in bulk: delete them all, and add the ones specified

    # but keep track of what is been modified to allow roll-backs

    # in case of failures

    nsx_routes = get_explicit_routes_lrouter(cluster, router_id)

    try:

        deleted_routes = []

        added_routes = []

        # omit the default route (0.0.0.0/0) from the processing;

        # this must be handled through the nexthop for the router

        for route in nsx_routes:

            prefix = route.get("destination") or route.get("prefix")

            if prefix != '0.0.0.0/0':

                delete_explicit_route_lrouter(cluster,

                                              router_id,

                                              route['uuid'])

                deleted_routes.append(route)

        for route in routes:

            prefix = route.get("destination") or route.get("prefix")

            if prefix != '0.0.0.0/0':

                uuid = create_explicit_route_lrouter(cluster,

                                                     router_id, route)

                added_routes.append(uuid)

    except api_exc.NsxApiException:

        LOG.exception(_('Cannot update NSX routes %(routes)s for '

                        'router %(router_id)s'),

                      {'routes': routes, 'router_id': router_id})

        # Roll back to keep NSX in consistent state

        with excutils.save_and_reraise_exception():

            if nsx_routes:

                if deleted_routes:

                    for route in deleted_routes:

                        create_explicit_route_lrouter(cluster,

                                                      router_id, route)

                if added_routes:

                    for route_id in added_routes:

                        delete_explicit_route_lrouter(cluster,

                                                      router_id, route_id)

    return nsx_routes

**** CubicPower OpenStack Study ****

def get_default_route_explicit_routing_lrouter_v33(cluster, router_id):

    static_filter = {"protocol": "static",

                     "prefix": "0.0.0.0/0"}

    default_route = do_request(

        HTTP_GET,

        _build_uri_path(LROUTERRIB_RESOURCE,

                        filters=static_filter,

                        fields="*",

                        parent_resource_id=router_id),

        cluster=cluster)["results"][0]

    return default_route

**** CubicPower OpenStack Study ****

def get_default_route_explicit_routing_lrouter_v32(cluster, router_id):

    # Scan all routes because 3.2 does not support query by prefix

    all_routes = get_explicit_routes_lrouter(cluster, router_id)

    for route in all_routes:

        if route['prefix'] == '0.0.0.0/0':

            return route

**** CubicPower OpenStack Study ****

def update_default_gw_explicit_routing_lrouter(cluster, router_id, next_hop):

    default_route = get_default_route_explicit_routing_lrouter(cluster,

                                                               router_id)

    if next_hop != default_route["next_hop_ip"]:

        new_default_route = {"action": "accept",

                             "next_hop_ip": next_hop,

                             "prefix": "0.0.0.0/0",

                             "protocol": "static"}

        do_request(HTTP_PUT,

                   _build_uri_path(LROUTERRIB_RESOURCE,

                                   resource_id=default_route['uuid'],

                                   parent_resource_id=router_id),

                   jsonutils.dumps(new_default_route),

                   cluster=cluster)

**** CubicPower OpenStack Study ****

def update_explicit_routing_lrouter(cluster, router_id,

                                    display_name, next_hop, routes=None):

    update_implicit_routing_lrouter(cluster, router_id, display_name, next_hop)

    if next_hop:

        update_default_gw_explicit_routing_lrouter(cluster,

                                                   router_id, next_hop)

    if routes is not None:

        return update_explicit_routes_lrouter(cluster, router_id, routes)

**** CubicPower OpenStack Study ****

def query_lrouter_lports(cluster, lr_uuid, fields="*",

                         filters=None, relations=None):

    uri = _build_uri_path(LROUTERPORT_RESOURCE, parent_resource_id=lr_uuid,

                          fields=fields, filters=filters, relations=relations)

    return do_request(HTTP_GET, uri, cluster=cluster)['results']

**** CubicPower OpenStack Study ****

def create_router_lport(cluster, lrouter_uuid, tenant_id, neutron_port_id,

                        display_name, admin_status_enabled, ip_addresses,

                        mac_address=None):

    """Creates a logical port on the assigned logical router."""

    lport_obj = dict(

        admin_status_enabled=admin_status_enabled,

        display_name=display_name,

        tags=utils.get_tags(os_tid=tenant_id, q_port_id=neutron_port_id),

        ip_addresses=ip_addresses,

        type="LogicalRouterPortConfig"

    )

    # Only add the mac_address to lport_obj if present. This is because

    # when creating the fake_ext_gw there is no mac_address present.

    if mac_address:

        lport_obj['mac_address'] = mac_address

    path = _build_uri_path(LROUTERPORT_RESOURCE,

                           parent_resource_id=lrouter_uuid)

    result = do_request(HTTP_POST, path, jsonutils.dumps(lport_obj),

                        cluster=cluster)

    LOG.debug(_("Created logical port %(lport_uuid)s on "

                "logical router %(lrouter_uuid)s"),

              {'lport_uuid': result['uuid'],

               'lrouter_uuid': lrouter_uuid})

    return result

**** CubicPower OpenStack Study ****

def update_router_lport(cluster, lrouter_uuid, lrouter_port_uuid,

                        tenant_id, neutron_port_id, display_name,

                        admin_status_enabled, ip_addresses):

    """Updates a logical port on the assigned logical router."""

    lport_obj = dict(

        admin_status_enabled=admin_status_enabled,

        display_name=display_name,

        tags=utils.get_tags(os_tid=tenant_id, q_port_id=neutron_port_id),

        ip_addresses=ip_addresses,

        type="LogicalRouterPortConfig"

    )

    # Do not pass null items to NSX

    for key in lport_obj.keys():

        if lport_obj[key] is None:

            del lport_obj[key]

    path = _build_uri_path(LROUTERPORT_RESOURCE,

                           lrouter_port_uuid,

                           parent_resource_id=lrouter_uuid)

    result = do_request(HTTP_PUT, path,

                        jsonutils.dumps(lport_obj),

                        cluster=cluster)

    LOG.debug(_("Updated logical port %(lport_uuid)s on "

                "logical router %(lrouter_uuid)s"),

              {'lport_uuid': lrouter_port_uuid, 'lrouter_uuid': lrouter_uuid})

    return result

**** CubicPower OpenStack Study ****

def delete_router_lport(cluster, lrouter_uuid, lport_uuid):

    """Creates a logical port on the assigned logical router."""

    path = _build_uri_path(LROUTERPORT_RESOURCE, lport_uuid, lrouter_uuid)

    do_request(HTTP_DELETE, path, cluster=cluster)

    LOG.debug(_("Delete logical router port %(lport_uuid)s on "

                "logical router %(lrouter_uuid)s"),

              {'lport_uuid': lport_uuid,

               'lrouter_uuid': lrouter_uuid})

**** CubicPower OpenStack Study ****

def delete_peer_router_lport(cluster, lr_uuid, ls_uuid, lp_uuid):

    nsx_port = get_port(cluster, ls_uuid, lp_uuid,

                        relations="LogicalPortAttachment")

    relations = nsx_port.get('_relations')

    if relations:

        att_data = relations.get('LogicalPortAttachment')

        if att_data:

            lrp_uuid = att_data.get('peer_port_uuid')

            if lrp_uuid:

                delete_router_lport(cluster, lr_uuid, lrp_uuid)

**** CubicPower OpenStack Study ****

def find_router_gw_port(context, cluster, router_id):

    """Retrieves the external gateway port for a NSX logical router."""

    # Find the uuid of nsx ext gw logical router port

    # TODO(salvatore-orlando): Consider storing it in Neutron DB

    results = query_lrouter_lports(

        cluster, router_id,

        relations="LogicalPortAttachment")

    for lport in results:

        if '_relations' in lport:

            attachment = lport['_relations'].get('LogicalPortAttachment')

            if attachment and attachment.get('type') == 'L3GatewayAttachment':

                return lport

**** CubicPower OpenStack Study ****

def plug_router_port_attachment(cluster, router_id, port_id,

                                attachment_uuid, nsx_attachment_type,

                                attachment_vlan=None):

    """Attach a router port to the given attachment.

    Current attachment types:

       - PatchAttachment [-> logical switch port uuid]

       - L3GatewayAttachment [-> L3GatewayService uuid]

    For the latter attachment type a VLAN ID can be specified as well.

    """

    uri = _build_uri_path(LROUTERPORT_RESOURCE, port_id, router_id,

                          is_attachment=True)

    attach_obj = {}

    attach_obj["type"] = nsx_attachment_type

    if nsx_attachment_type == "PatchAttachment":

        attach_obj["peer_port_uuid"] = attachment_uuid

    elif nsx_attachment_type == "L3GatewayAttachment":

        attach_obj["l3_gateway_service_uuid"] = attachment_uuid

        if attachment_vlan:

            attach_obj['vlan_id'] = attachment_vlan

    else:

        raise nsx_exc.InvalidAttachmentType(

            attachment_type=nsx_attachment_type)

    return do_request(

        HTTP_PUT, uri, jsonutils.dumps(attach_obj), cluster=cluster)

**** CubicPower OpenStack Study ****

def _create_nat_match_obj(**kwargs):

    nat_match_obj = {'ethertype': 'IPv4'}

    delta = set(kwargs.keys()) - set(MATCH_KEYS)

    if delta:

        raise Exception(_("Invalid keys for NAT match: %s"), delta)

    nat_match_obj.update(kwargs)

    return nat_match_obj

**** CubicPower OpenStack Study ****

def _create_lrouter_nat_rule(cluster, router_id, nat_rule_obj):

    LOG.debug(_("Creating NAT rule: %s"), nat_rule_obj)

    uri = _build_uri_path(LROUTERNAT_RESOURCE, parent_resource_id=router_id)

    return do_request(HTTP_POST, uri, jsonutils.dumps(nat_rule_obj),

                      cluster=cluster)

**** CubicPower OpenStack Study ****

def _build_snat_rule_obj(min_src_ip, max_src_ip, nat_match_obj):

    return {"to_source_ip_address_min": min_src_ip,

            "to_source_ip_address_max": max_src_ip,

            "type": "SourceNatRule",

            "match": nat_match_obj}

**** CubicPower OpenStack Study ****

def create_lrouter_nosnat_rule_v2(cluster, _router_id, _match_criteria=None):

    LOG.info(_("No SNAT rules cannot be applied as they are not available in "

               "this version of the NSX platform"))

**** CubicPower OpenStack Study ****

def create_lrouter_nodnat_rule_v2(cluster, _router_id, _match_criteria=None):

    LOG.info(_("No DNAT rules cannot be applied as they are not available in "

               "this version of the NSX platform"))

**** CubicPower OpenStack Study ****

def create_lrouter_snat_rule_v2(cluster, router_id,

                                min_src_ip, max_src_ip, match_criteria=None):

    nat_match_obj = _create_nat_match_obj(**match_criteria)

    nat_rule_obj = _build_snat_rule_obj(min_src_ip, max_src_ip, nat_match_obj)

    return _create_lrouter_nat_rule(cluster, router_id, nat_rule_obj)

**** CubicPower OpenStack Study ****

def create_lrouter_dnat_rule_v2(cluster, router_id, dst_ip,

                                to_dst_port=None, match_criteria=None):

    nat_match_obj = _create_nat_match_obj(**match_criteria)

    nat_rule_obj = {

        "to_destination_ip_address_min": dst_ip,

        "to_destination_ip_address_max": dst_ip,

        "type": "DestinationNatRule",

        "match": nat_match_obj

    }

    if to_dst_port:

        nat_rule_obj['to_destination_port'] = to_dst_port

    return _create_lrouter_nat_rule(cluster, router_id, nat_rule_obj)

**** CubicPower OpenStack Study ****

def create_lrouter_nosnat_rule_v3(cluster, router_id, order=None,

                                  match_criteria=None):

    nat_match_obj = _create_nat_match_obj(**match_criteria)

    nat_rule_obj = {

        "type": "NoSourceNatRule",

        "match": nat_match_obj

    }

    if order:

        nat_rule_obj['order'] = order

    return _create_lrouter_nat_rule(cluster, router_id, nat_rule_obj)

**** CubicPower OpenStack Study ****

def create_lrouter_nodnat_rule_v3(cluster, router_id, order=None,

                                  match_criteria=None):

    nat_match_obj = _create_nat_match_obj(**match_criteria)

    nat_rule_obj = {

        "type": "NoDestinationNatRule",

        "match": nat_match_obj

    }

    if order:

        nat_rule_obj['order'] = order

    return _create_lrouter_nat_rule(cluster, router_id, nat_rule_obj)

**** CubicPower OpenStack Study ****

def create_lrouter_snat_rule_v3(cluster, router_id, min_src_ip, max_src_ip,

                                order=None, match_criteria=None):

    nat_match_obj = _create_nat_match_obj(**match_criteria)

    nat_rule_obj = _build_snat_rule_obj(min_src_ip, max_src_ip, nat_match_obj)

    if order:

        nat_rule_obj['order'] = order

    return _create_lrouter_nat_rule(cluster, router_id, nat_rule_obj)

**** CubicPower OpenStack Study ****

def create_lrouter_dnat_rule_v3(cluster, router_id, dst_ip, to_dst_port=None,

                                order=None, match_criteria=None):

    nat_match_obj = _create_nat_match_obj(**match_criteria)

    nat_rule_obj = {

        "to_destination_ip_address": dst_ip,

        "type": "DestinationNatRule",

        "match": nat_match_obj

    }

    if to_dst_port:

        nat_rule_obj['to_destination_port'] = to_dst_port

    if order:

        nat_rule_obj['order'] = order

    return _create_lrouter_nat_rule(cluster, router_id, nat_rule_obj)

**** CubicPower OpenStack Study ****

def delete_nat_rules_by_match(cluster, router_id, rule_type,

                              max_num_expected,

                              min_num_expected=0,

                              **kwargs):

    # remove nat rules

    nat_rules = query_nat_rules(cluster, router_id)

    to_delete_ids = []

    for r in nat_rules:

        if (r['type'] != rule_type):

            continue

        for key, value in kwargs.iteritems():

            if not (key in r['match'] and r['match'][key] == value):

                break

        else:

            to_delete_ids.append(r['uuid'])

    if not (len(to_delete_ids) in

            range(min_num_expected, max_num_expected + 1)):

        raise nsx_exc.NatRuleMismatch(actual_rules=len(to_delete_ids),

                                      min_rules=min_num_expected,

                                      max_rules=max_num_expected)

    for rule_id in to_delete_ids:

        delete_router_nat_rule(cluster, router_id, rule_id)

**** CubicPower OpenStack Study ****

def delete_router_nat_rule(cluster, router_id, rule_id):

    uri = _build_uri_path(LROUTERNAT_RESOURCE, rule_id, router_id)

    do_request(HTTP_DELETE, uri, cluster=cluster)

**** CubicPower OpenStack Study ****

def query_nat_rules(cluster, router_id, fields="*", filters=None):

    uri = _build_uri_path(LROUTERNAT_RESOURCE, parent_resource_id=router_id,

                          fields=fields, filters=filters)

    return get_all_query_pages(uri, cluster)

# NOTE(salvatore-orlando): The following FIXME applies in general to

# each operation on list attributes.

# FIXME(salvatore-orlando): need a lock around the list of IPs on an iface

**** CubicPower OpenStack Study ****

def update_lrouter_port_ips(cluster, lrouter_id, lport_id,

                            ips_to_add, ips_to_remove):

    uri = _build_uri_path(LROUTERPORT_RESOURCE, lport_id, lrouter_id)

    try:

        port = do_request(HTTP_GET, uri, cluster=cluster)

        # TODO(salvatore-orlando): Enforce ips_to_add intersection with

        # ips_to_remove is empty

        ip_address_set = set(port['ip_addresses'])

        ip_address_set = ip_address_set - set(ips_to_remove)

        ip_address_set = ip_address_set | set(ips_to_add)

        # Set is not JSON serializable - convert to list

        port['ip_addresses'] = list(ip_address_set)

        do_request(HTTP_PUT, uri, jsonutils.dumps(port), cluster=cluster)

    except exception.NotFound:

        # FIXME(salv-orlando):avoid raising different exception

        data = {'lport_id': lport_id, 'lrouter_id': lrouter_id}

        msg = (_("Router Port %(lport_id)s not found on router "

                 "%(lrouter_id)s") % data)

        LOG.exception(msg)

        raise nsx_exc.NsxPluginException(err_msg=msg)

    except api_exc.NsxApiException as e:

        msg = _("An exception occurred while updating IP addresses on a "

                "router logical port:%s") % str(e)

        LOG.exception(msg)

        raise nsx_exc.NsxPluginException(err_msg=msg)

ROUTER_FUNC_DICT = {

    'create_lrouter': {

        2: {DEFAULT_VERSION: create_implicit_routing_lrouter, },

        3: {DEFAULT_VERSION: create_implicit_routing_lrouter,

            1: create_implicit_routing_lrouter_with_distribution,

            2: create_explicit_routing_lrouter, }, },

    'update_lrouter': {

        2: {DEFAULT_VERSION: update_implicit_routing_lrouter, },

        3: {DEFAULT_VERSION: update_implicit_routing_lrouter,

            2: update_explicit_routing_lrouter, }, },

    'create_lrouter_dnat_rule': {

        2: {DEFAULT_VERSION: create_lrouter_dnat_rule_v2, },

        3: {DEFAULT_VERSION: create_lrouter_dnat_rule_v3, }, },

    'create_lrouter_snat_rule': {

        2: {DEFAULT_VERSION: create_lrouter_snat_rule_v2, },

        3: {DEFAULT_VERSION: create_lrouter_snat_rule_v3, }, },

    'create_lrouter_nosnat_rule': {

        2: {DEFAULT_VERSION: create_lrouter_nosnat_rule_v2, },

        3: {DEFAULT_VERSION: create_lrouter_nosnat_rule_v3, }, },

    'create_lrouter_nodnat_rule': {

        2: {DEFAULT_VERSION: create_lrouter_nodnat_rule_v2, },

        3: {DEFAULT_VERSION: create_lrouter_nodnat_rule_v3, }, },

    'get_default_route_explicit_routing_lrouter': {

        3: {DEFAULT_VERSION: get_default_route_explicit_routing_lrouter_v32,

            2: get_default_route_explicit_routing_lrouter_v32, }, },

}

@versioned(ROUTER_FUNC_DICT)

**** CubicPower OpenStack Study ****

def create_lrouter(cluster, *args, **kwargs):

    if kwargs.get('distributed', None):

        v = cluster.api_client.get_version()

        if (v.major, v.minor) < (3, 1):

            raise nsx_exc.InvalidVersion(version=v)

        return v

@versioned(ROUTER_FUNC_DICT)

**** CubicPower OpenStack Study ****

def get_default_route_explicit_routing_lrouter(cluster, *args, **kwargs):

    pass

@versioned(ROUTER_FUNC_DICT)

**** CubicPower OpenStack Study ****

def update_lrouter(cluster, *args, **kwargs):

    if kwargs.get('routes', None):

        v = cluster.api_client.get_version()

        if (v.major, v.minor) < (3, 2):

            raise nsx_exc.InvalidVersion(version=v)

        return v

@versioned(ROUTER_FUNC_DICT)

**** CubicPower OpenStack Study ****

def create_lrouter_dnat_rule(cluster, *args, **kwargs):

    pass

@versioned(ROUTER_FUNC_DICT)

**** CubicPower OpenStack Study ****

def create_lrouter_snat_rule(cluster, *args, **kwargs):

    pass

@versioned(ROUTER_FUNC_DICT)

**** CubicPower OpenStack Study ****

def create_lrouter_nosnat_rule(cluster, *args, **kwargs):

    pass

@versioned(ROUTER_FUNC_DICT)

**** CubicPower OpenStack Study ****

def create_lrouter_nodnat_rule(cluster, *args, **kwargs):

    pass