示例#1
0
    def handle(self, context):
        current_ctx = context.current

        sfc_port_data = prepare_port_data(current_ctx, name='sfc')
        normal_port_data = prepare_port_data(current_ctx, name='normal')
        sfc_port = neutron_utils.create_port(self._core_plugin,
                                             context._plugin_context,
                                             {'port': sfc_port_data})
        LOG.info("Creating P4 port completed. ID= " + sfc_port['id'])
        normal_port = neutron_utils.create_port(self._core_plugin,
                                                context._plugin_context,
                                                {'port': normal_port_data})
        LOG.info("Creating P4 port completed. ID= " + normal_port['id'])
        program = current_ctx['program']

        with neutron_utils.delete_port_on_error(self._core_plugin,
                                                context._plugin_context,
                                                normal_port['id']):
            with neutron_utils.delete_port_on_error(self._core_plugin,
                                                    context._plugin_context,
                                                    sfc_port['id']):
                ports_data = self._prepare_port_data(sfc_port, normal_port)
                self.rpc_client.ask_agent_to_install_data_plane_module(
                    self.rpc_ctx,
                    network_id=normal_port_data['network_id'],
                    ports=ports_data,
                    program=program)
示例#2
0
 def test_delete_port_on_error_no_delete(self):
     core_plugin, context = mock.Mock(), mock.Mock()
     with testtools.ExpectedException(ValueError):
         with utils.delete_port_on_error(core_plugin, context, 1) as cm:
             cm.delete_on_error = False
             raise ValueError()
     self.assertFalse(core_plugin.delete_port.called)
示例#3
0
 def test_delete_port_on_error_no_delete(self):
     core_plugin, context = mock.Mock(), mock.Mock()
     with testtools.ExpectedException(ValueError):
         with utils.delete_port_on_error(core_plugin, context, 1) as cm:
             cm.delete_on_error = False
             raise ValueError()
     self.assertFalse(core_plugin.delete_port.called)
示例#4
0
    def _add_csnat_router_interface_port(
            self, context, router, network_id, subnet_id, do_pop=True):
        """Add SNAT interface to the specified router and subnet."""
        port_data = {'tenant_id': '',
                     'network_id': network_id,
                     'fixed_ips': [{'subnet_id': subnet_id}],
                     'device_id': router.id,
                     'device_owner': const.DEVICE_OWNER_ROUTER_SNAT,
                     'admin_state_up': True,
                     'name': ''}
        snat_port = p_utils.create_port(self._core_plugin, context,
                                        {'port': port_data})
        if not snat_port:
            msg = _("Unable to create the SNAT Interface Port")
            raise n_exc.BadRequest(resource='router', msg=msg)

        with p_utils.delete_port_on_error(
            self.l3plugin._core_plugin, context.elevated(), snat_port['id']):
            l3_obj.RouterPort(
                context,
                port_id=snat_port['id'],
                router_id=router.id,
                port_type=const.DEVICE_OWNER_ROUTER_SNAT
            ).create()

            if do_pop:
                return self.l3plugin._populate_mtu_and_subnets_for_ports(
                    context, [snat_port])
            return snat_port
示例#5
0
 def test_delete_port_on_error(self):
     core_plugin, context = mock.Mock(), mock.Mock()
     port_id = "pid"
     with testtools.ExpectedException(ValueError):
         with utils.delete_port_on_error(core_plugin, context, port_id):
             raise ValueError()
     core_plugin.delete_port.assert_called_once_with(context, port_id, l3_port_check=False)
示例#6
0
    def _add_csnat_router_interface_port(
            self, context, router, network_id, subnet_id, do_pop=True):
        """Add SNAT interface to the specified router and subnet."""
        port_data = {'tenant_id': '',
                     'network_id': network_id,
                     'fixed_ips': [{'subnet_id': subnet_id}],
                     'device_id': router.id,
                     'device_owner': const.DEVICE_OWNER_ROUTER_SNAT,
                     'admin_state_up': True,
                     'name': ''}
        snat_port = p_utils.create_port(self._core_plugin, context,
                                        {'port': port_data})
        if not snat_port:
            msg = _("Unable to create the SNAT Interface Port")
            raise n_exc.BadRequest(resource='router', msg=msg)

        with p_utils.delete_port_on_error(
            self.l3plugin._core_plugin, context.elevated(), snat_port['id']):
            l3_obj.RouterPort(
                context,
                port_id=snat_port['id'],
                router_id=router.id,
                port_type=const.DEVICE_OWNER_ROUTER_SNAT
            ).create()

            if do_pop:
                return self.l3plugin._populate_mtu_and_subnets_for_ports(
                    context, [snat_port])
            return snat_port
示例#7
0
 def test_delete_port_on_error(self):
     core_plugin, context = mock.Mock(), mock.Mock()
     port_id = 'pid'
     with testtools.ExpectedException(ValueError):
         with utils.delete_port_on_error(core_plugin, context, port_id):
             raise ValueError()
     core_plugin.delete_port.assert_called_once_with(context, port_id,
                                                     l3_port_check=False)
示例#8
0
 def test_delete_port_on_error_port_does_not_exist(self):
     core_plugin, context = mock.Mock(), mock.Mock()
     port_id = 'pid'
     core_plugin.delete_port.side_effect = exceptions.PortNotFound(
         port_id=port_id)
     with testtools.ExpectedException(exceptions.PortNotFound):
         with utils.delete_port_on_error(core_plugin, context, port_id):
             raise exceptions.PortNotFound(port_id=port_id)
     core_plugin.delete_port.assert_called_once_with(context, port_id,
                                                     l3_port_check=False)
示例#9
0
 def test_delete_port_on_error_port_does_not_exist(self):
     core_plugin, context = mock.Mock(), mock.Mock()
     port_id = 'pid'
     core_plugin.delete_port.side_effect = exceptions.PortNotFound(
         port_id=port_id)
     with testtools.ExpectedException(exceptions.PortNotFound):
         with utils.delete_port_on_error(core_plugin, context, port_id):
             raise exceptions.PortNotFound(port_id=port_id)
     core_plugin.delete_port.assert_called_once_with(context,
                                                     port_id,
                                                     l3_port_check=False)
示例#10
0
    def add_router_interface(self, context, router_id, interface_info):
        add_by_port, add_by_sub = self._validate_interface_info(interface_info)
        router = self._get_router(context, router_id)
        device_owner = self._get_device_owner(context, router)

        # This should be True unless adding an IPv6 prefix to an existing port
        new_port = True
        cleanup_port = False

        if add_by_port:
            port, subnets = self._add_interface_by_port(
                context, router, interface_info['port_id'], device_owner)
        elif add_by_sub:
            port, subnets, new_port = self._add_interface_by_subnet(
                context, router, interface_info['subnet_id'], device_owner)
            cleanup_port = new_port

        subnet = subnets[0]

        if new_port:
            with p_utils.delete_port_on_error(self._core_plugin, context,
                                              port['id']) as delmgr:
                if router.extra_attributes.distributed and router.gw_port:
                    admin_context = context.elevated()
                    self._add_csnat_router_interface_port(
                        admin_context, router, port['network_id'],
                        port['fixed_ips'][-1]['subnet_id'])

                delmgr.delete_on_error = cleanup_port
                with context.session.begin(subtransactions=True):
                    router_port = l3_db.RouterPort(port_id=port['id'],
                                                   router_id=router.id,
                                                   port_type=device_owner)
                    context.session.add(router_port)

        # NOTE: For IPv6 additional subnets added to the same
        # network we need to update the CSNAT port with respective
        # IPv6 subnet
        elif subnet and port:
            fixed_ip = {'subnet_id': subnet['id']}
            if subnet['ip_version'] == 6:
                # Add new prefix to an existing ipv6 csnat port with the
                # same network id if one exists
                cs_port = (
                    self._find_v6_router_port_by_network_and_device_owner(
                        router, subnet['network_id'],
                        const.DEVICE_OWNER_ROUTER_SNAT))
                if cs_port:
                    fixed_ips = list(cs_port['port']['fixed_ips'])
                    fixed_ips.append(fixed_ip)
                    updated_port = self._core_plugin.update_port(
                        context.elevated(), cs_port['port_id'],
                        {'port': {
                            'fixed_ips': fixed_ips
                        }})
                    LOG.debug("CSNAT port updated for IPv6 subnet: "
                              "%s", updated_port)
        router_interface_info = self._make_router_interface_info(
            router_id, port['tenant_id'], port['id'], port['network_id'],
            subnet['id'], [subnet['id']])
        self.notify_router_interface_action(context, router_interface_info,
                                            'add')
        if router.gw_port:
            gw_network_id = router.gw_port.network_id
            gw_ips = [x['ip_address'] for x in router.gw_port.fixed_ips]
            registry.notify(resources.ROUTER_INTERFACE,
                            events.AFTER_CREATE,
                            self,
                            context=context,
                            network_id=gw_network_id,
                            gateway_ips=gw_ips,
                            cidrs=[x['cidr'] for x in subnets],
                            port_id=port['id'],
                            router_id=router_id,
                            port=port,
                            interface_info=interface_info)
        return router_interface_info
示例#11
0
    def add_router_interface(self, context, router_id, interface_info):
        add_by_port, add_by_sub = self._validate_interface_info(interface_info)
        router = self._get_router(context, router_id)
        device_owner = self._get_device_owner(context, router)

        # This should be True unless adding an IPv6 prefix to an existing port
        new_port = True
        cleanup_port = False

        if add_by_port:
            port, subnets = self._add_interface_by_port(
                    context, router, interface_info['port_id'], device_owner)
        elif add_by_sub:
            port, subnets, new_port = self._add_interface_by_subnet(
                    context, router, interface_info['subnet_id'], device_owner)
            cleanup_port = new_port

        subnet = subnets[0]

        if new_port:
            with p_utils.delete_port_on_error(self._core_plugin,
                                              context, port['id']) as delmgr:
                if router.extra_attributes.distributed and router.gw_port:
                    admin_context = context.elevated()
                    self._add_csnat_router_interface_port(
                        admin_context, router, port['network_id'],
                        port['fixed_ips'][-1]['subnet_id'])

                delmgr.delete_on_error = cleanup_port
                with context.session.begin(subtransactions=True):
                    router_port = l3_db.RouterPort(
                        port_id=port['id'],
                        router_id=router.id,
                        port_type=device_owner
                    )
                    context.session.add(router_port)

        # NOTE: For IPv6 additional subnets added to the same
        # network we need to update the CSNAT port with respective
        # IPv6 subnet
        elif subnet and port:
            fixed_ip = {'subnet_id': subnet['id']}
            if subnet['ip_version'] == 6:
                # Add new prefix to an existing ipv6 csnat port with the
                # same network id if one exists
                cs_port = (
                    self._find_v6_router_port_by_network_and_device_owner(
                        router, subnet['network_id'],
                        const.DEVICE_OWNER_ROUTER_SNAT))
                if cs_port:
                    fixed_ips = list(cs_port['port']['fixed_ips'])
                    fixed_ips.append(fixed_ip)
                    updated_port = self._core_plugin.update_port(
                        context.elevated(),
                        cs_port['port_id'], {'port': {'fixed_ips': fixed_ips}})
                    LOG.debug("CSNAT port updated for IPv6 subnet: "
                              "%s", updated_port)
        router_interface_info = self._make_router_interface_info(
            router_id, port['tenant_id'], port['id'], port['network_id'],
            subnet['id'], [subnet['id']])
        self.notify_router_interface_action(
            context, router_interface_info, 'add')
        if router.gw_port:
            gw_network_id = router.gw_port.network_id
            gw_ips = [x['ip_address'] for x in router.gw_port.fixed_ips]
            registry.notify(resources.ROUTER_INTERFACE,
                        events.AFTER_CREATE,
                        self,
                        context=context,
                        network_id=gw_network_id,
                        gateway_ips=gw_ips,
                        cidrs=[x['cidr'] for x in subnets],
                        port_id=port['id'],
                        router_id=router_id,
                        port=port,
                        interface_info=interface_info)
        return router_interface_info
示例#12
0
    def _create_floatingip(self, context, floatingip,
                           initial_status=n_const.FLOATINGIP_STATUS_ACTIVE):
        fip = floatingip['floatingip']
        fip_id = uuidutils.generate_uuid()

        f_net_id = fip['floating_network_id']
        if not self._core_plugin._network_is_external(context, f_net_id):
            msg = _("Network %s is not a valid external network") % f_net_id
            raise n_exc.BadRequest(resource='floatingip', msg=msg)

        self._validate_network_for_floatingip(context, f_net_id)

        # This external port is never exposed to the tenant.
        # it is used purely for internal system and admin use when
        # managing floating IPs.

        port = {'tenant_id': '',  # tenant intentionally not set
                'network_id': f_net_id,
                'admin_state_up': True,
                'device_id': 'PENDING',
                'device_owner': DEVICE_OWNER_FLOATINGIP,
                'status': n_const.PORT_STATUS_NOTAPPLICABLE,
                'name': ''}
        if fip.get('floating_ip_address'):
            port['fixed_ips'] = [
                {'ip_address': fip['floating_ip_address']}]

        if fip.get('subnet_id'):
            port['fixed_ips'] = [
                {'subnet_id': fip['subnet_id']}]

        # 'status' in port dict could not be updated by default, use
        # check_allow_post to stop the verification of system
        external_port = p_utils.create_port(self._core_plugin,
                                            context.elevated(),
                                            {'port': port},
                                            check_allow_post=False)

        with p_utils.delete_port_on_error(self._core_plugin,
                                          context.elevated(),
                                          external_port['id']),\
                context.session.begin(subtransactions=True):
            external_ips = self._port_fixed_ips_for_floatingip(external_port)
            if not external_ips:
                raise n_exc.ExternalIpAddressExhausted(net_id=f_net_id)

            floating_fixed_ip = external_ips[0]
            floating_ip_address = floating_fixed_ip['ip_address']
            floatingip_db = l3_db.FloatingIP(
                id=fip_id,
                tenant_id=fip['tenant_id'],
                status=initial_status,
                floating_network_id=fip['floating_network_id'],
                floating_ip_address=floating_ip_address,
                floating_port_id=external_port['id'],
                description=fip.get('description'))
            # Update association with internal port
            # and define external IP address
            assoc_result = self._update_fip_assoc(context, fip,
                                                  floatingip_db, external_port)
            context.session.add(floatingip_db)
            floatingip_dict = self._make_floatingip_dict(
                floatingip_db, process_extensions=False)
            if self._is_dns_integration_supported:
                dns_data = self._process_dns_floatingip_create_precommit(
                    context, floatingip_dict, fip)

        self._core_plugin.update_port(context.elevated(), external_port['id'],
                                      {'port': {'device_id': fip_id}})
        registry.notify(resources.FLOATING_IP,
                        events.AFTER_UPDATE,
                        self._update_fip_assoc,
                        **assoc_result)

        if self._is_dns_integration_supported:
            self._process_dns_floatingip_create_postcommit(context,
                                                           floatingip_dict,
                                                           dns_data)
        self._apply_dict_extend_functions(l3.FLOATINGIPS, floatingip_dict,
                                          floatingip_db)
        return floatingip_dict