Example #1
0
 def test_show(self):
     # Get api sample of one single image details request.
     image_id = fake.get_valid_image_id()
     response = self._do_get("images/%s" % image_id)
     subs = self._get_regexes()
     subs["image_id"] = image_id
     self._verify_response("image-get-resp", subs, response, 200)
Example #2
0
 def test_instance_list_build_request_marker_ip_filter(self):
     """Tests listing instances with a marker that is in the build_requests
     table and also filtering by ip, in which case the ip filter can't
     possibly find anything because instances that are not yet scheduled
     can't have ips, but the point is to find the marker in the build
     requests table.
     """
     self.useFixture(nova_fixtures.AllServicesCurrent())
     # Create the server.
     body = {
         'server': {
             'name': 'test_instance_list_build_request_marker_ip_filter',
             'imageRef': fake_image.get_valid_image_id(),
             'flavorRef': '1',
             'networks': 'none'
         }
     }
     server = self.api.post_server(body)
     # Now list servers using the one we just created as the marker and
     # include the ip filter (see bug 1764685).
     search_opts = {
         'marker': server['id'],
         'ip': '192.168.159.150'
     }
     servers = self.api.get_servers(search_opts=search_opts)
     # We'll get 0 servers back because there are none with the specified
     # ip filter.
     self.assertEqual(0, len(servers))
Example #3
0
 def test_image_meta_key_put(self):
     # Get api sample of image metadata key put request.
     image_id = fake.get_valid_image_id()
     key = "auto_disk_config"
     response = self._do_put("images/%s/metadata/%s" % (image_id, key), "image-meta-key-put-req", {})
     subs = self._get_regexes()
     self._verify_response("image-meta-key-put-resp", subs, response, 200)
Example #4
0
 def test_delete_instance_from_buildrequest_old_service(self):
     image_ref = fake_image.get_valid_image_id()
     body = {"server": {"name": "foo", "imageRef": image_ref, "flavorRef": "1", "networks": "none"}}
     create_resp = self.api.api_post("servers", body)
     self.api.api_delete("servers/%s" % create_resp.body["server"]["id"])
     get_resp = self.api.api_get("servers/%s" % create_resp.body["server"]["id"], check_response_status=False)
     self.assertEqual(404, get_resp.status)
Example #5
0
    def _test_instance_list_from_buildrequests(self):
        image_ref = fake_image.get_valid_image_id()
        body = {
            'server': {
                'name': 'foo',
                'imageRef': image_ref,
                'flavorRef': '1',
                'networks': 'none',
            }
        }
        inst1 = self.api.api_post('servers', body)
        body['server']['name'] = 'bar'
        inst2 = self.api.api_post('servers', body)

        list_resp = self.api.get_servers()
        # Default sort is created_at desc, so last created is first
        self.assertEqual(2, len(list_resp))
        self.assertEqual(inst2.body['server']['id'], list_resp[0]['id'])
        self.assertEqual('bar', list_resp[0]['name'])
        self.assertEqual(inst1.body['server']['id'], list_resp[1]['id'])
        self.assertEqual('foo', list_resp[1]['name'])

        # Change the sort order
        list_resp = self.api.api_get(
            'servers/detail?sort_key=created_at&sort_dir=asc')
        list_resp = list_resp.body['servers']
        self.assertEqual(2, len(list_resp))
        self.assertEqual(inst1.body['server']['id'], list_resp[0]['id'])
        self.assertEqual('foo', list_resp[0]['name'])
        self.assertEqual(inst2.body['server']['id'], list_resp[1]['id'])
        self.assertEqual('bar', list_resp[1]['name'])
Example #6
0
 def test_instance_from_buildrequest_old_service(self):
     image_ref = fake_image.get_valid_image_id()
     body = {
         'server': {
             'name': 'foo',
             'imageRef': image_ref,
             'flavorRef': '1',
             'networks': 'none',
         }
     }
     create_resp = self.api.api_post('servers', body)
     get_resp = self.api.api_get('servers/%s' %
                                 create_resp.body['server']['id'])
     flavor_get_resp = self.api.api_get('flavors/%s' %
                                        body['server']['flavorRef'])
     server = get_resp.body['server']
     # Just validate some basics
     self.assertEqual('foo', server['name'])
     self.assertEqual(image_ref, server['image']['id'])
     self.assertEqual(flavor_get_resp.body['flavor']['name'],
                      server['flavor']['original_name'])
     self.assertEqual('', server['hostId'])
     self.assertIsNone(server['OS-SRV-USG:launched_at'])
     self.assertIsNone(server['OS-SRV-USG:terminated_at'])
     self.assertFalse(server['locked'])
     self.assertEqual([], server['tags'])
     self.assertEqual('scheduling', server['OS-EXT-STS:task_state'])
     self.assertEqual('building', server['OS-EXT-STS:vm_state'])
     self.assertEqual('BUILD', server['status'])
Example #7
0
 def test_image_metadata_post(self):
     # Get api sample to update metadata of an image metadata request.
     image_id = fake.get_valid_image_id()
     response = self._do_post(
             'images/%s/metadata' % image_id,
             'image-metadata-post-req', {})
     self._verify_response('image-metadata-post-resp', {}, response, 200)
Example #8
0
 def test_image_metadata_put(self):
     # Get api sample of image metadata put request.
     image_id = fake.get_valid_image_id()
     response = self._do_put('images/%s/metadata' %
                             (image_id), 'image-metadata-put-req', {})
     subs = self._get_regexes()
     self._verify_response('image-metadata-put-resp', subs, response, 200)
Example #9
0
 def test_image_meta_key_put(self):
     # Get api sample of image metadata key put request.
     image_id = fake.get_valid_image_id()
     key = "auto_disk_config"
     response = self._do_put('images/%s/metadata/%s' % (image_id, key),
                             'image-meta-key-put-req', {})
     self._verify_response('image-meta-key-put-resp', {}, response, 200)
    def _post_server(self, use_common_server_api_samples=True):
        # param use_common_server_api_samples: Boolean to set whether tests use
        # common sample files for server post request and response.
        # Default is True which means _get_sample_path method will fetch the
        # common server sample files from 'servers' directory.
        # Set False if tests need to use extension specific sample files

        subs = {
            "image_id": fake.get_valid_image_id(),
            "host": self._get_host(),
            "compute_endpoint": self._get_compute_endpoint(),
            "versioned_compute_endpoint": self._get_vers_compute_endpoint(),
            "glance_host": self._get_glance_host(),
            "access_ip_v4": "1.2.3.4",
            "access_ip_v6": "80fe::",
        }
        # TODO(gmann): Remove this hack once all tests using this common
        # _post_server method are enabled with all extension.
        # This is added to avoid all tests updates together.
        post_req_template = "server-post-req"
        post_resp_template = "server-post-resp"
        if self.all_extensions and use_common_server_api_samples:
            post_req_template = "server-create-req"
            post_resp_template = "server-create-resp"

        orig_value = self.__class__._use_common_server_api_samples
        orig_sample_dir = self.__class__.sample_dir
        try:
            self.__class__._use_common_server_api_samples = use_common_server_api_samples
            response = self._do_post("servers", post_req_template, subs)
            status = self._verify_response(post_resp_template, subs, response, 202)
            return status
        finally:
            self.__class__._use_common_server_api_samples = orig_value
            self.__class__.sample_dir = orig_sample_dir
Example #11
0
 def test_image_metadata_get(self):
     # Get api sample of an image metadata request.
     image_id = fake.get_valid_image_id()
     response = self._do_get('images/%s/metadata' % image_id)
     subs = self._get_regexes()
     subs['image_id'] = image_id
     self._verify_response('image-metadata-get-resp', subs, response, 200)
Example #12
0
 def test_image_meta_key_get(self):
     # Get api sample of an image metadata key request.
     image_id = fake.get_valid_image_id()
     key = "kernel_id"
     response = self._do_get('images/%s/metadata/%s' % (image_id, key))
     subs = self._get_regexes()
     self._verify_response('image-meta-key-get', subs, response, 200)
    def _test_server_rebuild_preserve_ephemeral(self, value, resp_tpl=None):
        uuid = self._post_server()
        image = fake.get_valid_image_id()
        subs = {'host': self._get_host(),
                'uuid': image,
                'name': 'foobar',
                'pass': '******',
                'hostid': '[a-f0-9]+',
                'preserve_ephemeral': str(value).lower(),
                'action': 'rebuild',
                'glance_host': self._get_glance_host(),
                'access_ip_v4': '1.2.3.4',
                'access_ip_v6': '80fe::'
                }
        old_rebuild = compute_api.API.rebuild

        def fake_rebuild(self_, context, instance, image_href, admin_password,
                         files_to_inject=None, **kwargs):
            self.assertEqual(kwargs['preserve_ephemeral'], value)
            if resp_tpl:
                return old_rebuild(self_, context, instance, image_href,
                                   admin_password, files_to_inject=None,
                                   **kwargs)
        self.stub_out('nova.compute.api.API.rebuild', fake_rebuild)

        response = self._do_post('servers/%s/action' % uuid,
                                 'server-action-rebuild-preserve-ephemeral',
                                 subs)
        if resp_tpl:
            del subs['uuid']
            self._verify_response(resp_tpl, subs, response, 202)
        else:
            self.assertEqual(202, response.status_code)
Example #14
0
 def test_image_get(self):
     # Get api sample of one single image details request.
     image_id = fake.get_valid_image_id()
     response = self._do_get('images/%s' % image_id)
     subs = self._get_regexes()
     subs['image_id'] = image_id
     self._verify_response('image-get-resp', subs, response, 200)
Example #15
0
    def _post_server(self, use_common_server_api_samples=True):
        # param use_common_server_api_samples: Boolean to set whether tests use
        # common sample files for server post request and response.
        # Default is True which means _get_sample_path method will fetch the
        # common server sample files from 'servers' directory.
        # Set False if tests need to use extension specific sample files

        subs = {
            'image_id': fake.get_valid_image_id(),
            'host': self._get_host(),
            'compute_endpoint': self._get_compute_endpoint(),
            'versioned_compute_endpoint': self._get_vers_compute_endpoint(),
            'glance_host': self._get_glance_host(),
            'access_ip_v4': '1.2.3.4',
            'access_ip_v6': '80fe::'
        }
        orig_value = self.__class__._use_common_server_api_samples
        orig_sample_dir = self.__class__.sample_dir
        try:
            self.__class__._use_common_server_api_samples = (
                                        use_common_server_api_samples)
            response = self._do_post('servers', 'server-post-req', subs)
            subs = self._get_regexes()
            status = self._verify_response('server-post-resp', subs,
                                           response, 202)
            return status
        finally:
            self.__class__._use_common_server_api_samples = orig_value
            self.__class__.sample_dir = orig_sample_dir
Example #16
0
    def _post_server(self, use_common_server_api_samples=True):
        # param use_common_server_api_samples: Boolean to set whether tests use
        # common sample files for server post request and response.
        # Default is True which means _get_sample_path method will fetch the
        # common server sample files from 'servers' directory.
        # Set False if tests need to use extension specific sample files

        subs = {
            'image_id': fake.get_valid_image_id(),
            'host': self._get_host(),
            'glance_host': self._get_glance_host(),
            'access_ip_v4': '1.2.3.4',
            'access_ip_v6': '80fe::'
        }
        orig_value = self.__class__._use_common_server_api_samples
        orig_sample_dir = self.__class__.sample_dir
        try:
            self.__class__._use_common_server_api_samples = (
                                        use_common_server_api_samples)
            # TODO(gmann) This is temporary hack to let other tests
            # inherited from ServersSampleBase run successfully.
            # Once all inherited tests are merged, below if condition
            # code needs to be removed.
            if ((self._api_version == 'v3') and
                use_common_server_api_samples):
                self.__class__._use_common_server_api_samples = False
                self.__class__.sample_dir = 'servers_v21'
            response = self._do_post('servers', 'server-post-req', subs)
            subs = self._get_regexes()
            status = self._verify_response('server-post-resp', subs,
                                           response, 202)
            return status
        finally:
            self.__class__._use_common_server_api_samples = orig_value
            self.__class__.sample_dir = orig_sample_dir
Example #17
0
    def test_instance_from_buildrequest(self):
        self.useFixture(nova_fixtures.AllServicesCurrent())
        image_ref = fake_image.get_valid_image_id()
        body = {
            'server': {
                'name': 'foo',
                'imageRef': image_ref,
                'flavorRef': '1',
                'networks': 'none',
            }
        }
        create_resp = self.api.api_post('servers', body)
        get_resp = self.api.api_get('servers/%s' %
                                    create_resp.body['server']['id'])

        server = get_resp.body['server']
        # Validate a few things
        self.assertEqual('foo', server['name'])
        self.assertEqual(image_ref, server['image']['id'])
        self.assertEqual('1', server['flavor']['id'])
        self.assertEqual('', server['hostId'])
        self.assertIsNone(None, server['OS-SRV-USG:launched_at'])
        self.assertIsNone(None, server['OS-SRV-USG:terminated_at'])
        self.assertFalse(server['locked'])
        self.assertEqual([], server['tags'])
        self.assertEqual('scheduling', server['OS-EXT-STS:task_state'])
        self.assertEqual('building', server['OS-EXT-STS:vm_state'])
        self.assertEqual('BUILD', server['status'])
Example #18
0
 def test_rebuild_server(self):
     uuid = self._post_server(use_common_server_api_samples=False)
     subs = {"image_id": fake.get_valid_image_id(), "host": self._get_host()}
     response = self._do_post("servers/%s/action" % uuid, "server-action-rebuild-req", subs)
     subs = self._get_regexes()
     subs["hostid"] = "[a-f0-9]+"
     self._verify_response("server-action-rebuild-resp", subs, response, 202)
Example #19
0
    def _post_server(self, use_common_server_api_samples=True):
        # param use_common_server_api_samples: Boolean to set whether tests use
        # common sample files for server post request and response.
        # Default is True which means _get_sample_path method will fetch the
        # common server sample files from 'servers' directory.
        # Set False if tests need to use extension specific sample files

        subs = {
            "image_id": fake.get_valid_image_id(),
            "host": self._get_host(),
            "compute_endpoint": self._get_compute_endpoint(),
            "versioned_compute_endpoint": self._get_vers_compute_endpoint(),
            "glance_host": self._get_glance_host(),
            "access_ip_v4": "1.2.3.4",
            "access_ip_v6": "80fe::",
        }
        orig_value = self.__class__._use_common_server_api_samples
        orig_sample_dir = self.__class__.sample_dir
        try:
            self.__class__._use_common_server_api_samples = use_common_server_api_samples
            response = self._do_post("servers", "server-post-req", subs)
            status = self._verify_response("server-post-resp", subs, response, 202)
            return status
        finally:
            self.__class__._use_common_server_api_samples = orig_value
            self.__class__.sample_dir = orig_sample_dir
Example #20
0
    def _post_server(self, use_common_server_api_samples=True, name=None):
        # param use_common_server_api_samples: Boolean to set whether tests use
        # common sample files for server post request and response.
        # Default is True which means _get_sample_path method will fetch the
        # common server sample files from 'servers' directory.
        # Set False if tests need to use extension specific sample files
        subs = {
            'image_id': fake.get_valid_image_id(),
            'host': self._get_host(),
            'compute_endpoint': self._get_compute_endpoint(),
            'versioned_compute_endpoint': self._get_vers_compute_endpoint(),
            'glance_host': self._get_glance_host(),
            'access_ip_v4': '1.2.3.4',
            'access_ip_v6': '80fe::',
            'user_data': (self.user_data if six.PY2
                          else self.user_data.decode('utf-8')),
            'uuid': '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}'
                    '-[0-9a-f]{4}-[0-9a-f]{12}',
            'name': 'new-server-test' if name is None else name,
        }

        orig_value = self.__class__._use_common_server_api_samples
        try:
            self.__class__._use_common_server_api_samples = (
                                        use_common_server_api_samples)
            response = self._do_post('servers', self._get_request_name(
                use_common_server_api_samples), subs)
            status = self._verify_response('server-create-resp', subs,
                                           response, 202)
            return status
        finally:
            self.__class__._use_common_server_api_samples = orig_value
Example #21
0
    def test_server_rebuild(self):
        uuid = self._post_server()
        image = fake.get_valid_image_id()
        params = {
            'uuid': image,
            'access_ip_v4': '1.2.3.4',
            'access_ip_v6': '80fe::',
            'disk_config': 'AUTO',
            'hostid': '[a-f0-9]+',
            'name': 'foobar',
            'pass': '******',
            'preserve_ephemeral': 'false',
            'description': 'description of foobar'
        }

        # Add 'tag1' and 'tag2' tags
        self._do_put('servers/%s/tags/tag1' % uuid)
        self._do_put('servers/%s/tags/tag2' % uuid)

        # Rebuild Action
        resp = self._do_post('servers/%s/action' % uuid,
                             'server-action-rebuild', params)

        subs = params.copy()
        del subs['uuid']
        self._verify_response('server-action-rebuild-resp', subs, resp, 202)
Example #22
0
 def test_scheduler_hints_post(self):
     # Get api sample of scheduler hint post request.
     subs = self._get_regexes()
     subs.update({'image_id': fake.get_valid_image_id(),
                  'image_near': str(uuid.uuid4())})
     response = self._do_post('servers', 'scheduler-hints-post-req',
                              subs)
     self._verify_response('scheduler-hints-post-resp', subs, response, 202)
 def test_servers_post(self):
     subs = {
         "image_id": fake.get_valid_image_id(),
         "host": self._get_host(),
         "access_ip_v4": "1.2.3.4",
         "access_ip_v6": "fe80::",
     }
     self._servers_post(subs)
Example #24
0
 def test_delete_instance_from_buildrequest(self):
     self.useFixture(nova_fixtures.AllServicesCurrent())
     image_ref = fake_image.get_valid_image_id()
     body = {"server": {"name": "foo", "imageRef": image_ref, "flavorRef": "1"}}
     create_resp = self.api.api_post("servers", body)
     self.api.api_delete("servers/%s" % create_resp.body["server"]["id"])
     get_resp = self.api.api_get("servers/%s" % create_resp.body["server"]["id"], check_response_status=False)
     self.assertEqual(404, get_resp.status)
Example #25
0
 def test_servers_post(self):
     subs = {
         'image_id': fake.get_valid_image_id(),
         'compute_endpoint': self._get_compute_endpoint(),
         'access_ip_v4': '1.2.3.4',
         'access_ip_v6': 'fe80::'
     }
     self._servers_post(subs)
Example #26
0
 def _rescue(self, uuid):
     req_subs = {
         'password': '******',
         'rescue_image_ref': fake.get_valid_image_id()
     }
     response = self._do_post('servers/%s/action' % uuid,
                              'server-rescue-req', req_subs)
     self._verify_response('server-rescue', req_subs, response, 200)
Example #27
0
 def test_scheduler_hints_post(self):
     # Get api sample of scheduler hint post request.
     subs = {'image_id': fake.get_valid_image_id(),
             'uuid': str(uuid.uuid4())}
     response = self._do_post('servers', 'scheduler-hints-post-req',
                              subs)
     del subs['uuid']
     self._verify_response('scheduler-hints-post-resp', subs, response, 202)
Example #28
0
 def test_cloud_pipe_create(self):
     # Get api samples of cloud pipe extension creation.
     self.flags(vpn_image_id=fake.get_valid_image_id())
     subs = {'project_id': str(uuid_lib.uuid4().hex)}
     response = self._do_post('os-cloudpipe', 'cloud-pipe-create-req',
                              subs)
     subs['image_id'] = CONF.vpn_image_id
     self._verify_response('cloud-pipe-create-resp', subs, response, 200)
     return subs
Example #29
0
 def _post_server(self):
     subs = {
         'image_id': fake.get_valid_image_id(),
         'host': self._get_host(),
         'glance_host': self._get_glance_host()
     }
     response = self._do_post('servers', 'server-post-req', subs)
     subs = self._get_regexes()
     return self._verify_response('server-post-resp', subs, response, 202)
Example #30
0
 def test_multiple_create(self):
     subs = {
         'image_id': fake.get_valid_image_id(),
         'compute_endpoint': self._get_compute_endpoint(),
         'min_count': "2",
         'max_count': "3"
     }
     response = self._do_post('servers', 'multiple-create-post-req', subs)
     self._verify_response('multiple-create-post-resp', subs, response, 202)
    def test_live_migrate_implicit_az(self):
        """Tests live migration of an instance with an implicit AZ.

        Before Pike, a server created without an explicit availability zone
        was assigned a default AZ based on the "default_schedule_zone" config
        option which defaults to None, which allows the instance to move
        freely between availability zones.

        With change I8d426f2635232ffc4b510548a905794ca88d7f99 in Pike, if the
        user does not request an availability zone, the
        instance.availability_zone field is set based on the host chosen by
        the scheduler. The default AZ for all nova-compute services is
        determined by the "default_availability_zone" config option which
        defaults to "nova".

        This test creates two nova-compute services in separate zones, creates
        a server without specifying an explicit zone, and then tries to live
        migrate the instance to the other compute which should succeed because
        the request spec does not include an explicit AZ, so the instance is
        still not restricted to its current zone even if it says it is in one.
        """
        # Start two compute services in separate zones.
        self._start_host_in_zone('host1', 'zone1')
        self._start_host_in_zone('host2', 'zone2')

        # Create a server, it doesn't matter which host it ends up in.
        server_body = self._build_minimal_create_server_request(
            self.api,
            'test_live_migrate_implicit_az_restriction',
            image_uuid=fake_image.get_valid_image_id(),
            networks='none')
        server = self.api.post_server({'server': server_body})
        server = self._wait_for_state_change(self.api, server, 'ACTIVE')
        original_host = server['OS-EXT-SRV-ATTR:host']
        # Assert the server has the AZ set (not None or 'nova').
        expected_zone = 'zone1' if original_host == 'host1' else 'zone2'
        self.assertEqual(expected_zone, server['OS-EXT-AZ:availability_zone'])

        # Attempt to live migrate the instance; again, we don't specify a host
        # because there are only two hosts so the scheduler would only be able
        # to pick the second host which is in a different zone.
        live_migrate_req = {
            'os-migrateLive': {
                'block_migration': 'auto',
                'host': None
            }
        }
        self.api.post_server_action(server['id'], live_migrate_req)

        # Poll the migration until it is done.
        migration = self._wait_for_migration_status(server, ['completed'])
        self.assertEqual('live-migration', migration['migration_type'])

        # Assert that the server did move. Note that we check both the API and
        # the database because the API will return the AZ from the host
        # aggregate if instance.host is not None.
        server = self.api.get_server(server['id'])
        expected_zone = 'zone2' if original_host == 'host1' else 'zone1'
        self.assertEqual(expected_zone, server['OS-EXT-AZ:availability_zone'])

        ctxt = context.get_admin_context()
        with context.target_cell(ctxt,
                                 self.cell_mappings[test.CELL1_NAME]) as cctxt:
            instance = objects.Instance.get_by_uuid(cctxt, server['id'])
            self.assertEqual(expected_zone, instance.availability_zone)
Example #32
0
 def test_get_image(self):
     image_id = fake.get_valid_image_id()
     response = self._do_get('images/%s' % image_id)
     subs = self._get_regexes()
     subs['image_id'] = image_id
     self._verify_response('image-get-resp', subs, response, 200)
Example #33
0
    def test_migrate_disk_and_power_off_crash_finish_revert_migration(self):
        """Tests the scenario that the compute service crashes while the
        driver's migrate_disk_and_power_off method is running (we could be
        slow transferring disks or something when it crashed) and on restart
        of the compute service the driver's finish_revert_migration method
        is called to cleanup the source host and reset the instance task_state.
        """
        # Start two compute service so we migrate across hosts.
        for x in range(2):
            self._start_compute('host%d' % x)
        # Create a server, it does not matter on which host it lands.
        name = 'test_migrate_disk_and_power_off_crash_finish_revert_migration'
        server = self._build_minimal_create_server_request(
            name, image_uuid=fake_image.get_valid_image_id(), networks='auto')
        server = self.api.post_server({'server': server})
        server = self._wait_for_state_change(server, 'ACTIVE')
        # Save the source hostname for assertions later.
        source_host = server['OS-EXT-SRV-ATTR:host']

        def fake_migrate_disk_and_power_off(*args, **kwargs):
            # Simulate the source compute service crashing by restarting it.
            self.restart_compute_service(self.computes[source_host])
            # We have to keep the method from returning before asserting the
            # _init_instance restart behavior otherwise resize_instance will
            # fail and set the instance to ERROR status, revert allocations,
            # etc which is not realistic if the service actually crashed while
            # migrate_disk_and_power_off was running.
            # The sleep value needs to be large to avoid this waking up and
            # interfering with other tests running on the same worker.
            time.sleep(1000000)

        source_driver = self.computes[source_host].manager.driver
        with mock.patch.object(source_driver,
                               'migrate_disk_and_power_off',
                               side_effect=fake_migrate_disk_and_power_off):
            # Initiate a cold migration from the source host.
            self.admin_api.post_server_action(server['id'], {'migrate': None})
            # Now wait for the task_state to be reset to None during
            # _init_instance.
            server = self._wait_for_server_parameter(
                server, {
                    'status': 'ACTIVE',
                    'OS-EXT-STS:task_state': None,
                    'OS-EXT-SRV-ATTR:host': source_host
                })

        # Assert we went through the _init_instance processing we expect.
        log_out = self.stdlog.logger.output
        self.assertIn(
            'Instance found in migrating state during startup. '
            'Resetting task_state', log_out)
        # Assert that driver.finish_revert_migration did not raise an error.
        self.assertNotIn('Failed to revert crashed migration', log_out)

        # The migration status should be "error" rather than stuck as
        # "migrating".
        context = nova_context.get_admin_context()
        # FIXME(mriedem): This is bug 1836369 because we would normally expect
        # Migration.get_by_instance_and_status to raise
        # MigrationNotFoundByStatus since the status should be "error".
        objects.Migration.get_by_instance_and_status(context, server['id'],
                                                     'migrating')

        # Assert things related to the resize get cleaned up:
        # - things set on the instance during prep_resize like:
        #   - migration_context
        #   - new_flavor
        #   - stashed old_vm_state in system_metadata
        # - migration-based allocations from conductor/scheduler, i.e. that the
        #   allocations created by the scheduler for the instance and dest host
        #   are gone and the source host allocations are back on the instance
        #   rather than the migration record
        instance = objects.Instance.get_by_uuid(
            context,
            server['id'],
            expected_attrs=['migration_context', 'flavor', 'system_metadata'])
        # FIXME(mriedem): Leaving these fields set on the instance is
        # bug 1836369.
        self.assertIsNotNone(instance.migration_context)
        self.assertIsNotNone(instance.new_flavor)
        self.assertEqual('active', instance.system_metadata['old_vm_state'])

        dest_host = 'host0' if source_host == 'host1' else 'host1'
        dest_rp_uuid = self._get_provider_uuid_by_host(dest_host)
        dest_allocations = self._get_allocations_by_provider_uuid(dest_rp_uuid)
        # FIXME(mriedem): This is bug 1836369 because we orphaned the
        # allocations created by the scheduler for the server on the dest host.
        self.assertIn(server['id'], dest_allocations)
        source_rp_uuid = self._get_provider_uuid_by_host(source_host)
        source_allocations = self._get_allocations_by_provider_uuid(
            source_rp_uuid)
        # FIXME(mriedem): This is bug 1836369 because the server is running on
        # the source host but is not tracking allocations against the source
        # host.
        self.assertNotIn(server['id'], source_allocations)
Example #34
0
    def test_build_reschedule_alt_host_alloc_fails(self):
        # Start two compute services so we have one alternate host.
        # Set cpu_allocation_ratio=1.0 to make placement inventory
        # and allocations for VCPU easier to manage.
        self.flags(cpu_allocation_ratio=1.0)
        for x in range(2):
            self._start_compute('host%i' % x)

        def fake_instance_claim(_self, _context, _inst, nodename, *a, **kw):
            # Before triggering the reschedule to the other host, max out the
            # capacity on the alternate host.
            alt_nodename = 'host0' if nodename == 'host1' else 'host1'
            rp_uuid = self._get_provider_uuid_by_host(alt_nodename)
            inventories = self._get_provider_inventory(rp_uuid)
            # Fake some other consumer taking all of the VCPU on the alt host.
            # Since we set cpu_allocation_ratio=1.0 the total is the total
            # capacity for VCPU on the host.
            total_vcpu = inventories['VCPU']['total']
            alt_consumer = '7d32d0bc-af16-44b2-8019-a24925d76152'
            allocs = {
                'allocations': {
                    rp_uuid: {
                        'resources': {
                            'VCPU': total_vcpu
                        }
                    }
                },
                'project_id': self.api.project_id,
                'user_id': self.api.project_id
            }
            resp = self.placement_api.put('/allocations/%s' % alt_consumer,
                                          allocs,
                                          version='1.12')
            self.assertEqual(204, resp.status, resp.content)
            raise exception.ComputeResourcesUnavailable(reason='overhead!')

        # Stub out the instance claim (regardless of which host the scheduler
        # picks as the primary) to trigger a reschedule.
        self.stub_out(
            'nova.compute.manager.resource_tracker.ResourceTracker.'
            'instance_claim', fake_instance_claim)

        # Now that our stub is in place, try to create a server and wait for it
        # to go to ERROR status.
        server = self._build_minimal_create_server_request(
            self.api,
            'test_build_reschedule_alt_host_alloc_fails',
            image_uuid=fake_image.get_valid_image_id(),
            networks=[{
                'port': nova_fixtures.NeutronFixture.port_1['id']
            }])
        server = self.api.post_server({'server': server})
        server = self._wait_for_state_change(self.api, server, 'ERROR')

        # Wait for the MaxRetriesExceeded fault to be recorded.
        # set_vm_state_and_notify sets the vm_state to ERROR before the fault
        # is recorded but after the notification is sent. So wait for the
        # unversioned notification to show up and then get the fault.
        self._wait_for_unversioned_notification('compute_task.build_instances')
        server = self.api.get_server(server['id'])
        self.assertIn('fault', server)
        self.assertIn('Exceeded maximum number of retries',
                      server['fault']['message'])