Example #1
0
 def deallocate_mac_address(self, context, address):
     mac = db_api.mac_address_find(context, address=address,
                                   scope=db_api.ONE)
     if not mac:
         raise exceptions.NotFound(
             message="No MAC address %s found" % netaddr.EUI(address))
     db_api.mac_address_update(context, mac, deallocated=True,
                               deallocated_at=timeutils.utcnow())
Example #2
0
    def allocate_mac_address(self,
                             context,
                             net_id,
                             port_id,
                             reuse_after,
                             mac_address=None):
        if mac_address:
            mac_address = netaddr.EUI(mac_address).value

        deallocated_mac = db_api.mac_address_find(context,
                                                  reuse_after=reuse_after,
                                                  scope=db_api.ONE,
                                                  address=mac_address)
        if deallocated_mac:
            return db_api.mac_address_update(context,
                                             deallocated_mac,
                                             deallocated=False,
                                             deallocated_at=None)

        ranges = db_api.mac_address_range_find_allocation_counts(
            context, address=mac_address)
        for result in ranges:
            rng, addr_count = result
            if rng["last_address"] - rng["first_address"] <= addr_count:
                continue

            next_address = None
            if mac_address:
                next_address = mac_address
            else:
                address = True
                while address:
                    next_address = rng["next_auto_assign_mac"]
                    rng["next_auto_assign_mac"] = next_address + 1
                    address = db_api.mac_address_find(
                        context,
                        tenant_id=context.tenant_id,
                        scope=db_api.ONE,
                        address=next_address)

            address = db_api.mac_address_create(context,
                                                address=next_address,
                                                mac_address_range_id=rng["id"])
            return address

        raise exceptions.MacAddressGenerationFailure(net_id=net_id)
Example #3
0
 def test_delete_mac_with_mac_range_do_not_use(self):
     macs = lambda mar: db_api.mac_address_find(
         self.context, mac_address_range_id=mar["id"], scope=db_api.ALL)
     with self._stubs(do_not_use=True) as mar:
         self.assertEqual(len(macs(mar)), 1)
         with self.assertRaises(n_exc_ext.MacAddressGenerationFailure):
             self.ipam.allocate_mac_address(self.context, 0, 0, 0)
         self.assertEqual(len(macs(mar)), 0)
Example #4
0
 def test_delete_mac_with_mac_range_do_not_use(self):
     macs = lambda mar: db_api.mac_address_find(
         self.context,
         mac_address_range_id=mar["id"],
         scope=db_api.ALL)
     with self._stubs(do_not_use=True) as mar:
         self.assertEqual(len(macs(mar)), 1)
         with self.assertRaises(exceptions.MacAddressGenerationFailure):
             self.ipam.allocate_mac_address(self.context, 0, 0, 0)
         self.assertEqual(len(macs(mar)), 0)
Example #5
0
 def deallocate_mac_address(self, context, address):
     mac = db_api.mac_address_find(context,
                                   address=address,
                                   scope=db_api.ONE)
     if not mac:
         raise exceptions.NotFound(message="No MAC address %s found" %
                                   netaddr.EUI(address))
     db_api.mac_address_update(context,
                               mac,
                               deallocated=True,
                               deallocated_at=timeutils.utcnow())
Example #6
0
    def allocate_mac_address(self, context, net_id, port_id, reuse_after,
                             mac_address=None):
        if mac_address:
            mac_address = netaddr.EUI(mac_address).value

        with context.session.begin(subtransactions=True):
            deallocated_mac = db_api.mac_address_find(
                context, lock_mode=True, reuse_after=reuse_after,
                scope=db_api.ONE, address=mac_address)
            if deallocated_mac:
                return db_api.mac_address_update(
                    context, deallocated_mac, deallocated=False,
                    deallocated_at=None)

        with context.session.begin(subtransactions=True):
            ranges = db_api.mac_address_range_find_allocation_counts(
                context, address=mac_address)
            for result in ranges:
                rng, addr_count = result
                last = rng["last_address"]
                first = rng["first_address"]
                if last - first <= addr_count:
                    continue
                next_address = None
                if mac_address:
                    next_address = mac_address
                else:
                    address = True
                    while address:
                        next_address = rng["next_auto_assign_mac"]
                        rng["next_auto_assign_mac"] = next_address + 1
                        address = db_api.mac_address_find(
                            context, tenant_id=context.tenant_id,
                            scope=db_api.ONE, address=next_address)

                address = db_api.mac_address_create(
                    context, address=next_address,
                    mac_address_range_id=rng["id"])
                return address

        raise exceptions.MacAddressGenerationFailure(net_id=net_id)
Example #7
0
    def deallocate_mac_address(self, context, address):
        admin_context = context.elevated()
        mac = db_api.mac_address_find(admin_context, address=address,
                                      scope=db_api.ONE)
        if not mac:
            raise exceptions.NotFound(
                message="No MAC address %s found" % netaddr.EUI(address))

        if mac["mac_address_range"]["do_not_use"]:
            db_api.mac_address_delete(admin_context, mac)
        else:
            db_api.mac_address_update(admin_context, mac, deallocated=True,
                                      deallocated_at=timeutils.utcnow())
Example #8
0
File: ipam.py Project: roaet/quark
    def deallocate_mac_address(self, context, address, **kwargs):
        admin_context = context.elevated()
        mac = db_api.mac_address_find(admin_context, address=address,
                                      scope=db_api.ONE)
        if not mac:
            raise q_exc.MacAddressNotFound(
                mac_address_id=address,
                readable_mac=netaddr.EUI(address))

        if (mac["mac_address_range"] is None or
                mac["mac_address_range"]["do_not_use"]):
            db_api.mac_address_delete(admin_context, mac)
        else:
            db_api.mac_address_update(admin_context, mac, deallocated=True,
                                      deallocated_at=timeutils.utcnow())
Example #9
0
    def deallocate_mac_address(self, context, address, **kwargs):
        admin_context = context.elevated()
        mac = db_api.mac_address_find(admin_context, address=address,
                                      scope=db_api.ONE)
        if not mac:
            raise q_exc.MacAddressNotFound(
                mac_address_id=address,
                readable_mac=netaddr.EUI(address))

        if (mac["mac_address_range"] is None or
                mac["mac_address_range"]["do_not_use"]):
            db_api.mac_address_delete(admin_context, mac)
        else:
            db_api.mac_address_update(admin_context, mac, deallocated=True,
                                      deallocated_at=timeutils.utcnow())
Example #10
0
    def deallocate_mac_address(self, context, address):
        admin_context = context.elevated()
        mac = db_api.mac_address_find(admin_context,
                                      address=address,
                                      scope=db_api.ONE)
        if not mac:
            raise exceptions.NotFound(message="No MAC address %s found" %
                                      netaddr.EUI(address))

        if mac["mac_address_range"]["do_not_use"]:
            db_api.mac_address_delete(admin_context, mac)
        else:
            db_api.mac_address_update(admin_context,
                                      mac,
                                      deallocated=True,
                                      deallocated_at=timeutils.utcnow())
Example #11
0
    def allocate_mac_address(self,
                             context,
                             net_id,
                             port_id,
                             reuse_after,
                             mac_address=None):
        if mac_address:
            mac_address = netaddr.EUI(mac_address).value

        for retry in xrange(cfg.CONF.QUARK.mac_address_retry_max):
            try:
                with context.session.begin():
                    deallocated_mac = db_api.mac_address_find(
                        context,
                        lock_mode=True,
                        reuse_after=reuse_after,
                        deallocated=True,
                        scope=db_api.ONE,
                        address=mac_address,
                        order_by="address ASC")
                    if deallocated_mac:
                        return db_api.mac_address_update(context,
                                                         deallocated_mac,
                                                         deallocated=False,
                                                         deallocated_at=None)
                    break
            except Exception:
                LOG.exception("Error in mac reallocate...")
                continue

        # This could fail if a large chunk of MACs were chosen explicitly,
        # but under concurrent load enough MAC creates should iterate without
        # any given thread exhausting its retry count.
        for retry in xrange(cfg.CONF.QUARK.mac_address_retry_max):
            next_address = None
            with context.session.begin():
                try:
                    fn = db_api.mac_address_range_find_allocation_counts
                    mac_range = fn(context, address=mac_address)

                    if not mac_range:
                        break

                    rng, addr_count = mac_range

                    last = rng["last_address"]
                    first = rng["first_address"]
                    if (last - first + 1) <= addr_count:
                        # Somehow, the range got filled up without us
                        # knowing, so set the next_auto_assign to be -1
                        # so we never try to create new ones
                        # in this range
                        rng["next_auto_assign_mac"] = -1
                        context.session.add(rng)
                        continue

                    if mac_address:
                        next_address = mac_address
                    else:
                        next_address = rng["next_auto_assign_mac"]
                        next_auto = next_address + 1
                        if next_auto > last:
                            next_auto = -1
                        db_api.mac_address_range_update(
                            context, rng, next_auto_assign_mac=next_auto)

                except Exception:
                    LOG.exception("Error in updating mac range")
                    continue

            # Based on the above, this should only fail if a MAC was
            # was explicitly chosen at some point. As such, fall through
            # here and get in line for a new MAC address to try
            try:
                with context.session.begin():
                    address = db_api.mac_address_create(
                        context,
                        address=next_address,
                        mac_address_range_id=rng["id"])
                    return address
            except Exception:
                LOG.exception("Error in creating mac. MAC possibly duplicate")
                continue

        raise exceptions.MacAddressGenerationFailure(net_id=net_id)
Example #12
0
    def allocate_mac_address(self, context, net_id, port_id, reuse_after,
                             mac_address=None):
        if mac_address:
            mac_address = netaddr.EUI(mac_address).value

        kwargs = {"network_id": net_id, "port_id": port_id,
                  "mac_address": mac_address}
        LOG.info(("Attempting to allocate a new MAC address "
                  "[{0}]").format(utils.pretty_kwargs(**kwargs)))

        for retry in xrange(CONF.QUARK.mac_address_retry_max):
            LOG.info("Attemping to reallocate deallocated MAC (step 1 of 3),"
                     " attempt {0} of {1}".format(
                         retry + 1, CONF.QUARK.mac_address_retry_max))
            try:
                with context.session.begin():
                    deallocated_mac = db_api.mac_address_find(
                        context, lock_mode=True, reuse_after=reuse_after,
                        deallocated=True, scope=db_api.ONE,
                        address=mac_address, order_by="address ASC")

                    if deallocated_mac:
                        dealloc = netaddr.EUI(deallocated_mac["address"])
                        LOG.info("Found a suitable deallocated MAC {0}".format(
                            str(dealloc)))

                        address = db_api.mac_address_update(
                            context, deallocated_mac, deallocated=False,
                            deallocated_at=None)

                        LOG.info("MAC assignment for port ID {0} completed "
                                 "with address {1}".format(port_id, dealloc))
                        return address
                    break
            except Exception:
                LOG.exception("Error in mac reallocate...")
                continue

        LOG.info("Couldn't find a suitable deallocated MAC, attempting "
                 "to create a new one")

        # This could fail if a large chunk of MACs were chosen explicitly,
        # but under concurrent load enough MAC creates should iterate without
        # any given thread exhausting its retry count.
        for retry in xrange(CONF.QUARK.mac_address_retry_max):
            LOG.info("Attemping to find a range to create a new MAC in "
                     "(step 2 of 3), attempt {0} of {1}".format(
                         retry + 1, CONF.QUARK.mac_address_retry_max))
            next_address = None
            with context.session.begin():
                try:
                    fn = db_api.mac_address_range_find_allocation_counts
                    mac_range = fn(context, address=mac_address)

                    if not mac_range:
                        LOG.info("No MAC ranges could be found given "
                                 "the criteria")
                        break

                    rng, addr_count = mac_range
                    LOG.info("Found a MAC range {0}".format(rng["cidr"]))

                    last = rng["last_address"]
                    first = rng["first_address"]
                    if (last - first + 1) <= addr_count:
                        # Somehow, the range got filled up without us
                        # knowing, so set the next_auto_assign to be -1
                        # so we never try to create new ones
                        # in this range
                        rng["next_auto_assign_mac"] = -1
                        context.session.add(rng)
                        LOG.info("MAC range {0} is full".format(rng["cidr"]))
                        continue

                    if mac_address:
                        next_address = mac_address
                    else:
                        next_address = rng["next_auto_assign_mac"]
                        next_auto = next_address + 1
                        if next_auto > last:
                            next_auto = -1
                        db_api.mac_address_range_update(
                            context, rng, next_auto_assign_mac=next_auto)

                except Exception:
                    LOG.exception("Error in updating mac range")
                    continue

            # Based on the above, this should only fail if a MAC was
            # was explicitly chosen at some point. As such, fall through
            # here and get in line for a new MAC address to try
            try:
                mac_readable = str(netaddr.EUI(next_address))
                LOG.info("Attempting to create new MAC {0} "
                         "(step 3 of 3)".format(mac_readable))
                with context.session.begin():
                    address = db_api.mac_address_create(
                        context, address=next_address,
                        mac_address_range_id=rng["id"])
                    LOG.info("MAC assignment for port ID {0} completed with "
                             "address {1}".format(port_id, mac_readable))
                    return address
            except Exception:
                LOG.info("Failed to create new MAC {0}".format(mac_readable))
                LOG.exception("Error in creating mac. MAC possibly duplicate")
                continue

        raise exceptions.MacAddressGenerationFailure(net_id=net_id)
Example #13
0
    def allocate_mac_address(self, context, net_id, port_id, reuse_after,
                             mac_address=None):
        if mac_address:
            mac_address = netaddr.EUI(mac_address).value

        for retry in xrange(cfg.CONF.QUARK.mac_address_retry_max):
            try:
                with context.session.begin():
                    deallocated_mac = db_api.mac_address_find(
                        context, lock_mode=True, reuse_after=reuse_after,
                        deallocated=True, scope=db_api.ONE,
                        address=mac_address, order_by="address ASC")
                    if deallocated_mac:
                        return db_api.mac_address_update(
                            context, deallocated_mac, deallocated=False,
                            deallocated_at=None)
                    break
            except Exception:
                LOG.exception("Error in mac reallocate...")
                continue

        # This could fail if a large chunk of MACs were chosen explicitly,
        # but under concurrent load enough MAC creates should iterate without
        # any given thread exhausting its retry count.
        for retry in xrange(cfg.CONF.QUARK.mac_address_retry_max):
            next_address = None
            with context.session.begin():
                try:
                    fn = db_api.mac_address_range_find_allocation_counts
                    mac_range = fn(context, address=mac_address)

                    if not mac_range:
                        break

                    rng, addr_count = mac_range

                    last = rng["last_address"]
                    first = rng["first_address"]
                    if (last - first + 1) <= addr_count:
                        # Somehow, the range got filled up without us
                        # knowing, so set the next_auto_assign to be -1
                        # so we never try to create new ones
                        # in this range
                        rng["next_auto_assign_mac"] = -1
                        context.session.add(rng)
                        continue

                    if mac_address:
                        next_address = mac_address
                    else:
                        next_address = rng["next_auto_assign_mac"]
                        next_auto = next_address + 1
                        if next_auto > last:
                            next_auto = -1
                        db_api.mac_address_range_update(
                            context, rng, next_auto_assign_mac=next_auto)

                except Exception:
                    LOG.exception("Error in updating mac range")
                    continue

            # Based on the above, this should only fail if a MAC was
            # was explicitly chosen at some point. As such, fall through
            # here and get in line for a new MAC address to try
            try:
                with context.session.begin():
                    address = db_api.mac_address_create(
                        context, address=next_address,
                        mac_address_range_id=rng["id"])
                    return address
            except Exception:
                LOG.exception("Error in creating mac. MAC possibly duplicate")
                continue

        raise exceptions.MacAddressGenerationFailure(net_id=net_id)