Example #1
0
    def test_update_port_associations_for_ip(self, associate_mock,
                                             disassociate_mock,
                                             get_associations_mock):
        self.context.session.add = mock.Mock()
        self.context.session.delete = mock.Mock()
        mock_ports = [models.Port(id=str(x), network_id="2", ip_addresses=[])
                      for x in xrange(4)]
        mock_address = models.IPAddress(id="1", address=3232235876,
                                        address_readable="192.168.1.100",
                                        subnet_id="1", network_id="2",
                                        version=4, used_by_tenant_id="1")
        mock_address.ports = mock_ports
        new_port_list = mock_ports[1:3]
        new_port_list.append(models.Port(id="4", network_id="2",
                             ip_addresses=[]))
        get_associations_mock.return_value = mock_ports
        # NOTE(thomasem): Should be the new address after associating
        # any new ports in the list.
        mock_new_address = associate_mock.return_value

        db_api.update_port_associations_for_ip(self.context,
                                               new_port_list,
                                               mock_address)

        associate_mock.assert_called_once_with(self.context,
                                               set([new_port_list[2]]),
                                               mock_address)

        disassociate_mock.assert_called_once_with(self.context,
                                                  set([mock_ports[0],
                                                       mock_ports[3]]),
                                                  mock_new_address)
Example #2
0
def delete_ip_address(context, id):
    """Delete an ip address.

    : param context: neutron api request context
    : param id: UUID representing the ip address to delete.
    """
    LOG.info("delete_ip_address %s for tenant %s" % (id, context.tenant_id))
    with context.session.begin():
        ip_address = db_api.ip_address_find(
            context, id=id, scope=db_api.ONE)
        if not ip_address or ip_address.deallocated:
            raise q_exc.IpAddressNotFound(addr_id=id)

        iptype = ip_address.address_type
        if iptype == ip_types.FIXED and not CONF.QUARK.ipaddr_allow_fixed_ip:
            raise n_exc.BadRequest(
                resource="ip_addresses",
                msg="Fixed ips cannot be updated using this interface.")

        if ip_address.has_any_shared_owner():
            raise q_exc.PortRequiresDisassociation()

        db_api.update_port_associations_for_ip(context, [], ip_address)

        ipam_driver.deallocate_ip_address(context, ip_address)
Example #3
0
def delete_ip_address(context, id):
    """Delete an ip address.

    : param context: neutron api request context
    : param id: UUID representing the ip address to delete.
    """
    LOG.info("delete_ip_address %s for tenant %s" % (id, context.tenant_id))
    with context.session.begin():
        ip_address = db_api.ip_address_find(context, id=id, scope=db_api.ONE)
        if not ip_address or ip_address.deallocated:
            raise q_exc.IpAddressNotFound(addr_id=id)

        iptype = ip_address.address_type
        if iptype == ip_types.FIXED and not CONF.QUARK.ipaddr_allow_fixed_ip:
            raise n_exc.BadRequest(
                resource="ip_addresses",
                msg="Fixed ips cannot be updated using this interface.")

        if ip_address.has_any_shared_owner():
            raise q_exc.PortRequiresDisassociation()

        db_api.update_port_associations_for_ip(context, [], ip_address)

        ipam_driver.deallocate_ip_address(context, ip_address)
Example #4
0
def update_ip_address(context, id, ip_address):
    LOG.info("update_ip_address %s for tenant %s" %
             (id, context.tenant_id))
    ports = []
    with context.session.begin():
        address = db_api.ip_address_find(
            context, id=id, tenant_id=context.tenant_id, scope=db_api.ONE)
        if not address:
            raise exceptions.NotFound(
                message="No IP address found with id=%s" % id)

        reset = ip_address['ip_address'].get('reset_allocation_time', False)
        if reset and address['deallocated'] == 1:
            if context.is_admin:
                LOG.info("IP's deallocated time being manually reset")
                address['deallocated_at'] = _get_deallocated_override()
            else:
                msg = "Modification of reset_allocation_time requires admin"
                raise webob.exc.HTTPForbidden(detail=msg)

        port_ids = ip_address['ip_address'].get('port_ids')

        if port_ids:
            _raise_if_shared_and_enabled(ip_address, address)
            ports = db_api.port_find(context, tenant_id=context.tenant_id,
                                     id=port_ids, scope=db_api.ALL)
            # NOTE(name): could be considered inefficient because we're
            # converting to a list to check length. Maybe revisit
            if len(ports) != len(port_ids):
                raise exceptions.NotFound(
                    message="No ports not found with ids=%s" % port_ids)

            validate_ports_on_network_and_same_segment(ports,
                                                       address["network_id"])
            validate_port_ip_quotas(context, ports)

            LOG.info("Updating IP address, %s, to only be used by the"
                     "following ports:  %s" % (address.address_readable,
                                               [p.id for p in ports]))
            new_address = db_api.update_port_associations_for_ip(context,
                                                                 ports,
                                                                 address)
        else:
            if port_ids is not None:
                ipam_driver.deallocate_ip_address(
                    context, address)
            return v._make_ip_dict(address)
    return v._make_ip_dict(new_address)
Example #5
0
def update_ip_address(context, id, ip_address):
    """Due to NCP-1592 ensure that address_type cannot change after update."""
    LOG.info("update_ip_address %s for tenant %s" % (id, context.tenant_id))
    ports = []
    if 'ip_address' not in ip_address:
        raise n_exc.BadRequest(resource="ip_addresses",
                               msg="Invalid request body.")
    with context.session.begin():
        address = db_api.ip_address_find(context, id=id, scope=db_api.ONE)
        if not address:
            raise q_exc.IpAddressNotFound(addr_id=id)
        iptype = address.address_type
        if iptype == ip_types.FIXED and not CONF.QUARK.ipaddr_allow_fixed_ip:
            raise n_exc.BadRequest(
                resource="ip_addresses",
                msg="Fixed ips cannot be updated using this interface.")

        reset = ip_address['ip_address'].get('reset_allocation_time', False)
        if reset and address['deallocated'] == 1:
            if context.is_admin:
                LOG.info("IP's deallocated time being manually reset")
                address['deallocated_at'] = _get_deallocated_override()
            else:
                msg = "Modification of reset_allocation_time requires admin"
                raise webob.exc.HTTPForbidden(detail=msg)

        port_ids = ip_address['ip_address'].get('port_ids', None)

        if port_ids is not None and not port_ids:
            raise n_exc.BadRequest(
                resource="ip_addresses",
                msg="Cannot be updated with empty port_id list")

        if iptype == ip_types.SHARED:
            has_owner = address.has_any_shared_owner()

        if port_ids:
            if iptype == ip_types.FIXED and len(port_ids) > 1:
                raise n_exc.BadRequest(
                    resource="ip_addresses",
                    msg="Fixed ips cannot be updated with more than one port.")

            _raise_if_shared_and_enabled(ip_address, address)
            ports = db_api.port_find(context,
                                     tenant_id=context.tenant_id,
                                     id=port_ids,
                                     scope=db_api.ALL)
            # NOTE(name): could be considered inefficient because we're
            # converting to a list to check length. Maybe revisit
            if len(ports) != len(port_ids):
                raise n_exc.PortNotFound(port_id=port_ids)

            validate_and_fetch_segment(ports, address["network_id"])
            validate_port_ip_quotas(context, address.network_id, ports)

            if iptype == ip_types.SHARED and has_owner:
                for assoc in address.associations:
                    pid = assoc.port_id
                    if pid not in port_ids and 'none' != assoc.service:
                        raise q_exc.PortRequiresDisassociation()

            LOG.info("Updating IP address, %s, to only be used by the"
                     "following ports:  %s" %
                     (address.address_readable, [p.id for p in ports]))
            new_address = db_api.update_port_associations_for_ip(
                context, ports, address)
        elif iptype == ip_types.SHARED and has_owner:
            raise q_exc.PortRequiresDisassociation()
        else:
            ipam_driver.deallocate_ip_address(context, address)
            return v._make_ip_dict(address)
    return v._make_ip_dict(new_address)
Example #6
0
def update_ip_address(context, id, ip_address):
    """Due to NCP-1592 ensure that address_type cannot change after update."""
    LOG.info("update_ip_address %s for tenant %s" % (id, context.tenant_id))
    ports = []
    if 'ip_address' not in ip_address:
        raise n_exc.BadRequest(resource="ip_addresses",
                               msg="Invalid request body.")
    with context.session.begin():
        address = db_api.ip_address_find(context, id=id, scope=db_api.ONE)
        if not address:
            raise q_exc.IpAddressNotFound(addr_id=id)
        iptype = address.address_type
        if iptype == ip_types.FIXED and not CONF.QUARK.ipaddr_allow_fixed_ip:
            raise n_exc.BadRequest(
                resource="ip_addresses",
                msg="Fixed ips cannot be updated using this interface.")

        reset = ip_address['ip_address'].get('reset_allocation_time', False)
        if reset and address['deallocated'] == 1:
            if context.is_admin:
                LOG.info("IP's deallocated time being manually reset")
                address['deallocated_at'] = _get_deallocated_override()
            else:
                msg = "Modification of reset_allocation_time requires admin"
                raise webob.exc.HTTPForbidden(detail=msg)

        port_ids = ip_address['ip_address'].get('port_ids', None)

        if port_ids is not None and not port_ids:
            raise n_exc.BadRequest(
                resource="ip_addresses",
                msg="Cannot be updated with empty port_id list")

        if iptype == ip_types.SHARED:
            has_owner = address.has_any_shared_owner()

        if port_ids:
            if iptype == ip_types.FIXED and len(port_ids) > 1:
                raise n_exc.BadRequest(
                    resource="ip_addresses",
                    msg="Fixed ips cannot be updated with more than one port.")

            _raise_if_shared_and_enabled(ip_address, address)
            ports = db_api.port_find(context, tenant_id=context.tenant_id,
                                     id=port_ids, scope=db_api.ALL)
            # NOTE(name): could be considered inefficient because we're
            # converting to a list to check length. Maybe revisit
            if len(ports) != len(port_ids):
                raise n_exc.PortNotFound(port_id=port_ids)

            validate_and_fetch_segment(ports, address["network_id"])
            validate_port_ip_quotas(context, address.network_id, ports)

            if iptype == ip_types.SHARED and has_owner:
                for assoc in address.associations:
                    pid = assoc.port_id
                    if pid not in port_ids and 'none' != assoc.service:
                        raise q_exc.PortRequiresDisassociation()

            LOG.info("Updating IP address, %s, to only be used by the"
                     "following ports:  %s" % (address.address_readable,
                                               [p.id for p in ports]))
            new_address = db_api.update_port_associations_for_ip(context,
                                                                 ports,
                                                                 address)
        elif iptype == ip_types.SHARED and has_owner:
            raise q_exc.PortRequiresDisassociation()
        else:
            ipam_driver.deallocate_ip_address(context, address)
            return v._make_ip_dict(address)
    return v._make_ip_dict(new_address)