Esempio n. 1
0
 def _load_instance(self, db_instance):
     # NOTE(alaski): Be very careful with instance loading because it
     # changes more than most objects.
     try:
         self.instance = objects.Instance.obj_from_primitive(
             jsonutils.loads(db_instance))
     except TypeError:
         LOG.debug(
             'Failed to load instance from BuildRequest with uuid '
             '%s because it is None', self.instance_uuid)
         raise exception.BuildRequestNotFound(uuid=self.instance_uuid)
     except ovoo_exc.IncompatibleObjectVersion:
         # This should only happen if proper service upgrade strategies are
         # not followed. Log the exception and raise BuildRequestNotFound.
         # If the instance can't be loaded this object is useless and may
         # as well not exist.
         LOG.debug(
             'Could not deserialize instance store in BuildRequest '
             'with uuid %(instance_uuid)s. Found version %(version)s '
             'which is not supported here.',
             dict(instance_uuid=self.instance_uuid,
                  version=jsonutils.loads(db_instance)
                  ["nova_object.version"]))
         LOG.exception('Could not deserialize instance in BuildRequest')
         raise exception.BuildRequestNotFound(uuid=self.instance_uuid)
     # NOTE(sbauza): The instance primitive should already have the deleted
     # field being set, so when hydrating it back here, we should get the
     # right value but in case we don't have it, let's suppose that the
     # instance is not deleted, which is the default value for that field.
     # NOTE(mriedem): Same for the "hidden" field.
     self.instance.obj_set_defaults('deleted', 'hidden')
     # NOTE(alaski): Set some fields on instance that are needed by the api,
     # not lazy-loadable, and don't change.
     self.instance.disable_terminate = False
     self.instance.terminated_at = None
     self.instance.host = None
     self.instance.node = None
     self.instance.launched_at = None
     self.instance.launched_on = None
     self.instance.cell_name = None
     # The fields above are not set until the instance is in a cell at
     # which point this BuildRequest will be gone. locked_by could
     # potentially be set by an update so it should not be overwritten.
     if not self.instance.obj_attr_is_set('locked_by'):
         self.instance.locked_by = None
     # created_at/updated_at are not on the serialized instance because it
     # was never persisted.
     self.instance.created_at = self.created_at
     self.instance.updated_at = self.updated_at
     self.instance.tags = self.tags
Esempio n. 2
0
    def test_get_instances_with_cell_down_support(self, mock_sg):
        self.flags(list_records_by_skipping_down_cells=False, group='api')
        inst_cell0 = self.insts[uuids.cell0]
        # storing the uuids of the instances from the up cell
        uuid_initial = [inst['uuid'] for inst in inst_cell0]

        def wrap(thing):
            return multi_cell_list.RecordWrapper(ctx, self.context, thing)

        ctx = nova_context.RequestContext()
        instances = [wrap(inst) for inst in inst_cell0]

        # creating one up cell and two down cells
        ret_val = {}
        ret_val[uuids.cell0] = instances
        ret_val[uuids.cell1] = [wrap(exception.BuildRequestNotFound(uuid='f'))]
        ret_val[uuids.cell2] = [wrap(nova_context.did_not_respond_sentinel)]
        mock_sg.return_value = ret_val

        # From the new microversion (2.68) if cell_down_support is True
        # then CONF.api.list_records_by_skipping_down_cells will be ignored.
        # Exception will not be raised even if its False.
        obj, res = instance_list.get_instances_sorted(self.context, {},
                                                      None,
                                                      None, [],
                                                      None,
                                                      None,
                                                      cell_down_support=True)

        uuid_final = [inst['uuid'] for inst in res]

        # return the results from the up cell, ignoring the down cell and
        # constructing partial results later.
        self.assertEqual(uuid_initial, uuid_final)
Esempio n. 3
0
    def test_get_instances_with_down_cells(self, mock_sg):
        inst_cell0 = self.insts[uuids.cell0]
        # storing the uuids of the instances from the up cell
        uuid_initial = [inst['uuid'] for inst in inst_cell0]

        def wrap(thing):
            return multi_cell_list.RecordWrapper(ctx, self.context, thing)

        ctx = nova_context.RequestContext()
        instances = [wrap(inst) for inst in inst_cell0]

        # creating one up cell and two down cells
        ret_val = {}
        ret_val[uuids.cell0] = instances
        ret_val[uuids.cell1] = [wrap(exception.BuildRequestNotFound(uuid='f'))]
        ret_val[uuids.cell2] = [wrap(nova_context.did_not_respond_sentinel)]
        mock_sg.return_value = ret_val

        obj, res = instance_list.get_instances_sorted(self.context, {}, None,
                                                      None, [], None, None)

        uuid_final = [inst['uuid'] for inst in res]

        # return the results from the up cell, ignoring the down cell.
        self.assertEqual(uuid_initial, uuid_final)
Esempio n. 4
0
 def _get_by_instance_uuid_from_db(context, instance_uuid):
     db_req = (context.session.query(api_models.BuildRequest).options(
         joinedload('request_spec')).filter_by(
             instance_uuid=instance_uuid)).first()
     if not db_req:
         raise exception.BuildRequestNotFound(uuid=instance_uuid)
     return db_req
Esempio n. 5
0
 def _load_instance(self, db_instance):
     # NOTE(alaski): Be very careful with instance loading because it
     # changes more than most objects.
     try:
         self.instance = objects.Instance.obj_from_primitive(
             jsonutils.loads(db_instance))
     except TypeError:
         LOG.debug(
             'Failed to load instance from BuildRequest with uuid '
             '%s because it is None', self.instance_uuid)
         raise exception.BuildRequestNotFound(uuid=self.instance_uuid)
     except ovoo_exc.IncompatibleObjectVersion as exc:
         # This should only happen if proper service upgrade strategies are
         # not followed. Log the exception and raise BuildRequestNotFound.
         # If the instance can't be loaded this object is useless and may
         # as well not exist.
         LOG.debug(
             'Could not deserialize instance store in BuildRequest '
             'with uuid %(instance_uuid)s. Found version %(version)s '
             'which is not supported here.',
             dict(instance_uuid=self.instance_uuid, version=exc.objver))
         LOG.exception(
             _LE('Could not deserialize instance in '
                 'BuildRequest'))
         raise exception.BuildRequestNotFound(uuid=self.instance_uuid)
     # NOTE(alaski): Set some fields on instance that are needed by the api,
     # not lazy-loadable, and don't change.
     self.instance.deleted = 0
     self.instance.disable_terminate = False
     self.instance.terminated_at = None
     self.instance.host = None
     self.instance.node = None
     self.instance.launched_at = None
     self.instance.launched_on = None
     self.instance.cell_name = None
     # The fields above are not set until the instance is in a cell at
     # which point this BuildRequest will be gone. locked_by could
     # potentially be set by an update so it should not be overwritten.
     if not self.instance.obj_attr_is_set('locked_by'):
         self.instance.locked_by = None
     # created_at/updated_at are not on the serialized instance because it
     # was never persisted.
     self.instance.created_at = self.created_at
     self.instance.updated_at = self.updated_at
     self.instance.tags = objects.TagList([])
Esempio n. 6
0
    def _save_in_db(self, context, req_id, updates):
        db_req = context.session.query(
            api_models.BuildRequest).filter_by(id=req_id).first()
        if not db_req:
            raise exception.BuildRequestNotFound(uuid=self.instance_uuid)

        db_req.update(updates)
        context.session.add(db_req)
        return db_req
Esempio n. 7
0
    def test_deleting_instance_at_the_same_time(self, mock_get_i, mock_get_im,
                                                mock_get_br):
        """This tests the scenario where another request is trying to delete
        the instance record at the same time we are, while the instance is
        booting. An example of this: while the create and delete are running at
        the same time, the delete request deletes the build request, the create
        request finds the build request already deleted when it tries to delete
        it. The create request deletes the instance record and then delete
        request tries to lookup the instance after it deletes the build
        request. Its attempt to lookup the instance fails because the create
        request already deleted it.
        """
        # First lookup at the beginning of the delete request in the
        # ServersController succeeds, second lookup to handle "delete while
        # booting" in compute/api fails after the conductor has deleted it.
        br_not_found = exception.BuildRequestNotFound(uuid=self.server['id'])
        mock_get_br.side_effect = [self.br, br_not_found]
        # Simulate the instance transitioning from having no cell assigned to
        # having a cell assigned while the delete request is being processed.
        # First lookup of the instance mapping has the instance unmapped (no
        # cell) and subsequent lookups have the instance mapped to cell1.
        no_cell_im = objects.InstanceMapping(
            context=self.ctxt, instance_uuid=self.server['id'],
            cell_mapping=None)
        has_cell_im = objects.InstanceMapping(
            context=self.ctxt, instance_uuid=self.server['id'],
            cell_mapping=self.cell_mappings['cell1'])
        mock_get_im.side_effect = [
            no_cell_im, has_cell_im, has_cell_im, has_cell_im]
        # Simulate that the instance object has been created by the conductor
        # in the create path while the delete request is being processed.
        # First lookups are before the instance has been deleted and the last
        # lookup is after the conductor has deleted the instance. Use the build
        # request to make an instance object for testing.
        i = self.br.get_new_instance(self.ctxt)
        i_not_found = exception.InstanceNotFound(instance_id=self.server['id'])
        mock_get_i.side_effect = [i, i, i, i_not_found]

        # Simulate that the conductor is running instance_destroy at the same
        # time as we are.
        def fake_instance_destroy(*args, **kwargs):
            # NOTE(melwitt): This is a misleading exception, as it is not only
            # raised when a constraint on 'host' is not met, but also when two
            # instance_destroy calls are racing. In this test, the soft delete
            # returns 0 rows affected because another request soft deleted the
            # record first.
            raise exception.ObjectActionError(
                action='destroy', reason='host changed')

        self.stub_out(
            'nova.objects.instance.Instance.destroy', fake_instance_destroy)
        # FIXME(melwitt): Delete request fails due to the AttributeError.
        ex = self.assertRaises(
            client.OpenStackApiException, self._delete_server, self.server)
        self.assertEqual(500, ex.response.status_code)
        self.assertIn('AttributeError', str(ex))
Esempio n. 8
0
 def test_build_request_and_instance_not_found(self, mock_get_br):
     """This tests a scenario where another request has deleted the build
     request record and the instance record ahead of us.
     """
     # The first lookup at the beginning of the delete request in the
     # ServersController succeeds and the second lookup to handle "delete
     # while booting" in compute/api fails after a different request has
     # deleted it.
     br_not_found = exception.BuildRequestNotFound(uuid=self.server['id'])
     mock_get_br.side_effect = [self.br, br_not_found, br_not_found]
     self._delete_server(self.server)
 def _get_by_instance_uuid_from_db(context, instance_uuid):
     db_req = (context.session.query(api_models.BuildRequest).join(
         api_models.RequestSpec).with_entities(
             api_models.BuildRequest, api_models.RequestSpec).filter(
                 api_models.RequestSpec.instance_uuid == instance_uuid)
               ).first()
     if not db_req:
         raise exception.BuildRequestNotFound(uuid=instance_uuid)
     # db_req is a tuple (api_models.BuildRequest, api_models.RequestSpect)
     build_req = db_req[0]
     build_req['request_spec'] = db_req[1]
     return build_req
Esempio n. 10
0
 def _load_instance(self, db_instance):
     # NOTE(alaski): Be very careful with instance loading because it
     # changes more than most objects.
     try:
         self.instance = objects.Instance.obj_from_primitive(
                 jsonutils.loads(db_instance))
     except TypeError:
         LOG.debug('Failed to load instance from BuildRequest with uuid '
                   '%s because it is None' % (self.instance_uuid))
         raise exception.BuildRequestNotFound(uuid=self.instance_uuid)
     except ovoo_exc.IncompatibleObjectVersion as exc:
         # This should only happen if proper service upgrade strategies are
         # not followed. Log the exception and raise BuildRequestNotFound.
         # If the instance can't be loaded this object is useless and may
         # as well not exist.
         LOG.debug('Could not deserialize instance store in BuildRequest '
                   'with uuid %(instance_uuid)s. Found version %(version)s '
                   'which is not supported here.',
                   dict(instance_uuid=self.instance_uuid,
                       version=exc.objver))
         LOG.exception(_LE('Could not deserialize instance in '
                           'BuildRequest'))
         raise exception.BuildRequestNotFound(uuid=self.instance_uuid)
Esempio n. 11
0
 def test_build_request_and_instance_not_found(self, mock_get_br):
     """This tests a scenario where another request has deleted the build
     request record and the instance record ahead of us.
     """
     # The first lookup at the beginning of the delete request in the
     # ServersController succeeds and the second lookup to handle "delete
     # while booting" in compute/api fails after a different request has
     # deleted it.
     br_not_found = exception.BuildRequestNotFound(uuid=self.server['id'])
     mock_get_br.side_effect = [self.br, br_not_found]
     # FIXME(melwitt): Delete request fails due to the AttributeError.
     ex = self.assertRaises(
         client.OpenStackApiException, self._delete_server, self.server)
     self.assertEqual(500, ex.response.status_code)
     self.assertIn('AttributeError', str(ex))
Esempio n. 12
0
    def test_get_instances_by_not_skipping_down_cells(self, mock_sg):
        self.flags(list_records_by_skipping_down_cells=False, group='api')
        inst_cell0 = self.insts[uuids.cell0]

        def wrap(thing):
            return multi_cell_list.RecordWrapper(ctx, self.context, thing)

        ctx = nova_context.RequestContext()
        instances = [wrap(inst) for inst in inst_cell0]

        # creating one up cell and two down cells
        ret_val = {}
        ret_val[uuids.cell0] = instances
        ret_val[uuids.cell1] = [wrap(exception.BuildRequestNotFound(uuid='f'))]
        ret_val[uuids.cell2] = [wrap(nova_context.did_not_respond_sentinel)]
        mock_sg.return_value = ret_val

        # Raises exception if a cell is down without skipping them
        # as CONF.api.list_records_by_skipping_down_cells is set to False.
        # This would in turn result in an API 500 internal error.
        exp = self.assertRaises(exception.NovaException,
                                instance_list.get_instance_objects_sorted,
                                self.context, {}, None, None, [], None, None)
        self.assertIn('configuration indicates', six.text_type(exp))
Esempio n. 13
0
 def _destroy_in_db(context, instance_uuid):
     result = context.session.query(api_models.BuildRequest).filter_by(
         instance_uuid=instance_uuid).delete()
     if not result:
         raise exception.BuildRequestNotFound(uuid=instance_uuid)