components/openstack/neutron/files/evs/db/l3nat.py
changeset 1944 56ac2df1785b
parent 1760 353323c7bdc1
child 3524 ad6a9e0880b9
child 3619 639868f63ef4
equal deleted inserted replaced
1943:1a27f000029f 1944:56ac2df1785b
    19 # @author: Dan Wendlandt, Nicira, Inc
    19 # @author: Dan Wendlandt, Nicira, Inc
    20 # @author: Girish Moodalbail, Oracle, Inc.
    20 # @author: Girish Moodalbail, Oracle, Inc.
    21 #
    21 #
    22 
    22 
    23 """
    23 """
    24 Based off generic l3_agent (quantum/agent/l3_agent) code
    24 Based off generic l3_agent (neutron/agent/l3_agent) code
    25 """
    25 """
    26 
    26 
    27 import sqlalchemy as sa
    27 import sqlalchemy as sa
    28 
    28 
    29 from quantum.api.v2 import attributes
    29 from neutron.api.v2 import attributes
    30 from quantum.common import constants as l3_constants
    30 from neutron.common import constants as l3_constants
    31 from quantum.common import exceptions as q_exc
    31 from neutron.common import exceptions as q_exc
    32 from quantum.db import l3_db
    32 from neutron.db import l3_db
    33 from quantum.extensions import l3
    33 from neutron.extensions import l3
    34 from quantum.openstack.common import log as logging
    34 from neutron.extensions import external_net
    35 from quantum.openstack.common import uuidutils
    35 from neutron.openstack.common import log as logging
    36 from quantum.plugins.evs.db import api as evs_db
    36 from neutron.openstack.common import uuidutils
       
    37 from neutron.plugins.evs.db import api as evs_db
    37 
    38 
    38 
    39 
    39 LOG = logging.getLogger(__name__)
    40 LOG = logging.getLogger(__name__)
    40 
    41 
    41 DEVICE_OWNER_ROUTER_INTF = l3_constants.DEVICE_OWNER_ROUTER_INTF
    42 DEVICE_OWNER_ROUTER_INTF = l3_constants.DEVICE_OWNER_ROUTER_INTF
    42 DEVICE_OWNER_ROUTER_GW = l3_constants.DEVICE_OWNER_ROUTER_GW
    43 DEVICE_OWNER_ROUTER_GW = l3_constants.DEVICE_OWNER_ROUTER_GW
    43 DEVICE_OWNER_FLOATINGIP = l3_constants.DEVICE_OWNER_FLOATINGIP
    44 DEVICE_OWNER_FLOATINGIP = l3_constants.DEVICE_OWNER_FLOATINGIP
    44 
    45 
    45 
    46 
    46 class Router(evs_db.EVS_DB_BASE):
    47 class Router(evs_db.EVS_DB_BASE):
    47     """Represents a v2 quantum router."""
    48     """Represents a v2 neutron router."""
    48 
    49 
    49     id = sa.Column(sa.String(36), primary_key=True,
    50     id = sa.Column(sa.String(36), primary_key=True,
    50                    default=uuidutils.generate_uuid)
    51                    default=uuidutils.generate_uuid)
    51     name = sa.Column(sa.String(255))
    52     name = sa.Column(sa.String(255))
    52     status = sa.Column(sa.String(16))
    53     status = sa.Column(sa.String(16))
    55     gw_port_id = sa.Column(sa.String(36))
    56     gw_port_id = sa.Column(sa.String(36))
    56     gw_port_network_id = sa.Column(sa.String(36))
    57     gw_port_network_id = sa.Column(sa.String(36))
    57 
    58 
    58 
    59 
    59 class FloatingIP(evs_db.EVS_DB_BASE):
    60 class FloatingIP(evs_db.EVS_DB_BASE):
    60     """Represents a floating IP, which may or many not be
    61     """Represents a floating IP address.
    61        allocated to a tenant, and may or may not be associated with
    62 
    62        an internal port/ip address/router."""
    63     This IP address may or may not be allocated to a tenant, and may or
       
    64     may not be associated with an internal port/ip address/router.
       
    65     """
    63 
    66 
    64     id = sa.Column(sa.String(36), primary_key=True,
    67     id = sa.Column(sa.String(36), primary_key=True,
    65                    default=uuidutils.generate_uuid)
    68                    default=uuidutils.generate_uuid)
    66     floating_ip_address = sa.Column(sa.String(64), nullable=False)
    69     floating_ip_address = sa.Column(sa.String(64), nullable=False)
    67     floating_network_id = sa.Column(sa.String(36), nullable=False)
    70     floating_network_id = sa.Column(sa.String(36), nullable=False)
    76     """Mixin class to add L3/NAT router methods"""
    79     """Mixin class to add L3/NAT router methods"""
    77 
    80 
    78     Router = Router
    81     Router = Router
    79     FloatingIP = FloatingIP
    82     FloatingIP = FloatingIP
    80 
    83 
    81     def _make_router_dict(self, router, fields=None):
    84     def _make_router_dict(self, router, fields=None,
       
    85                           process_extensions=True):
    82         res = {'id': router['id'],
    86         res = {'id': router['id'],
    83                'name': router['name'],
    87                'name': router['name'],
    84                'tenant_id': router['tenant_id'],
    88                'tenant_id': router['tenant_id'],
    85                'admin_state_up': router['admin_state_up'],
    89                'admin_state_up': router['admin_state_up'],
    86                'status': router['status'],
    90                'status': router['status'],
    87                'external_gateway_info': None}
    91                'external_gateway_info': None,
       
    92                'gw_port_id': router['gw_port_id']}
    88         if router['gw_port_id']:
    93         if router['gw_port_id']:
    89             nw_id = router['gw_port_network_id']
    94             nw_id = router['gw_port_network_id']
    90             res['external_gateway_info'] = {'network_id': nw_id}
    95             res['external_gateway_info'] = {'network_id': nw_id}
       
    96         if process_extensions:
       
    97             self._apply_dict_extend_functions(
       
    98                 l3.ROUTERS, res, router)
    91         return self._fields(res, fields)
    99         return self._fields(res, fields)
    92 
   100 
    93     def create_router(self, context, router):
   101     def create_router(self, context, router):
    94         return super(EVS_L3_NAT_db_mixin, self).\
   102         return super(EVS_L3_NAT_db_mixin, self).\
    95             create_router(evs_db.get_evs_context(context), router)
   103             create_router(evs_db.get_evs_context(context), router)
    96 
   104 
    97     def update_router(self, context, id, router):
   105     def update_router(self, context, id, router):
    98         return super(EVS_L3_NAT_db_mixin, self).\
   106         return super(EVS_L3_NAT_db_mixin, self).\
    99             update_router(evs_db.get_evs_context(context), id, router)
   107             update_router(evs_db.get_evs_context(context), id, router)
   100 
   108 
   101     def _update_router_gw_info(self, context, router_id, info):
   109     def _update_router_gw_info(self, context, router_id, info, router=None):
   102         """This method overrides the base class method and it's contents
   110         """This method overrides the base class method and it's contents
   103         are exactly same as the base class method except that the Router
   111         are exactly same as the base class method except that the Router
   104         DB columns are different for EVS and OVS"""
   112         DB columns are different for EVS and OVS"""
   105 
   113 
   106         router = self._get_router(context, router_id)
   114         router = router or self._get_router(context, router_id)
   107         gw_port_id = router['gw_port_id']
   115         gw_port_id = router['gw_port_id']
       
   116         # network_id attribute is required by API, so it must be present
   108         gw_port_network_id = router['gw_port_network_id']
   117         gw_port_network_id = router['gw_port_network_id']
   109 
   118 
   110         network_id = info.get('network_id', None) if info else None
   119         network_id = info.get('network_id', None) if info else None
   111         if network_id:
   120         if network_id:
   112             self._get_network(context, network_id)
   121             self._get_network(context, network_id)
   137                 self._check_for_dup_router_subnet(context, router_id,
   146                 self._check_for_dup_router_subnet(context, router_id,
   138                                                   network_id, subnet['id'],
   147                                                   network_id, subnet['id'],
   139                                                   subnet['cidr'])
   148                                                   subnet['cidr'])
   140 
   149 
   141             # Port has no 'tenant-id', as it is hidden from user
   150             # Port has no 'tenant-id', as it is hidden from user
   142             gw_port = self.create_port(context.elevated(), {
   151             gw_port = self._core_plugin.create_port(context.elevated(), {
   143                 'port':
   152                 'port':
   144                 {'tenant_id': '',  # intentionally not set
   153                 {'tenant_id': '',  # intentionally not set
   145                  'network_id': network_id,
   154                  'network_id': network_id,
   146                  'mac_address': attributes.ATTR_NOT_SPECIFIED,
   155                  'mac_address': attributes.ATTR_NOT_SPECIFIED,
   147                  'fixed_ips': attributes.ATTR_NOT_SPECIFIED,
   156                  'fixed_ips': attributes.ATTR_NOT_SPECIFIED,
   148                  'device_id': router_id,
   157                  'device_id': router_id,
   149                  'device_owner': DEVICE_OWNER_ROUTER_GW,
   158                  'device_owner': DEVICE_OWNER_ROUTER_GW,
   150                  'admin_state_up': True,
   159                  'admin_state_up': True,
   151                  'name': ''}})
   160                  'name': ''}})
   152 
   161 
   153             if not len(gw_port['fixed_ips']):
   162             if not gw_port['fixed_ips']:
   154                 self.delete_port(context.elevated(), gw_port['id'],
   163                 self._core_plugin.delete_port(context.elevated(),
   155                                  l3_port_check=False)
   164                                               gw_port['id'],
       
   165                                               l3_port_check=False)
   156                 msg = (_('No IPs available for external network %s') %
   166                 msg = (_('No IPs available for external network %s') %
   157                        network_id)
   167                        network_id)
   158                 raise q_exc.BadRequest(resource='router', msg=msg)
   168                 raise q_exc.BadRequest(resource='router', msg=msg)
   159 
   169 
   160             with context.session.begin(subtransactions=True):
   170             with context.session.begin(subtransactions=True):
   193         return super(EVS_L3_NAT_db_mixin, self).\
   203         return super(EVS_L3_NAT_db_mixin, self).\
   194             add_router_interface(evs_db.get_evs_context(context),
   204             add_router_interface(evs_db.get_evs_context(context),
   195                                  router_id, interface_info)
   205                                  router_id, interface_info)
   196 
   206 
   197     def remove_router_interface(self, context, router_id, interface_info):
   207     def remove_router_interface(self, context, router_id, interface_info):
   198         super(EVS_L3_NAT_db_mixin, self).\
   208         return super(EVS_L3_NAT_db_mixin, self).\
   199             remove_router_interface(evs_db.get_evs_context(context),
   209             remove_router_interface(evs_db.get_evs_context(context),
   200                                     router_id, interface_info)
   210                                     router_id, interface_info)
   201 
   211 
   202     def create_floatingip(self, context, floatingip):
   212     def create_floatingip(self, context, floatingip):
   203         return super(EVS_L3_NAT_db_mixin, self).\
   213         return super(EVS_L3_NAT_db_mixin, self).\
   252 
   262 
   253     def disassociate_floatingips(self, context, port_id):
   263     def disassociate_floatingips(self, context, port_id):
   254         super(EVS_L3_NAT_db_mixin, self).\
   264         super(EVS_L3_NAT_db_mixin, self).\
   255             disassociate_floatingips(evs_db.get_evs_context(context), port_id)
   265             disassociate_floatingips(evs_db.get_evs_context(context), port_id)
   256 
   266 
   257     def _network_is_external(self, context, net_id):
       
   258         try:
       
   259             evs = self.get_network(context, net_id)
       
   260             return evs[l3.EXTERNAL]
       
   261         except:
       
   262             return False
       
   263 
       
   264     def get_sync_data(self, context, router_ids=None, active=None):
   267     def get_sync_data(self, context, router_ids=None, active=None):
   265         return super(EVS_L3_NAT_db_mixin, self).\
   268         return super(EVS_L3_NAT_db_mixin, self).\
   266             get_sync_data(evs_db.get_evs_context(context), router_ids, active)
   269             get_sync_data(evs_db.get_evs_context(context), router_ids, active)
   267 
       
   268     def get_external_network_id(self, context):
       
   269         return super(EVS_L3_NAT_db_mixin, self).\
       
   270             get_external_network_id(evs_db.get_evs_context(context))
       
   271 
       
   272     def _get_tenant_id_for_create(self, context, resource):
       
   273         if context.is_admin and 'tenant_id' in resource:
       
   274             tenant_id = resource['tenant_id']
       
   275         elif ('tenant_id' in resource and
       
   276               resource['tenant_id'] != context.tenant_id):
       
   277             reason = _('Cannot create resource for another tenant')
       
   278             raise q_exc.AdminRequired(reason=reason)
       
   279         else:
       
   280             tenant_id = context.tenant_id
       
   281         return tenant_id
       
   282 
   270 
   283     def _get_by_id(self, context, model, id):
   271     def _get_by_id(self, context, model, id):
   284         return context.session.query(model).\
   272         return context.session.query(model).\
   285             filter(model.id == id).one()
   273             filter(model.id == id).one()
   286 
       
   287     def _get_network(self, context, network_id):
       
   288         return self.get_network(context, network_id)
       
   289 
       
   290     def _get_subnet(self, context, subnet_id):
       
   291         return self.get_subnet(context, subnet_id)
       
   292 
       
   293     def _get_port(self, context, port_id):
       
   294         return self.get_port(context, port_id)
       
   295 
       
   296     def _delete_port(self, context, port_id):
       
   297         return self.delete_port(context, port_id)
       
   298 
       
   299     def _get_subnets_by_network(self, context, network_id):
       
   300         return self.get_subnets(context, filters={'network_id': network_id})
       
   301 
   274 
   302     def allow_l3_port_deletion(self, context, port_id):
   275     def allow_l3_port_deletion(self, context, port_id):
   303         """ If an L3 agent is using this port, then we need to send
   276         """ If an L3 agent is using this port, then we need to send
   304         a notification to L3 agent to release the port before we can
   277         a notification to L3 agent to release the port before we can
   305         delete the port"""
   278         delete the port"""