def _allocate_segment(self, sa_range, count=1):
     """Populate a given segment range."""
     allocs = []
     for i in xrange(sa_range["first_id"], sa_range["first_id"] + count):
         filters = {"segment_allocation_range_id": sa_range["id"], "deallocated": True}
         alloc = db_api.segment_allocation_find(self.context, **filters).first()
         if not alloc:
             raise Exception("Could not find deallocated id.")
         update = {"deallocated": False}
         allocs.append(db_api.segment_allocation_update(self.context, alloc, **update))
         self.context.session.flush()
     self.assertEqual(len(allocs), count)
     return allocs
Esempio n. 2
0
    def _try_deallocate(self, context, segment_id, network_id):
        LOG.info("Attempting to deallocate segment for network %s "
                 "segment_id %s segment_type %s"
                 % (network_id, segment_id, self.segment_type))

        with context.session.begin(subtransactions=True):
            filter_dict = {
                "deallocated": False,
                "segment_id": segment_id,
                "segment_type": self.segment_type,
                "network_id": network_id
            }

            allocations = db_api.segment_allocation_find(
                context, **filter_dict).all()

            if not allocations:
                LOG.info("Could not find allocated segment for network %s "
                         "segment_id %s segment_type %s for deallocate."
                         % (network_id, segment_id, self.segment_type))
                return

            if len(allocations) > 1:
                LOG.error("Found multiple allocated segments for network %s "
                          "segment_id %s segment_type %s for deallocate. "
                          "Refusing to deallocate, these allocations are now "
                          "orphaned."
                          % (network_id, segment_id, self.segment_type))
                return

            allocation = allocations[0]
            # Deallocate the found segment.
            update_dict = {
                "deallocated": True,
                "deallocated_at": timeutils.utcnow(),
                "network_id": None
            }
            allocation = db_api.segment_allocation_update(
                context, allocation, **update_dict)

            LOG.info("Deallocated %s allocated segment(s) for network %s "
                     "segment_id %s segment_type %s"
                     % (len(allocations), network_id, segment_id,
                        self.segment_type))
Esempio n. 3
0
    def _try_deallocate(self, context, segment_id, network_id):
        LOG.info("Attempting to deallocate segment for network %s "
                 "segment_id %s segment_type %s"
                 % (network_id, segment_id, self.segment_type))

        with context.session.begin(subtransactions=True):
            filter_dict = {
                "deallocated": False,
                "segment_id": segment_id,
                "segment_type": self.segment_type,
                "network_id": network_id
            }

            allocations = db_api.segment_allocation_find(
                context, **filter_dict).all()

            if not allocations:
                LOG.info("Could not find allocated segment for network %s "
                         "segment_id %s segment_type %s for deallocate."
                         % (network_id, segment_id, self.segment_type))
                return

            if len(allocations) > 1:
                LOG.error("Found multiple allocated segments for network %s "
                          "segment_id %s segment_type %s for deallocate. "
                          "Refusing to deallocate, these allocations are now "
                          "orphaned."
                          % (network_id, segment_id, self.segment_type))
                return

            allocation = allocations[0]
            # Deallocate the found segment.
            update_dict = {
                "deallocated": True,
                "deallocated_at": timeutils.utcnow(),
                "network_id": None
            }
            allocation = db_api.segment_allocation_update(
                context, allocation, **update_dict)

            LOG.info("Deallocated %s allocated segment(s) for network %s "
                     "segment_id %s segment_type %s"
                     % (len(allocations), network_id, segment_id,
                        self.segment_type))
Esempio n. 4
0
 def _allocate_segment(self, sa_range, count=1):
     """Populate a given segment range."""
     allocs = []
     for i in xrange(sa_range['first_id'], sa_range['first_id'] + count):
         filters = {
             'segment_allocation_range_id': sa_range['id'],
             'deallocated': True
         }
         alloc = db_api.segment_allocation_find(self.context,
                                                **filters).first()
         if not alloc:
             raise Exception("Could not find deallocated id.")
         update = {'deallocated': False}
         allocs.append(
             db_api.segment_allocation_update(self.context, alloc,
                                              **update))
         self.context.session.flush()
     self.assertEqual(len(allocs), count)
     return allocs
Esempio n. 5
0
    def _try_allocate(self, context, segment_id, network_id):
        """Find a deallocated network segment id and reallocate it.

        NOTE(morgabra) This locks the segment table, but only the rows
        in use by the segment, which is pretty handy if we ever have
        more than 1 segment or segment type.
        """
        LOG.info("Attempting to allocate segment for network %s "
                 "segment_id %s segment_type %s"
                 % (network_id, segment_id, self.segment_type))

        filter_dict = {
            "segment_id": segment_id,
            "segment_type": self.segment_type,
            "do_not_use": False
        }
        available_ranges = db_api.segment_allocation_range_find(
            context, scope=db_api.ALL, **filter_dict)
        available_range_ids = [r["id"] for r in available_ranges]

        try:
            with context.session.begin(subtransactions=True):
                # Search for any deallocated segment ids for the
                # given segment.
                filter_dict = {
                    "deallocated": True,
                    "segment_id": segment_id,
                    "segment_type": self.segment_type,
                    "segment_allocation_range_ids": available_range_ids
                }

                # NOTE(morgabra) We select 100 deallocated segment ids from
                # the table here, and then choose 1 randomly. This is to help
                # alleviate the case where an uncaught exception might leave
                # an allocation active on a remote service but we do not have
                # a record of it locally. If we *do* end up choosing a
                # conflicted id, the caller should simply allocate another one
                # and mark them all as reserved. If a single object has
                # multiple reservations on the same segment, they will not be
                # deallocated, and the operator must resolve the conficts
                # manually.
                allocations = db_api.segment_allocation_find(
                    context, lock_mode=True, **filter_dict).limit(100).all()

                if allocations:
                    allocation = random.choice(allocations)

                    # Allocate the chosen segment.
                    update_dict = {
                        "deallocated": False,
                        "deallocated_at": None,
                        "network_id": network_id
                    }
                    allocation = db_api.segment_allocation_update(
                        context, allocation, **update_dict)
                    LOG.info("Allocated segment %s for network %s "
                             "segment_id %s segment_type %s"
                             % (allocation["id"], network_id, segment_id,
                                self.segment_type))
                    return allocation
        except Exception:
            LOG.exception("Error in segment reallocation.")

        LOG.info("Cannot find reallocatable segment for network %s "
                 "segment_id %s segment_type %s"
                 % (network_id, segment_id, self.segment_type))
Esempio n. 6
0
    def _try_allocate(self, context, segment_id, network_id):
        """Find a deallocated network segment id and reallocate it.

        NOTE(morgabra) This locks the segment table, but only the rows
        in use by the segment, which is pretty handy if we ever have
        more than 1 segment or segment type.
        """
        LOG.info("Attempting to allocate segment for network %s "
                 "segment_id %s segment_type %s"
                 % (network_id, segment_id, self.segment_type))

        filter_dict = {
            "segment_id": segment_id,
            "segment_type": self.segment_type,
            "do_not_use": False
        }
        available_ranges = db_api.segment_allocation_range_find(
            context, scope=db_api.ALL, **filter_dict)
        available_range_ids = [r["id"] for r in available_ranges]

        try:
            with context.session.begin(subtransactions=True):
                # Search for any deallocated segment ids for the
                # given segment.
                filter_dict = {
                    "deallocated": True,
                    "segment_id": segment_id,
                    "segment_type": self.segment_type,
                    "segment_allocation_range_ids": available_range_ids
                }

                # NOTE(morgabra) We select 100 deallocated segment ids from
                # the table here, and then choose 1 randomly. This is to help
                # alleviate the case where an uncaught exception might leave
                # an allocation active on a remote service but we do not have
                # a record of it locally. If we *do* end up choosing a
                # conflicted id, the caller should simply allocate another one
                # and mark them all as reserved. If a single object has
                # multiple reservations on the same segment, they will not be
                # deallocated, and the operator must resolve the conficts
                # manually.
                allocations = db_api.segment_allocation_find(
                    context, lock_mode=True, **filter_dict).limit(100).all()

                if allocations:
                    allocation = random.choice(allocations)

                    # Allocate the chosen segment.
                    update_dict = {
                        "deallocated": False,
                        "deallocated_at": None,
                        "network_id": network_id
                    }
                    allocation = db_api.segment_allocation_update(
                        context, allocation, **update_dict)
                    LOG.info("Allocated segment %s for network %s "
                             "segment_id %s segment_type %s"
                             % (allocation["id"], network_id, segment_id,
                                self.segment_type))
                    return allocation
        except Exception:
            LOG.exception("Error in segment reallocation.")

        LOG.info("Cannot find reallocatable segment for network %s "
                 "segment_id %s segment_type %s"
                 % (network_id, segment_id, self.segment_type))