1 # Copyright 2012 VMware, Inc.
4 # Licensed under the Apache License, Version 2.0 (the "License"); you may
5 # not use this file except in compliance with the License. You may obtain
6 # a copy of the License at
8 # http://www.apache.org/licenses/LICENSE-2.0
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 # License for the specific language governing permissions and limitations
18 from oslo_config import cfg
20 from neutron._i18n import _
21 from neutron.api import extensions
22 from neutron.api.v2 import attributes as attr
23 from neutron.api.v2 import resource_helper
24 from neutron.common import exceptions as nexception
25 from neutron.plugins.common import constants
29 class RouterNotFound(nexception.NotFound):
30 message = _("Router %(router_id)s could not be found")
33 class RouterInUse(nexception.InUse):
34 message = _("Router %(router_id)s %(reason)s")
36 def __init__(self, **kwargs):
37 if 'reason' not in kwargs:
38 kwargs['reason'] = "still has ports"
39 super(RouterInUse, self).__init__(**kwargs)
42 class RouterInterfaceNotFound(nexception.NotFound):
43 message = _("Router %(router_id)s does not have "
44 "an interface with id %(port_id)s")
47 class RouterInterfaceNotFoundForSubnet(nexception.NotFound):
48 message = _("Router %(router_id)s has no interface "
49 "on subnet %(subnet_id)s")
52 class RouterInterfaceInUseByFloatingIP(nexception.InUse):
53 message = _("Router interface for subnet %(subnet_id)s on router "
54 "%(router_id)s cannot be deleted, as it is required "
55 "by one or more floating IPs.")
58 class FloatingIPNotFound(nexception.NotFound):
59 message = _("Floating IP %(floatingip_id)s could not be found")
62 class ExternalGatewayForFloatingIPNotFound(nexception.NotFound):
63 message = _("External network %(external_network_id)s is not reachable "
64 "from subnet %(subnet_id)s. Therefore, cannot associate "
65 "Port %(port_id)s with a Floating IP.")
68 class FloatingIPPortAlreadyAssociated(nexception.InUse):
69 message = _("Cannot associate floating IP %(floating_ip_address)s "
70 "(%(fip_id)s) with port %(port_id)s "
71 "using fixed IP %(fixed_ip)s, as that fixed IP already "
72 "has a floating IP on external network %(net_id)s.")
75 class RouterExternalGatewayInUseByFloatingIp(nexception.InUse):
76 message = _("Gateway cannot be updated for router %(router_id)s, since a "
77 "gateway to external network %(net_id)s is required by one or "
81 EXTERNAL_GW_INFO = 'external_gateway_info'
82 FLOATINGIPS = 'floatingips'
84 RESOURCE_ATTRIBUTE_MAP = {
86 'id': {'allow_post': False, 'allow_put': False,
87 'validate': {'type:uuid': None},
90 'name': {'allow_post': True, 'allow_put': True,
91 'validate': {'type:string': attr.NAME_MAX_LEN},
92 'is_visible': True, 'default': ''},
93 'admin_state_up': {'allow_post': True, 'allow_put': True,
95 'convert_to': attr.convert_to_boolean,
97 'status': {'allow_post': False, 'allow_put': False,
99 'tenant_id': {'allow_post': True, 'allow_put': False,
100 'required_by_policy': True,
101 'validate': {'type:string': attr.TENANT_ID_MAX_LEN},
103 EXTERNAL_GW_INFO: {'allow_post': True, 'allow_put': True,
104 'is_visible': True, 'default': None,
105 'enforce_policy': True,
107 'type:dict_or_nodata': {
108 'network_id': {'type:uuid': None,
110 'external_fixed_ips': {
112 attr.convert_kvp_list_to_dict,
113 'type:fixed_ips': None,
121 'id': {'allow_post': False, 'allow_put': False,
122 'validate': {'type:uuid': None},
124 'primary_key': True},
125 'floating_ip_address': {'allow_post': True, 'allow_put': False,
126 'validate': {'type:ip_address_or_none': None},
127 'is_visible': True, 'default': None,
128 'enforce_policy': True},
129 'subnet_id': {'allow_post': True, 'allow_put': False,
130 'validate': {'type:uuid_or_none': None},
131 'is_visible': False, # Use False for input only attr
133 'floating_network_id': {'allow_post': True, 'allow_put': False,
134 'validate': {'type:uuid': None},
136 'router_id': {'allow_post': False, 'allow_put': False,
137 'validate': {'type:uuid_or_none': None},
138 'is_visible': True, 'default': None},
139 'port_id': {'allow_post': True, 'allow_put': True,
140 'validate': {'type:uuid_or_none': None},
141 'is_visible': True, 'default': None,
142 'required_by_policy': True},
143 'fixed_ip_address': {'allow_post': True, 'allow_put': True,
144 'validate': {'type:ip_address_or_none': None},
145 'is_visible': True, 'default': None},
146 'tenant_id': {'allow_post': True, 'allow_put': False,
147 'required_by_policy': True,
148 'validate': {'type:string': attr.TENANT_ID_MAX_LEN},
150 'status': {'allow_post': False, 'allow_put': False,
156 cfg.IntOpt('quota_router',
158 help=_('Number of routers allowed per tenant. '
159 'A negative value means unlimited.')),
160 cfg.IntOpt('quota_floatingip',
162 help=_('Number of floating IPs allowed per tenant. '
163 'A negative value means unlimited.')),
165 cfg.CONF.register_opts(l3_quota_opts, 'QUOTAS')
168 class L3(extensions.ExtensionDescriptor):
172 return "Neutron L3 Router"
179 def get_description(cls):
180 return ("Router abstraction for basic L3 forwarding"
181 " between L2 Neutron networks and access to external"
182 " networks via a NAT gateway.")
185 def get_updated(cls):
186 return "2012-07-20T10:00:00-00:00"
189 def get_resources(cls):
190 """Returns Ext Resources."""
191 plural_mappings = resource_helper.build_plural_mappings(
192 {}, RESOURCE_ATTRIBUTE_MAP)
193 plural_mappings['external_fixed_ips'] = 'external_fixed_ip'
194 attr.PLURALS.update(plural_mappings)
195 action_map = {'router': {'add_router_interface': 'PUT',
196 'remove_router_interface': 'PUT'}}
197 return resource_helper.build_resource_info(plural_mappings,
198 RESOURCE_ATTRIBUTE_MAP,
199 constants.L3_ROUTER_NAT,
200 action_map=action_map,
203 def update_attributes_map(self, attributes):
204 super(L3, self).update_attributes_map(
205 attributes, extension_attrs_map=RESOURCE_ATTRIBUTE_MAP)
207 def get_extended_resources(self, version):
209 return RESOURCE_ATTRIBUTE_MAP
214 class RouterPluginBase(object):
217 def create_router(self, context, router):
221 def update_router(self, context, id, router):
225 def get_router(self, context, id, fields=None):
229 def delete_router(self, context, id):
233 def get_routers(self, context, filters=None, fields=None,
234 sorts=None, limit=None, marker=None, page_reverse=False):
238 def add_router_interface(self, context, router_id, interface_info):
242 def remove_router_interface(self, context, router_id, interface_info):
246 def create_floatingip(self, context, floatingip):
250 def update_floatingip(self, context, id, floatingip):
254 def get_floatingip(self, context, id, fields=None):
258 def delete_floatingip(self, context, id):
262 def get_floatingips(self, context, filters=None, fields=None,
263 sorts=None, limit=None, marker=None,
267 def get_routers_count(self, context, filters=None):
268 raise NotImplementedError()
270 def get_floatingips_count(self, context, filters=None):
271 raise NotImplementedError()