コード例 #1
0
    def test_create_segment_allocation_ranges_diff_overlap_allowed(self):
        """Assert different segments with overlapping ids are allowed."""
        sa_range_dict = self._make_segment_allocation_range_dict()
        sa_range_request = {"segment_allocation_range": sa_range_dict}

        segment_ids = [
            'segment1',
            'segment2',
            'segment3'
        ]
        for segment_id in segment_ids:
            sa_range_dict['first_id'] = 1
            sa_range_dict['last_id'] = 5
            sa_range_dict['segment_id'] = segment_id
            sa_range = sa_ranges_api.create_segment_allocation_range(
                self.context, sa_range_request)

            # Find all ranges added in the db
            sa_range_models = db_api.segment_allocation_range_find(
                self.context, id=sa_range['id'], scope=db_api.ALL)

            # Assert we actually added the range to the db with correct
            # values and returned the correct response.
            self.assertEqual(len(sa_range_models), 1)
            self.assertEqual(self._sa_range_to_dict(sa_range_models[0]),
                             sa_range)
コード例 #2
0
    def _create_range(self, context, sa_range):
        with context.session.begin(subtransactions=True):
            # Validate any range-specific things, like min/max ids.
            self._validate_range(context, sa_range)

            # Check any existing ranges for this segment for collisions
            segment_id = sa_range["segment_id"]
            segment_type = sa_range["segment_type"]

            filters = {"segment_id": segment_id,
                       "segment_type": segment_type}
            existing_ranges = db_api.segment_allocation_range_find(
                context, lock_mode=True, scope=db_api.ALL, **filters)

            collides = self._check_collisions(
                (sa_range["first_id"], sa_range["last_id"]),
                [(r["first_id"], r["last_id"]) for r in existing_ranges])

            if collides:
                raise q_exc.InvalidSegmentAllocationRange(
                    msg=("The specified allocation collides with existing "
                         "range"))

            return db_api.segment_allocation_range_create(
                context, **sa_range)
コード例 #3
0
    def test_create_segment_allocation_ranges(self):
        """Assert segments with same type/id are allowed."""
        sa_range_dict = self._make_segment_allocation_range_dict()
        sa_range_request = {"segment_allocation_range": sa_range_dict}

        valid_ranges = [
            (10, 15),
            (5, 9),
            (16, 20),
        ]
        for first_id, last_id in valid_ranges:
            sa_range_dict['first_id'] = first_id
            sa_range_dict['last_id'] = last_id
            sa_range = sa_ranges_api.create_segment_allocation_range(
                self.context, sa_range_request)

            # Find all ranges added in the db
            sa_range_models = db_api.segment_allocation_range_find(
                self.context, id=sa_range['id'], scope=db_api.ALL)

            # Assert we actually added the range to the db with correct
            # values and returned the correct response.
            self.assertEqual(len(sa_range_models), 1)
            self.assertEqual(self._sa_range_to_dict(sa_range_models[0]),
                             sa_range)
コード例 #4
0
    def test_create_segment_allocation_ranges(self):
        """Assert segments with same type/id are allowed."""
        sa_range_dict = self._make_segment_allocation_range_dict()
        sa_range_request = {"segment_allocation_range": sa_range_dict}

        valid_ranges = [
            (10, 15),
            (5, 9),
            (16, 20),
        ]
        for first_id, last_id in valid_ranges:
            sa_range_dict['first_id'] = first_id
            sa_range_dict['last_id'] = last_id
            sa_range = sa_ranges_api.create_segment_allocation_range(
                self.context, sa_range_request)

            # Find all ranges added in the db
            sa_range_models = db_api.segment_allocation_range_find(
                self.context, id=sa_range['id'], scope=db_api.ALL)

            # Assert we actually added the range to the db with correct
            # values and returned the correct response.
            self.assertEqual(len(sa_range_models), 1)
            self.assertEqual(self._sa_range_to_dict(sa_range_models[0]),
                             sa_range)
コード例 #5
0
    def _create_range(self, context, sa_range):
        with context.session.begin(subtransactions=True):
            # Validate any range-specific things, like min/max ids.
            self._validate_range(context, sa_range)

            # Check any existing ranges for this segment for collisions
            segment_id = sa_range["segment_id"]
            segment_type = sa_range["segment_type"]

            filters = {"segment_id": segment_id,
                       "segment_type": segment_type}
            existing_ranges = db_api.segment_allocation_range_find(
                context, lock_mode=True, scope=db_api.ALL, **filters)

            collides = self._check_collisions(
                (sa_range["first_id"], sa_range["last_id"]),
                [(r["first_id"], r["last_id"]) for r in existing_ranges])

            if collides:
                raise q_exc.InvalidSegmentAllocationRange(
                    msg=("The specified allocation collides with existing "
                         "range"))

            return db_api.segment_allocation_range_create(
                context, **sa_range)
コード例 #6
0
def get_segment_allocation_ranges(context, **filters):
    LOG.info("get_segment_allocation_ranges for tenant %s" % context.tenant_id)
    if not context.is_admin:
        raise exceptions.NotAuthorized()

    sa_ranges = db_api.segment_allocation_range_find(
        context, scope=db_api.ALL, **filters)
    return [v._make_segment_allocation_range_dict(m) for m in sa_ranges]
コード例 #7
0
    def test_create_segment_allocation_range(self):
        """Assert a range is created."""

        # Create a segment allocation range
        sa_range_dict = self._make_segment_allocation_range_dict()
        sa_range_request = {"segment_allocation_range": sa_range_dict}
        sa_range = sa_ranges_api.create_segment_allocation_range(self.context, sa_range_request)

        # Find all ranges added in the db
        sa_range_models = db_api.segment_allocation_range_find(self.context, scope=db_api.ALL)
        # ensure non-admins can fetch them as well
        sa_range_models = db_api.segment_allocation_range_find(self.old_context, scope=db_api.ALL)

        # Assert we actually added the range to the db with correct
        # values and returned the correct response.
        self.assertEqual(len(sa_range_models), 1)
        self.assertEqual(self._sa_range_to_dict(sa_range_models[0]), sa_range)
コード例 #8
0
    def test_delete_segment_allocation_range_in_use_fails(self):
        sa_range = self._create_segment_allocation_range()
        self._allocate_segment(sa_range, count=1)

        self.assertRaises(n_exc.InUse, sa_ranges_api.delete_segment_allocation_range, self.context, sa_range["id"])

        # assert the range was not deleted
        sa_ranges = db_api.segment_allocation_range_find(self.context, id=sa_range["id"], scope=db_api.ALL)
        self.assertEqual(sa_ranges, [sa_range])
コード例 #9
0
    def test_delete_segment_allocation_range_unauthorized(self):
        sa_range = self._create_segment_allocation_range()

        # assert non-admins are not authorized
        self.assertRaises(
            n_exc.NotAuthorized, sa_ranges_api.delete_segment_allocation_range, self.old_context, sa_range["id"]
        )

        # assert the range was not deleted
        sa_ranges = db_api.segment_allocation_range_find(self.context, id=sa_range["id"], scope=db_api.ALL)
        self.assertEqual(sa_ranges, [sa_range])
コード例 #10
0
    def test_create_segment_allocation_range(self):
        """Assert a range is created."""

        # Create a segment allocation range
        sa_range_dict = self._make_segment_allocation_range_dict()
        sa_range_request = {"segment_allocation_range": sa_range_dict}
        sa_range = sa_ranges_api.create_segment_allocation_range(
            self.context, sa_range_request)

        # Find all ranges added in the db
        sa_range_models = db_api.segment_allocation_range_find(
            self.context, scope=db_api.ALL)
        # ensure non-admins can fetch them as well
        sa_range_models = db_api.segment_allocation_range_find(
            self.old_context, scope=db_api.ALL)

        # Assert we actually added the range to the db with correct
        # values and returned the correct response.
        self.assertEqual(len(sa_range_models), 1)
        self.assertEqual(self._sa_range_to_dict(sa_range_models[0]), sa_range)
コード例 #11
0
    def test_delete_segment_allocation_range_deletes(self):
        sa_range = self._create_segment_allocation_range()
        sa_range_id = sa_range["id"]

        sa_ranges_api.delete_segment_allocation_range(self.context, sa_range_id)

        # assert that the range and it's unused allocations are deleted
        sa_range = db_api.segment_allocation_range_find(self.context, id=sa_range_id, scope=db_api.ALL)
        allocs = db_api.segment_allocation_find(self.context, segment_allocation_range_id=sa_range_id).all()
        self.assertEqual(sa_range, [])
        self.assertEqual(allocs, [])
コード例 #12
0
    def test_delete_segment_allocation_range_unauthorized(self):
        sa_range = self._create_segment_allocation_range()

        # assert non-admins are not authorized
        self.assertRaises(exceptions.NotAuthorized,
                          sa_ranges_api.delete_segment_allocation_range,
                          self.old_context, sa_range["id"])

        # assert the range was not deleted
        sa_ranges = db_api.segment_allocation_range_find(self.context,
                                                         id=sa_range["id"],
                                                         scope=db_api.ALL)
        self.assertEqual(sa_ranges, [sa_range])
コード例 #13
0
    def test_delete_segment_allocation_range_in_use_fails(self):
        sa_range = self._create_segment_allocation_range()
        self._allocate_segment(sa_range, count=1)

        self.assertRaises(exceptions.InUse,
                          sa_ranges_api.delete_segment_allocation_range,
                          self.context, sa_range["id"])

        # assert the range was not deleted
        sa_ranges = db_api.segment_allocation_range_find(self.context,
                                                         id=sa_range["id"],
                                                         scope=db_api.ALL)
        self.assertEqual(sa_ranges, [sa_range])
コード例 #14
0
    def test_delete_segment_allocation_range_deletes(self):
        sa_range = self._create_segment_allocation_range()
        sa_range_id = sa_range["id"]

        sa_ranges_api.delete_segment_allocation_range(self.context,
                                                      sa_range_id)

        # assert that the range and it's unused allocations are deleted
        sa_range = db_api.segment_allocation_range_find(self.context,
                                                        id=sa_range_id,
                                                        scope=db_api.ALL)
        allocs = db_api.segment_allocation_find(
            self.context, segment_allocation_range_id=sa_range_id).all()
        self.assertEqual(sa_range, [])
        self.assertEqual(allocs, [])
コード例 #15
0
def delete_segment_allocation_range(context, sa_id):
    """Delete a segment_allocation_range.

    : param context: neutron api request context
    : param id: UUID representing the segment_allocation_range to delete.
    """
    LOG.info("delete_segment_allocation_range %s for tenant %s" %
             (sa_id, context.tenant_id))
    if not context.is_admin:
        raise exceptions.NotAuthorized()

    with context.session.begin():
        sa_range = db_api.segment_allocation_range_find(
            context, id=sa_id, scope=db_api.ONE)
        if not sa_range:
            raise quark_exceptions.SegmentAllocationRangeNotFound(
                segment_allocation_range_id=sa_id)
        _delete_segment_allocation_range(context, sa_range)
コード例 #16
0
def get_segment_allocation_range(context, id, fields=None):
    LOG.info("get_segment_allocation_range %s for tenant %s fields %s" %
             (id, context.tenant_id, fields))

    if not context.is_admin:
        raise n_exc.NotAuthorized()

    sa_range = db_api.segment_allocation_range_find(context,
                                                    id=id,
                                                    scope=db_api.ONE)

    if not sa_range:
        raise q_exc.SegmentAllocationRangeNotFound(
            segment_allocation_range_id=id)

    # Count up allocations so we can calculate how many are free.
    allocs = db_api.segment_allocation_find(
        context, segment_allocation_range_id=sa_range["id"],
        deallocated=False).count()
    return v._make_segment_allocation_range_dict(sa_range, allocations=allocs)
コード例 #17
0
def get_segment_allocation_range(context, id, fields=None):
    LOG.info("get_segment_allocation_range %s for tenant %s fields %s" %
             (id, context.tenant_id, fields))

    if not context.is_admin:
        raise exceptions.NotAuthorized()

    sa_range = db_api.segment_allocation_range_find(
        context, id=id, scope=db_api.ONE)

    if not sa_range:
        raise quark_exceptions.SegmentAllocationRangeNotFound(
            segment_allocation_range_id=id)

    # Count up allocations so we can calculate how many are free.
    allocs = db_api.segment_allocation_find(
        context,
        segment_allocation_range_id=sa_range["id"],
        deallocated=False).count()
    return v._make_segment_allocation_range_dict(
        sa_range, allocations=allocs)
コード例 #18
0
    def test_create_segment_allocation_ranges_diff_overlap_allowed(self):
        """Assert different segments with overlapping ids are allowed."""
        sa_range_dict = self._make_segment_allocation_range_dict()
        sa_range_request = {"segment_allocation_range": sa_range_dict}

        segment_ids = ['segment1', 'segment2', 'segment3']
        for segment_id in segment_ids:
            sa_range_dict['first_id'] = 1
            sa_range_dict['last_id'] = 5
            sa_range_dict['segment_id'] = segment_id
            sa_range = sa_ranges_api.create_segment_allocation_range(
                self.context, sa_range_request)

            # Find all ranges added in the db
            sa_range_models = db_api.segment_allocation_range_find(
                self.context, id=sa_range['id'], scope=db_api.ALL)

            # Assert we actually added the range to the db with correct
            # values and returned the correct response.
            self.assertEqual(len(sa_range_models), 1)
            self.assertEqual(self._sa_range_to_dict(sa_range_models[0]),
                             sa_range)
コード例 #19
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))
コード例 #20
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))