def update_floatingip(self, context, fpid, floatingip):
        port_id_specified = 'port_id' in floatingip['floatingip']
        if not port_id_specified:
            LOG.error(_LE("port_id key is not found in %s"), floatingip)
            raise exc.PortNotFound(port_id=None)

        port_id = floatingip['floatingip'].get('port_id')
        try:
            if port_id_specified and not port_id:
                floating = context.session.query(l3_db.FloatingIP).filter_by(
                    id=fpid).one()
                self._delete_nat(context, floating)
        except sa.orm.exc.NoResultFound:
            raise exc.PortNotFound(port_id=port_id)

        ret = super(NECNWAL3Plugin, self).update_floatingip(
            context, fpid, floatingip)

        try:
            if port_id_specified and port_id:
                floating = context.session.query(l3_db.FloatingIP).filter_by(
                    id=fpid).one()
                tenant_id = nwa_l3_db.get_tenant_id_by_router(
                    context.session,
                    floating['router_id']
                )
                nwa_tenant_id = nwa_com_utils.get_nwa_tenant_id(tenant_id)

                fl_data = {
                    'floating_ip_address': floating['floating_ip_address'],
                    'fixed_ip_address': floating['fixed_ip_address'],
                    'id': fpid, 'device_id': floating['router_id'],
                    'floating_network_id': floating['floating_network_id'],
                    'tenant_id': floating['tenant_id'],
                    'floating_port_id': floating['floating_port_id']
                }
                LOG.info(_LI('setting_nat fl_data is %s'), fl_data)
                proxy = self._get_nwa_proxy(self, tenant_id)
                proxy.setting_nat(
                    context, tenant_id=tenant_id,
                    nwa_tenant_id=nwa_tenant_id,
                    floating=fl_data
                )

        except sa.orm.exc.NoResultFound:
            raise exc.PortNotFound(port_id=port_id)

        return ret
Example #2
0
def disassociate_port(context, id, ip_address_id):
    """Disassociates a port from an IP address.

    : param context: neutron api request context
    : param id: UUID representing the port to disassociate.
    : param ip_address_id: UUID representing the IP address to
    disassociate.
    """
    LOG.info("disassociate_port %s for tenant %s ip_address_id %s" %
             (id, context.tenant_id, ip_address_id))
    port = db_api.port_find(context,
                            id=id,
                            ip_address_id=[ip_address_id],
                            scope=db_api.ONE)

    if not port:
        raise exceptions.PortNotFound(port_id=id, net_id='')

    the_address = [
        address for address in port["ip_addresses"]
        if address["id"] == ip_address_id
    ][0]
    port["ip_addresses"] = [
        address for address in port["ip_addresses"]
        if address.id != ip_address_id
    ]

    if len(the_address["ports"]) == 0:
        the_address["deallocated"] = 1
    return v._make_port_dict(port)
Example #3
0
def get_port_for_ip_address(context, ip_id, id, fields=None):
    """Retrieve a port.

    : param context: neutron api request context
    : param id: UUID representing the port to fetch.
    : param fields: a list of strings that are valid keys in a
        port dictionary as listed in the RESOURCE_ATTRIBUTE_MAP
        object in neutron/api/v2/attributes.py. Only these fields
        will be returned.
    """
    LOG.info("get_port %s for tenant %s fields %s" %
             (id, context.tenant_id, fields))
    addr = db_api.ip_address_find(context, id=ip_id, scope=db_api.ONE)
    if not addr:
        raise quark_exceptions.IpAddressNotFound(addr_id=ip_id)

    filters = {'ip_address_id': [ip_id]}
    results = db_api.port_find(context,
                               id=id,
                               fields=fields,
                               scope=db_api.ONE,
                               **filters)

    if not results:
        raise exceptions.PortNotFound(port_id=id, net_id='')

    return v._make_port_for_ip_dict(addr, results)
Example #4
0
def delete_port(context, id):
    """Delete a port.

    : param context: neutron api request context
    : param id: UUID representing the port to delete.
    """
    LOG.info("delete_port %s for tenant %s" %
             (id, context.tenant_id))

    port = db_api.port_find(context, id=id, scope=db_api.ONE)
    if not port:
        raise exceptions.PortNotFound(net_id=id)

    backend_key = port["backend_key"]
    mac_address = netaddr.EUI(port["mac_address"]).value
    ipam_driver = ipam.IPAM_REGISTRY.get_strategy(
        port["network"]["ipam_strategy"])
    ipam_driver.deallocate_mac_address(context, mac_address)
    ipam_driver.deallocate_ips_by_port(
        context, port, ipam_reuse_after=CONF.QUARK.ipam_reuse_after)

    net_driver = registry.DRIVER_REGISTRY.get_driver(
        port.network["network_plugin"])
    net_driver.delete_port(context, backend_key, device_id=port["device_id"],
                           mac_address=port["mac_address"])

    with context.session.begin():
        db_api.port_delete(context, port)
Example #5
0
 def _set_port_status(self, port_id, status):
     session = db.get_session()
     try:
         port = session.query(models_v2.Port).filter_by(id=port_id).one()
         port['status'] = status
         session.flush()
     except sqlexc.NoResultFound:
         raise exceptions.PortNotFound(port_id=port_id)
Example #6
0
def set_port_status(session, port_id, status):
    try:
        port = session.query(models_v2.Port).filter_by(id=port_id).one()
        port['status'] = status
        session.merge(port)
        session.flush()
    except orm_exc.NoResultFound:
        raise n_exc.PortNotFound(port_id=port_id)
Example #7
0
 def test_update_device_up_with_dvr_when_port_not_found(self):
     kwargs = {
         'agent_id': 'foo_agent',
         'device': 'foo_device'
     }
     self.l3plugin.dvr_vmarp_table_update.side_effect = (
         exceptions.PortNotFound(port_id='foo_port_id'))
     self._test_update_device_up(['router', 'dvr'], kwargs)
     self.assertTrue(self.l3plugin.dvr_vmarp_table_update.call_count)
Example #8
0
 def set_port_status(self, port_id, status):
     session = db_api.get_session()
     try:
         port = session.query(models_v2.Port).filter_by(id=port_id).one()
         port['status'] = status
         session.merge(port)
         session.flush()
     except exc.NoResultFound:
         raise q_exc.PortNotFound(port_id=port_id)
Example #9
0
    def update_port(self, context, id, port):
        attrs = port['port']
        need_port_update_notify = False

        session = context.session
        changed_fixed_ips = 'fixed_ips' in port['port']
        with session.begin(subtransactions=True):
            try:
                port_db = (session.query(
                    models_v2.Port).enable_eagerloads(False).filter_by(
                        id=id).with_lockmode('update').one())
            except sa_exc.NoResultFound:
                raise exc.PortNotFound(port_id=id)
            original_port = self._make_port_dict(port_db)
            updated_port = super(Ml2Plugin,
                                 self).update_port(context, id, port)
            if self.is_address_pairs_attribute_updated(original_port, port):
                self._delete_allowed_address_pairs(context, id)
                self._process_create_allowed_address_pairs(
                    context, updated_port,
                    port['port'][addr_pair.ADDRESS_PAIRS])
                need_port_update_notify = True
            elif changed_fixed_ips:
                self._check_fixed_ips_and_address_pairs_no_overlap(
                    context, updated_port)
            need_port_update_notify |= self.update_security_group_on_port(
                context, id, port, original_port, updated_port)
            network = self.get_network(context, original_port['network_id'])
            need_port_update_notify |= self._update_extra_dhcp_opts_on_port(
                context, id, port, updated_port)
            mech_context = driver_context.PortContext(
                self,
                context,
                updated_port,
                network,
                original_port=original_port)
            need_port_update_notify |= self._process_port_binding(
                mech_context, attrs)
            self.mechanism_manager.update_port_precommit(mech_context)

        # TODO(apech) - handle errors raised by update_port, potentially
        # by re-calling update_port with the previous attributes. For
        # now the error is propogated to the caller, which is expected to
        # either undo/retry the operation or delete the resource.
        self.mechanism_manager.update_port_postcommit(mech_context)

        need_port_update_notify |= self.is_security_group_member_updated(
            context, original_port, updated_port)

        if original_port['admin_state_up'] != updated_port['admin_state_up']:
            need_port_update_notify = True

        if need_port_update_notify:
            self._notify_port_updated(mech_context)

        return updated_port
Example #10
0
 def test_delete_floatingip_deleted_port_no_notify(self):
     port_id = 'bee50827-bcee-4cc8-91c1-a27b0ce54222'
     with mock.patch.object(
         self.nova_notifier._plugin_ref, 'get_port',
         side_effect=n_exc.PortNotFound(port_id=port_id)):
         returned_obj = {'floatingip':
                         {'port_id': port_id}}
         event = self.nova_notifier.create_port_changed_event(
             'delete_floatingip', {}, returned_obj)
         self.assertIsNone(event)
Example #11
0
def post_update_port(context, id, port):
    LOG.info("post_update_port %s for tenant %s" % (id, context.tenant_id))
    if not port.get("port"):
        raise exceptions.BadRequest(resource="ports", msg="Port body required")

    port_db = db_api.port_find(context, id=id, scope=db_api.ONE)
    if not port_db:
        raise exceptions.PortNotFound(port_id=id, net_id="")

    port = port["port"]
    if "fixed_ips" in port and port["fixed_ips"]:
        for ip in port["fixed_ips"]:
            address = None
            ipam_driver = ipam.IPAM_REGISTRY.get_strategy(
                port_db["network"]["ipam_strategy"])
            if ip:
                if "ip_id" in ip:
                    ip_id = ip["ip_id"]
                    address = db_api.ip_address_find(
                        context,
                        id=ip_id,
                        tenant_id=context.tenant_id,
                        scope=db_api.ONE)
                elif "ip_address" in ip:
                    ip_address = ip["ip_address"]
                    net_address = netaddr.IPAddress(ip_address)
                    address = db_api.ip_address_find(
                        context,
                        ip_address=net_address,
                        network_id=port_db["network_id"],
                        tenant_id=context.tenant_id,
                        scope=db_api.ONE)
                    if not address:
                        address = ipam_driver.allocate_ip_address(
                            context,
                            port_db["network_id"],
                            id,
                            CONF.QUARK.ipam_reuse_after,
                            ip_address=ip_address)
            else:
                address = ipam_driver.allocate_ip_address(
                    context, port_db["network_id"], id,
                    CONF.QUARK.ipam_reuse_after)

        address["deallocated"] = 0

        already_contained = False
        for port_address in port_db["ip_addresses"]:
            if address["id"] == port_address["id"]:
                already_contained = True
                break

        if not already_contained:
            port_db["ip_addresses"].append(address)
    return v._make_port_dict(port_db)
Example #12
0
def set_port_status(port_id, status):
    """Set the port status."""
    LOG.debug(_("Set_port_status as %s called"), status)
    session = db.get_session()
    try:
        port = session.query(models_v2.Port).filter_by(id=port_id).one()
        port['status'] = status
        session.merge(port)
        session.flush()
    except exc.NoResultFound:
        raise q_exc.PortNotFound(port_id=port_id)
Example #13
0
def update_port(context, id, port):
    """Update values of a port.

    : param context: neutron api request context
    : param id: UUID representing the port to update.
    : param port: dictionary with keys indicating fields to update.
        valid keys are those that have a value of True for 'allow_put'
        as listed in the RESOURCE_ATTRIBUTE_MAP object in
        neutron/api/v2/attributes.py.
    """
    LOG.info("update_port %s for tenant %s" % (id, context.tenant_id))
    port_db = db_api.port_find(context, id=id, scope=db_api.ONE)
    if not port_db:
        raise exceptions.PortNotFound(port_id=id)

    address_pairs = []
    fixed_ips = port["port"].pop("fixed_ips", None)
    if fixed_ips:
        ipam_driver.deallocate_ip_address(
            context, port_db, ipam_reuse_after=CONF.QUARK.ipam_reuse_after)
        addresses = []
        for fixed_ip in fixed_ips:
            subnet_id = fixed_ip.get("subnet_id")
            ip_address = fixed_ip.get("ip_address")
            if not (subnet_id and ip_address):
                raise exceptions.BadRequest(
                    resource="fixed_ips",
                    msg="subnet_id and ip_address required")
            # Note: we don't allow overlapping subnets, thus subnet_id is
            #       ignored.
            addresses.append(
                ipam_driver.allocate_ip_address(context,
                                                port_db["network_id"],
                                                id,
                                                CONF.QUARK.ipam_reuse_after,
                                                ip_address=ip_address))
        port["port"]["addresses"] = addresses
        mac_address_string = str(
            netaddr.EUI(port_db.mac_address, dialect=netaddr.mac_unix))
        address_pairs = [{
            'mac_address': mac_address_string,
            'ip_address': address.get('address_readable', '')
        } for address in addresses]

    group_ids, security_groups = v.make_security_group_list(
        context, port["port"].pop("security_groups", None))
    net_driver.update_port(context,
                           port_id=port_db.backend_key,
                           security_groups=group_ids,
                           allowed_pairs=address_pairs)

    port["port"]["security_groups"] = security_groups
    port = db_api.port_update(context, port_db, **port["port"])
    return v._make_port_dict(port)
Example #14
0
 def test_update_routers_states_port_not_found(self):
     router1 = self._create_router()
     self._bind_router(router1['id'])
     port = {'id': 'foo', 'device_id': router1['id']}
     with mock.patch.object(self.core_plugin, 'get_ports',
                            return_value=[port]):
         with mock.patch.object(
                 self.core_plugin, 'update_port',
                 side_effect=n_exc.PortNotFound(port_id='foo')):
             states = {router1['id']: 'active'}
             self.plugin.update_routers_states(
                 self.admin_ctx, states, self.agent1['host'])
Example #15
0
 def test_delete_resource_port_handle_port_not_found(self):
     mgmt_port_id = 'fake_port_id'
     mocked_plugin = mock.MagicMock()
     mock_ctx = mock.MagicMock()
     mocked_plugin.delete_port = mock.MagicMock(
         side_effect=n_exc.PortNotFound(port_id=mgmt_port_id))
     with mock.patch.object(VIFHotPlugPluggingDriver,
                            '_core_plugin') as plugin:
         plugin.__get__ = mock.MagicMock(return_value=mocked_plugin)
         vif_plugging_driver = VIFHotPlugPluggingDriver()
         vif_plugging_driver._delete_resource_port(mock_ctx, mgmt_port_id)
         self.assertEqual(1, mocked_plugin.delete_port.call_count)
Example #16
0
 def clean_by_port(self, port):
     """Detach port from policy and cleanup data we don't need anymore."""
     port_id = port['port_id']
     if port_id in self.port_policies:
         del self.port_policies[port_id]
         for qos_policy_id, port_dict in self.qos_policy_ports.items():
             if port_id in port_dict:
                 del port_dict[port_id]
                 if not port_dict:
                     self._clean_policy_info(qos_policy_id)
                 return
     raise exceptions.PortNotFound(port_id=port['port_id'])
Example #17
0
def diagnose_port(context, id, fields):
    if not context.is_admin:
        raise exceptions.NotAuthorized()

    if id == "*":
        return {'ports': [_diag_port(context, port, fields) for
                port in db_api.port_find(context).all()]}
    db_port = db_api.port_find(context, id=id, scope=db_api.ONE)
    if not db_port:
        raise exceptions.PortNotFound(port_id=id, net_id='')
    port = _diag_port(context, db_port, fields)
    return {'ports': port}
Example #18
0
 def test_synchronize_port_not_found_in_db_no_raise(self):
     ctx = context.get_admin_context()
     with self._populate_data(ctx):
         # Put a port down to verify synchronization
         lp_uuid = self.fc._fake_lswitch_lport_dict.keys()[0]
         lport = self.fc._fake_lswitch_lport_dict[lp_uuid]
         q_port_id = self._get_tag_dict(lport['tags'])['q_port_id']
         lport['status'] = 'true'
         q_port_data = self._plugin._get_port(ctx, q_port_id)
         with mock.patch.object(self._plugin, '_get_port') as _get_port:
             _get_port.side_effect = n_exc.PortNotFound(
                 port_id=q_port_data['id'])
             self._plugin._synchronizer.synchronize_port(ctx, q_port_data)
Example #19
0
def set_port_status(port_id, status):
    """
    Set the status of the port.

    :param port_id: UUID representing the port
    :param status: string representing the new status
    """
    db_session = db.get_session()
    try:
        port = db_session.query(models_v2.Port).filter_by(id=port_id).one()
        port.status = status
    except exc.NoResultFound:
        raise q_exc.PortNotFound(port_id=port_id)
Example #20
0
def create_ip_address(context, ip_address):
    LOG.info("create_ip_address for tenant %s" % context.tenant_id)

    port = None
    ip_dict = ip_address["ip_address"]
    port_ids = ip_dict.get('port_ids')
    network_id = ip_dict.get('network_id')
    device_ids = ip_dict.get('device_ids')
    ip_version = ip_dict.get('version')
    ip_address = ip_dict.get('ip_address')

    ports = []
    if device_ids and not network_id:
        raise exceptions.BadRequest(
            resource="ip_addresses",
            msg="network_id is required if device_ids are supplied.")
    with context.session.begin():
        if network_id and device_ids:
            for device_id in device_ids:
                port = db_api.port_find(
                    context, network_id=network_id, device_id=device_id,
                    tenant_id=context.tenant_id, scope=db_api.ONE)
                ports.append(port)
        elif port_ids:
            for port_id in port_ids:
                port = db_api.port_find(context, id=port_id,
                                        tenant_id=context.tenant_id,
                                        scope=db_api.ONE)
                ports.append(port)

        if not ports:
            raise exceptions.PortNotFound(port_id=port_ids,
                                          net_id=network_id)

        address = ipam_driver.allocate_ip_address(
            context,
            port['network_id'],
            port['id'],
            CONF.QUARK.ipam_reuse_after,
            ip_version,
            ip_addresses=[ip_address])

        for port in ports:
            port["ip_addresses"].append(address)

    return v._make_ip_dict(address)
Example #21
0
def delete_port(context, id):
    """Delete a port.

    : param context: neutron api request context
    : param id: UUID representing the port to delete.
    """
    LOG.info("delete_port %s for tenant %s" % (id, context.tenant_id))

    port = db_api.port_find(context, id=id, scope=db_api.ONE)
    if not port:
        raise exceptions.PortNotFound(net_id=id)

    backend_key = port["backend_key"]
    mac_address = netaddr.EUI(port["mac_address"]).value
    ipam_driver.deallocate_mac_address(context, mac_address)
    ipam_driver.deallocate_ip_address(
        context, port, ipam_reuse_after=CONF.QUARK.ipam_reuse_after)
    db_api.port_delete(context, port)
    net_driver.delete_port(context, backend_key)
Example #22
0
 def test_prevent_l3_port_deletion_port_not_found(self, gp):
     # port not found doesn't prevent
     gp.return_value.get_port.side_effect = n_exc.PortNotFound(port_id='1')
     self.db.prevent_l3_port_deletion(None, None)
Example #23
0
 def test_port_delete_helper_tolerates_failure(self):
     plugin = manager.NeutronManager.get_plugin()
     with mock.patch.object(plugin,
                            "delete_port",
                            side_effect=exc.PortNotFound(port_id="123")):
         plugin._delete_ports(None, [mock.MagicMock()])
Example #24
0
def create_floatingip(context, content):
    """Allocate or reallocate a floating IP.

    :param context: neutron api request context.
    :param content: dictionary describing the floating ip, with keys
        as listed in the RESOURCE_ATTRIBUTE_MAP object in
        neutron/api/v2/attributes.py.  All keys will be populated.

    :returns: Dictionary containing details for the new floating IP.  If values
        are declared in the fields parameter, then only those keys will be
        present.
    """
    LOG.info('create_floatingip %s for tenant %s and body %s' %
             (id, context.tenant_id, content))
    tenant_id = content.get('tenant_id')
    network_id = content.get('floating_network_id')
    fixed_ip_address = content.get('fixed_ip_address')
    ip_address = content.get('floating_ip_address')
    port_id = content.get('port_id')

    if not tenant_id:
        tenant_id = context.tenant_id

    if not network_id:
        raise exceptions.BadRequest(resource='floating_ip',
                                    msg='floating_network_id is required.')

    network = db_api.network_find(context, id=network_id, scope=db_api.ONE)

    if not network:
        raise exceptions.NetworkNotFound(net_id=network_id)

    fixed_ip = None
    port = None
    if port_id:
        port = db_api.port_find(context, id=port_id, scope=db_api.ONE)

        if not port:
            raise exceptions.PortNotFound(port_id=port_id)

        if not port.ip_addresses or len(port.ip_addresses) == 0:
            raise qex.NoAvailableFixedIpsForPort(port_id=port_id)

        if not fixed_ip_address:
            fixed_ip = _get_next_available_fixed_ip(port)
            if not fixed_ip:
                raise qex.NoAvailableFixedIpsForPort(
                    port_id=port_id)
        else:
            fixed_ip = next((ip for ip in port.ip_addresses
                            if (ip['address_readable'] == fixed_ip_address and
                                ip.get('address_type') == ip_types.FIXED)),
                            None)

            if not fixed_ip:
                raise qex.FixedIpDoesNotExistsForPort(
                    fixed_ip=fixed_ip_address, port_id=port_id)

            if any(ip for ip in port.ip_addresses
                   if (ip.get('address_type') == ip_types.FLOATING and
                       ip.fixed_ip['address_readable'] == fixed_ip_address)):
                raise qex.PortAlreadyContainsFloatingIp(
                    port_id=port_id)

    new_addresses = []
    ip_addresses = []
    if ip_address:
        ip_addresses.append(ip_address)

    seg_name = CONF.QUARK.floating_ip_segment_name
    strategy_name = CONF.QUARK.floating_ip_ipam_strategy

    if strategy_name.upper() == 'NETWORK':
        strategy_name = network.get("ipam_strategy")

    ipam_driver = ipam.IPAM_REGISTRY.get_strategy(strategy_name)
    ipam_driver.allocate_ip_address(context, new_addresses, network_id,
                                    port_id, CONF.QUARK.ipam_reuse_after,
                                    seg_name, version=4,
                                    ip_addresses=ip_addresses,
                                    address_type=ip_types.FLOATING)

    flip = new_addresses[0]

    if fixed_ip and port:
        context.session.begin()
        try:
            flip = db_api.port_associate_ip(context, [port], flip, [port_id])
            flip = db_api.floating_ip_associate_fixed_ip(context, flip,
                                                         fixed_ip)

            flip_driver = registry.DRIVER_REGISTRY.get_driver()

            flip_driver.register_floating_ip(flip, port, fixed_ip)
            context.session.commit()
        except Exception:
            context.session.rollback()
            raise

    return v._make_floating_ip_dict(flip, port_id)
Example #25
0
def update_floatingip(context, id, content):
    """Update an existing floating IP.

    :param context: neutron api request context.
    :param id: id of the floating ip
    :param content: dictionary with keys indicating fields to update.
        valid keys are those that have a value of True for 'allow_put'
        as listed in the RESOURCE_ATTRIBUTE_MAP object in
        neutron/api/v2/attributes.py.

    :returns: Dictionary containing details for the new floating IP.  If values
        are declared in the fields parameter, then only those keys will be
        present.
    """

    LOG.info('update_floatingip %s for tenant %s and body %s' %
             (id, context.tenant_id, content))

    if 'port_id' not in content:
        raise exceptions.BadRequest(resource='floating_ip',
                                    msg='port_id is required.')

    port_id = content.get('port_id')
    port = None
    fixed_ip = None
    current_port = None

    context.session.begin()
    try:
        flip = db_api.floating_ip_find(context, id=id, scope=db_api.ONE)
        if not flip:
            raise qex.FloatingIpNotFound(id=id)

        current_ports = flip.ports

        if current_ports and len(current_ports) > 0:
            current_port = current_ports[0]

        if not port_id and not current_port:
            raise qex.FloatingIpUpdateNoPortIdSupplied()

        if port_id:
            port = db_api.port_find(context, id=port_id, scope=db_api.ONE)
            if not port:
                raise exceptions.PortNotFound(port_id=port_id)

            if any(ip for ip in port.ip_addresses
                   if (ip.get('address_type') == ip_types.FLOATING)):
                raise qex.PortAlreadyContainsFloatingIp(port_id=port_id)

            if current_port and current_port.id == port_id:
                d = dict(flip_id=id, port_id=port_id)
                raise qex.PortAlreadyAssociatedToFloatingIp(**d)

            fixed_ip = _get_next_available_fixed_ip(port)
            LOG.info('new fixed ip: %s' % fixed_ip)
            if not fixed_ip:
                raise qex.NoAvailableFixedIpsForPort(port_id=port_id)

        LOG.info('current ports: %s' % current_ports)

        if current_port:
            flip = db_api.port_disassociate_ip(context, [current_port], flip)

        if flip.fixed_ip:
            flip = db_api.floating_ip_disassociate_fixed_ip(context, flip)

        if port:
            flip = db_api.port_associate_ip(context, [port], flip, [port_id])
            flip = db_api.floating_ip_associate_fixed_ip(context, flip,
                                                         fixed_ip)

        flip_driver = registry.DRIVER_REGISTRY.get_driver()

        if port:
            if current_port:
                flip_driver.update_floating_ip(flip, port, fixed_ip)
            else:
                flip_driver.register_floating_ip(flip, port, fixed_ip)
        else:
            flip_driver.remove_floating_ip(flip)

        context.session.commit()
    except (qex.RegisterFloatingIpFailure, qex.RemoveFloatingIpFailure):
        context.session.rollback()
        raise

    # Note(alanquillin) The ports parameters on the model is not
    # properly getting cleaned up when removed.  Manually cleaning them up.
    # Need to fix the db api to correctly update the model.
    if not port:
        flip.ports = []

    return v._make_floating_ip_dict(flip, port_id)
Example #26
0
 def test_update_device_up_notify_not_sent_with_port_not_found(self):
     self.plugin._get_port.side_effect = (exceptions.PortNotFound(
         port_id='foo_port_id'))
     notify = self._test_update_device_up()
     self.assertFalse(notify.call_count)
 def test_get_dhcp_port_create_new_with_failure_on_port_update(self):
     self._test_get_dhcp_port_create_new(
         update_port=n_exc.PortNotFound(port_id='foo'))
Example #28
0
 def _get_port(self, context, id):
     try:
         port = self._get_by_id(context, models_v2.Port, id)
     except exc.NoResultFound:
         raise n_exc.PortNotFound(port_id=id)
     return port
Example #29
0
def update_port(context, id, port):
    """Update values of a port.

    : param context: neutron api request context
    : param id: UUID representing the port to update.
    : param port: dictionary with keys indicating fields to update.
        valid keys are those that have a value of True for 'allow_put'
        as listed in the RESOURCE_ATTRIBUTE_MAP object in
        neutron/api/v2/attributes.py.
    """
    LOG.info("update_port %s for tenant %s" % (id, context.tenant_id))
    port_db = db_api.port_find(context, id=id, scope=db_api.ONE)
    if not port_db:
        raise exceptions.PortNotFound(port_id=id)

    port_dict = port["port"]
    fixed_ips = port_dict.pop("fixed_ips", None)

    admin_only = ["mac_address", "device_owner", "bridge", "admin_state_up",
                  "device_id"]
    always_filter = ["network_id", "backend_key"]
    utils.filter_body(context, port_dict, admin_only=admin_only,
                      always_filter=always_filter)

    # Pre-check the requested fixed_ips before making too many db trips.
    # Note that this is the only check we need, since this call replaces
    # the entirety of the IP addresses document if fixed_ips are provided.
    if fixed_ips:
        quota.QUOTAS.limit_check(context, context.tenant_id,
                                 fixed_ips_per_port=len(fixed_ips))

    # TODO(anyone): security groups are not currently supported on port create,
    #               nor on isolated networks today. Please see RM8615
    new_security_groups = utils.pop_param(port_dict, "security_groups")
    if new_security_groups is not None:
        if not STRATEGY.is_parent_network(port_db["network_id"]):
            raise q_exc.TenantNetworkSecurityGroupsNotImplemented()

    if new_security_groups is not None and not port_db["device_id"]:
        raise q_exc.SecurityGroupsRequireDevice()

    group_ids, security_group_mods = _make_security_group_list(
        context, new_security_groups)
    quota.QUOTAS.limit_check(context, context.tenant_id,
                             security_groups_per_port=len(group_ids))

    if fixed_ips is not None:
        # NOTE(mdietz): we want full control over IPAM since
        #              we're allocating by subnet instead of
        #              network.
        ipam_driver = ipam.IPAM_REGISTRY.get_strategy(
            ipam.QuarkIpamANY.get_name())

        addresses, subnet_ids = [], []
        ip_addresses = {}

        for fixed_ip in fixed_ips:
            subnet_id = fixed_ip.get("subnet_id")
            ip_address = fixed_ip.get("ip_address")
            if not (subnet_id or ip_address):
                raise exceptions.BadRequest(
                    resource="fixed_ips",
                    msg="subnet_id or ip_address required")

            if ip_address and not subnet_id:
                raise exceptions.BadRequest(
                    resource="fixed_ips",
                    msg="subnet_id required for ip_address allocation")

            if subnet_id and ip_address:
                ip_netaddr = netaddr.IPAddress(ip_address).ipv6()
                ip_addresses[ip_netaddr] = subnet_id
            else:
                subnet_ids.append(subnet_id)

        port_ips = set([netaddr.IPAddress(int(a["address"]))
                        for a in port_db["ip_addresses"]])
        new_ips = set([a for a in ip_addresses.keys()])

        ips_to_allocate = list(new_ips - port_ips)
        ips_to_deallocate = list(port_ips - new_ips)

        for ip in ips_to_allocate:
            if ip in ip_addresses:
                # NOTE: Fix for RM10187 - we were losing the list of IPs if
                #       more than one IP was to be allocated. Track an
                #       aggregate list instead, and add it to the running total
                #       after each allocate
                allocated = []
                ipam_driver.allocate_ip_address(
                    context, allocated, port_db["network_id"],
                    port_db["id"], reuse_after=None, ip_addresses=[ip],
                    subnets=[ip_addresses[ip]])
                addresses.extend(allocated)

        for ip in ips_to_deallocate:
            ipam_driver.deallocate_ips_by_port(
                context, port_db, ip_address=ip)

        for subnet_id in subnet_ids:
            ipam_driver.allocate_ip_address(
                context, addresses, port_db["network_id"], port_db["id"],
                reuse_after=CONF.QUARK.ipam_reuse_after,
                subnets=[subnet_id])

        # Need to return all existing addresses and the new ones
        if addresses:
            port_dict["addresses"] = port_db["ip_addresses"]
            port_dict["addresses"].extend(addresses)

    net_driver = registry.DRIVER_REGISTRY.get_driver(
        port_db.network["network_plugin"])

    # TODO(anyone): What do we want to have happen here if this fails? Is it
    #               ok to continue to keep the IPs but fail to apply security
    #               groups? Is there a clean way to have a multi-status? Since
    #               we're in a beta-y status, I'm going to let this sit for
    #               a future patch where we have time to solve it well.
    kwargs = {}
    if new_security_groups is not None:
        kwargs["security_groups"] = security_group_mods
    net_driver.update_port(context, port_id=port_db["backend_key"],
                           mac_address=port_db["mac_address"],
                           device_id=port_db["device_id"],
                           **kwargs)

    port_dict["security_groups"] = security_group_mods

    with context.session.begin():
        port = db_api.port_update(context, port_db, **port_dict)

    # NOTE(mdietz): fix for issue 112, we wanted the IPs to be in
    #              allocated_at order, so get a fresh object every time
    if port_db in context.session:
        context.session.expunge(port_db)
    port_db = db_api.port_find(context, id=id, scope=db_api.ONE)

    return v._make_port_dict(port_db)
Example #30
0
 def get_port_db(self, context, port_id):
     try:
         port = self._get_by_id(context, netforce_model.Port, port_id)
     except orm_exc.NoResultFound:
         raise n_exc.PortNotFound(port_id=port_id)
     return port