Exemplo n.º 1
0
    def test_basic_schedule_run_instance(self):
        ctxt = context.RequestContext('fake', 'fake', False)
        ctxt_elevated = 'fake-context-elevated'
        fake_args = (1, 2, 3)
        fake_kwargs = {'fake_kwarg1': 'fake_value1',
                       'fake_kwarg2': 'fake_value2'}
        instance_opts = {'fake_opt1': 'meow'}
        request_spec = {'num_instances': 2,
                        'instance_properties': instance_opts}
        instance1 = {'uuid': 'fake-uuid1'}
        instance2 = {'uuid': 'fake-uuid2'}
        instance1_encoded = {'uuid': 'fake-uuid1', '_is_precooked': False}
        instance2_encoded = {'uuid': 'fake-uuid2', '_is_precooked': False}
        reservations = ['resv1', 'resv2']

        # create_instance_db_entry() usually does this, but we're
        # stubbing it.
        def _add_uuid1(ctxt, request_spec, reservations):
            request_spec['instance_properties']['uuid'] = 'fake-uuid1'

        def _add_uuid2(ctxt, request_spec, reservations):
            request_spec['instance_properties']['uuid'] = 'fake-uuid2'

        self.mox.StubOutWithMock(ctxt, 'elevated')
        self.mox.StubOutWithMock(self.driver, 'hosts_up')
        self.mox.StubOutWithMock(random, 'random')
        self.mox.StubOutWithMock(self.driver, 'create_instance_db_entry')
        self.mox.StubOutWithMock(driver, 'cast_to_compute_host')
        self.mox.StubOutWithMock(driver, 'encode_instance')

        ctxt.elevated().AndReturn(ctxt_elevated)
        # instance 1
        self.driver.hosts_up(ctxt_elevated, 'compute').AndReturn(
                ['host1', 'host2', 'host3', 'host4'])
        random.random().AndReturn(.5)
        self.driver.create_instance_db_entry(ctxt, request_spec,
                reservations).WithSideEffects(_add_uuid1).AndReturn(
                instance1)
        driver.cast_to_compute_host(ctxt, 'host3', 'run_instance',
                instance_uuid=instance1['uuid'], **fake_kwargs)
        driver.encode_instance(instance1).AndReturn(instance1_encoded)
        # instance 2
        ctxt.elevated().AndReturn(ctxt_elevated)
        self.driver.hosts_up(ctxt_elevated, 'compute').AndReturn(
                ['host1', 'host2', 'host3', 'host4'])
        random.random().AndReturn(.2)
        self.driver.create_instance_db_entry(ctxt, request_spec,
                reservations).WithSideEffects(_add_uuid2).AndReturn(
                instance2)
        driver.cast_to_compute_host(ctxt, 'host1', 'run_instance',
                instance_uuid=instance2['uuid'], **fake_kwargs)
        driver.encode_instance(instance2).AndReturn(instance2_encoded)

        self.mox.ReplayAll()
        result = self.driver.schedule_run_instance(ctxt, request_spec,
                reservations, *fake_args, **fake_kwargs)
        expected = [instance1_encoded, instance2_encoded]
        self.assertEqual(result, expected)
    def test_scheduler_includes_launch_index(self):
        ctxt = "fake-context"
        instance_opts = {'fake_opt1': 'meow'}
        request_spec = {
            'num_instances': 2,
            'instance_properties': instance_opts
        }
        instance1 = {'uuid': 'fake-uuid1'}
        instance2 = {'uuid': 'fake-uuid2'}

        # create_instance_db_entry() usually does this, but we're
        # stubbing it.
        def _add_uuid(num):
            """Return a function that adds the provided uuid number."""
            def _add_uuid_num(_, spec):
                spec['instance_properties']['uuid'] = 'fake-uuid%d' % num

            return _add_uuid_num

        def _has_launch_index(expected_index):
            """Return a function that verifies the expected index."""
            def _check_launch_index(value):
                if 'instance_properties' in value:
                    if 'launch_index' in value['instance_properties']:
                        index = value['instance_properties']['launch_index']
                        if index == expected_index:
                            return True
                return False

            return _check_launch_index

        self.mox.StubOutWithMock(self.driver, '_schedule')
        self.mox.StubOutWithMock(self.driver, 'create_instance_db_entry')
        self.mox.StubOutWithMock(driver, 'cast_to_compute_host')
        self.mox.StubOutWithMock(driver, 'encode_instance')
        # instance 1
        self.driver._schedule(ctxt, 'compute', request_spec).AndReturn('host')
        self.driver.create_instance_db_entry(
            ctxt, mox.Func(_has_launch_index(0))).WithSideEffects(
                _add_uuid(1)).AndReturn(instance1)
        driver.cast_to_compute_host(ctxt,
                                    'host',
                                    'run_instance',
                                    instance_uuid=instance1['uuid'])
        driver.encode_instance(instance1).AndReturn(instance1)
        # instance 2
        self.driver._schedule(ctxt, 'compute', request_spec).AndReturn('host')
        self.driver.create_instance_db_entry(
            ctxt, mox.Func(_has_launch_index(1))).WithSideEffects(
                _add_uuid(2)).AndReturn(instance2)
        driver.cast_to_compute_host(ctxt,
                                    'host',
                                    'run_instance',
                                    instance_uuid=instance2['uuid'])
        driver.encode_instance(instance2).AndReturn(instance2)
        self.mox.ReplayAll()

        self.driver.schedule_run_instance(ctxt, request_spec)
Exemplo n.º 3
0
    def test_basic_schedule_run_instance(self):
        ctxt = context.RequestContext('fake', 'fake', False)
        ctxt_elevated = 'fake-context-elevated'
        fake_args = (1, 2, 3)
        fake_kwargs = {'fake_kwarg1': 'fake_value1',
                       'fake_kwarg2': 'fake_value2'}
        instance_opts = {'fake_opt1': 'meow'}
        request_spec = {'num_instances': 2,
                        'instance_properties': instance_opts}
        instance1 = {'uuid': 'fake-uuid1'}
        instance2 = {'uuid': 'fake-uuid2'}
        instance1_encoded = {'uuid': 'fake-uuid1', '_is_precooked': False}
        instance2_encoded = {'uuid': 'fake-uuid2', '_is_precooked': False}

        # create_instance_db_entry() usually does this, but we're
        # stubbing it.
        def _add_uuid1(ctxt, request_spec):
            request_spec['instance_properties']['uuid'] = 'fake-uuid1'

        def _add_uuid2(ctxt, request_spec):
            request_spec['instance_properties']['uuid'] = 'fake-uuid2'

        self.mox.StubOutWithMock(ctxt, 'elevated')
        self.mox.StubOutWithMock(self.driver, 'hosts_up')
        self.mox.StubOutWithMock(random, 'random')
        self.mox.StubOutWithMock(self.driver, 'create_instance_db_entry')
        self.mox.StubOutWithMock(driver, 'cast_to_compute_host')
        self.mox.StubOutWithMock(driver, 'encode_instance')

        ctxt.elevated().AndReturn(ctxt_elevated)
        # instance 1
        self.driver.hosts_up(ctxt_elevated, 'compute').AndReturn(
                ['host1', 'host2', 'host3', 'host4'])
        random.random().AndReturn(.5)
        self.driver.create_instance_db_entry(ctxt,
                request_spec).WithSideEffects(_add_uuid1).AndReturn(
                instance1)
        driver.cast_to_compute_host(ctxt, 'host3', 'run_instance',
                instance_uuid=instance1['uuid'], **fake_kwargs)
        driver.encode_instance(instance1).AndReturn(instance1_encoded)
        # instance 2
        ctxt.elevated().AndReturn(ctxt_elevated)
        self.driver.hosts_up(ctxt_elevated, 'compute').AndReturn(
                ['host1', 'host2', 'host3', 'host4'])
        random.random().AndReturn(.2)
        self.driver.create_instance_db_entry(ctxt,
                request_spec).WithSideEffects(_add_uuid2).AndReturn(
                instance2)
        driver.cast_to_compute_host(ctxt, 'host1', 'run_instance',
                instance_uuid=instance2['uuid'], **fake_kwargs)
        driver.encode_instance(instance2).AndReturn(instance2_encoded)

        self.mox.ReplayAll()
        result = self.driver.schedule_run_instance(ctxt, request_spec,
                *fake_args, **fake_kwargs)
        expected = [instance1_encoded, instance2_encoded]
        self.assertEqual(result, expected)
Exemplo n.º 4
0
    def test_basic_schedule_run_instance(self):
        ctxt = context.RequestContext('fake', 'fake', False)
        ctxt_elevated = 'fake-context-elevated'
        fake_args = (1, 2, 3)
        instance_opts = {'fake_opt1': 'meow', 'launch_index': -1}
        instance1 = {'uuid': 'fake-uuid1'}
        instance2 = {'uuid': 'fake-uuid2'}
        request_spec = {'instance_uuids': ['fake-uuid1', 'fake-uuid2'],
                        'instance_properties': instance_opts}
        instance1_encoded = {'uuid': 'fake-uuid1', '_is_precooked': False}
        instance2_encoded = {'uuid': 'fake-uuid2', '_is_precooked': False}
        reservations = ['resv1', 'resv2']

        def inc_launch_index(*args):
            request_spec['instance_properties']['launch_index'] = (
                request_spec['instance_properties']['launch_index'] + 1)

        self.mox.StubOutWithMock(ctxt, 'elevated')
        self.mox.StubOutWithMock(self.driver, 'hosts_up')
        self.mox.StubOutWithMock(random, 'random')
        self.mox.StubOutWithMock(driver, 'encode_instance')
        self.mox.StubOutWithMock(driver, 'instance_update_db')
        self.mox.StubOutWithMock(compute_rpcapi.ComputeAPI, 'run_instance')

        ctxt.elevated().AndReturn(ctxt_elevated)
        # instance 1
        self.driver.hosts_up(ctxt_elevated, 'compute').AndReturn(
                ['host1', 'host2', 'host3', 'host4'])
        random.random().AndReturn(.5)
        driver.instance_update_db(ctxt, instance1['uuid'],
                'host3').WithSideEffects(inc_launch_index).AndReturn(instance1)
        compute_rpcapi.ComputeAPI.run_instance(ctxt, host='host3',
                instance=instance1, requested_networks=None,
                injected_files=None, admin_password=None, is_first_time=None,
                request_spec=request_spec, filter_properties={})
        driver.encode_instance(instance1).AndReturn(instance1_encoded)

        # instance 2
        ctxt.elevated().AndReturn(ctxt_elevated)
        self.driver.hosts_up(ctxt_elevated, 'compute').AndReturn(
                ['host1', 'host2', 'host3', 'host4'])
        random.random().AndReturn(.2)
        driver.instance_update_db(ctxt, instance2['uuid'],
                'host1').WithSideEffects(inc_launch_index).AndReturn(instance2)
        compute_rpcapi.ComputeAPI.run_instance(ctxt, host='host1',
                instance=instance2, requested_networks=None,
                injected_files=None, admin_password=None, is_first_time=None,
                request_spec=request_spec, filter_properties={})
        driver.encode_instance(instance2).AndReturn(instance2_encoded)

        self.mox.ReplayAll()
        result = self.driver.schedule_run_instance(ctxt, request_spec,
                None, None, None, None, {})
        expected = [instance1_encoded, instance2_encoded]
        self.assertEqual(result, expected)
Exemplo n.º 5
0
    def test_scheduler_includes_launch_index(self):
        ctxt = "fake-context"
        instance_opts = {'fake_opt1': 'meow'}
        request_spec = {'num_instances': 2,
                        'instance_properties': instance_opts}
        instance1 = {'uuid': 'fake-uuid1'}
        instance2 = {'uuid': 'fake-uuid2'}

        # create_instance_db_entry() usually does this, but we're
        # stubbing it.
        def _add_uuid(num):
            """Return a function that adds the provided uuid number."""
            def _add_uuid_num(_, spec, reservations):
                spec['instance_properties']['uuid'] = 'fake-uuid%d' % num
            return _add_uuid_num

        def _has_launch_index(expected_index):
            """Return a function that verifies the expected index."""
            def _check_launch_index(value):
                if 'instance_properties' in value:
                    if 'launch_index' in value['instance_properties']:
                        index = value['instance_properties']['launch_index']
                        if index == expected_index:
                            return True
                return False
            return _check_launch_index

        self.mox.StubOutWithMock(self.driver, '_schedule')
        self.mox.StubOutWithMock(self.driver, 'create_instance_db_entry')
        self.mox.StubOutWithMock(driver, 'cast_to_compute_host')
        self.mox.StubOutWithMock(driver, 'encode_instance')
        # instance 1
        self.driver._schedule(ctxt, 'compute', request_spec).AndReturn('host')
        self.driver.create_instance_db_entry(
            ctxt, mox.Func(_has_launch_index(0)), None
            ).WithSideEffects(_add_uuid(1)).AndReturn(instance1)
        driver.cast_to_compute_host(ctxt, 'host', 'run_instance',
                                    instance_uuid=instance1['uuid'])
        driver.encode_instance(instance1).AndReturn(instance1)
        # instance 2
        self.driver._schedule(ctxt, 'compute', request_spec).AndReturn('host')
        self.driver.create_instance_db_entry(
            ctxt, mox.Func(_has_launch_index(1)), None
            ).WithSideEffects(_add_uuid(2)).AndReturn(instance2)
        driver.cast_to_compute_host(ctxt, 'host', 'run_instance',
                                    instance_uuid=instance2['uuid'])
        driver.encode_instance(instance2).AndReturn(instance2)
        self.mox.ReplayAll()

        self.driver.schedule_run_instance(ctxt, request_spec, None)
Exemplo n.º 6
0
    def _provision_resource(self, context, weighted_host, request_spec,
            reservations, filter_properties, requested_networks,
            injected_files, admin_password, is_first_time):
        """Create the requested resource in this Zone."""
        instance = self.create_instance_db_entry(context, request_spec,
                                                 reservations)

        # Add a retry entry for the selected compute host:
        self._add_retry_host(filter_properties, weighted_host.host_state.host)

        payload = dict(request_spec=request_spec,
                       weighted_host=weighted_host.to_dict(),
                       instance_id=instance['uuid'])
        notifier.notify(context, notifier.publisher_id("scheduler"),
                        'scheduler.run_instance.scheduled', notifier.INFO,
                        payload)

        updated_instance = driver.instance_update_db(context, instance['uuid'],
                weighted_host.host_state.host)

        self.compute_rpcapi.run_instance(context, instance=updated_instance,
                host=weighted_host.host_state.host,
                request_spec=request_spec, filter_properties=filter_properties,
                requested_networks=requested_networks,
                injected_files=injected_files,
                admin_password=admin_password, is_first_time=is_first_time)

        inst = driver.encode_instance(updated_instance, local=True)

        # So if another instance is created, create_instance_db_entry will
        # actually create a new entry, instead of assume it's been created
        # already
        del request_spec['instance_properties']['uuid']

        return inst
Exemplo n.º 7
0
 def schedule_run_instance(self, context, request_spec, admin_password,
                           injected_files, requested_networks,
                           is_first_time, filter_properties, reservations):
     """Create and run an instance or instances"""
     num_instances = request_spec.get('num_instances', 1)
     instances = []
     for num in xrange(num_instances):
         host = self._schedule(context, 'compute', request_spec,
                               filter_properties)
         request_spec['instance_properties']['launch_index'] = num
         instance = self.create_instance_db_entry(context, request_spec,
                                                  reservations)
         updated_instance = driver.instance_update_db(
             context, instance['uuid'], host)
         self.compute_rpcapi.run_instance(
             context,
             instance=updated_instance,
             host=host,
             requested_networks=requested_networks,
             injected_files=injected_files,
             admin_password=admin_password,
             is_first_time=is_first_time,
             request_spec=request_spec,
             filter_properties=filter_properties)
         instances.append(driver.encode_instance(updated_instance))
         # So if we loop around, create_instance_db_entry will actually
         # create a new entry, instead of assume it's been created
         # already
         del request_spec['instance_properties']['uuid']
     return instances
Exemplo n.º 8
0
    def test_encode_instance(self):
        instance = {'id': 31337, 'test_arg': 'meow'}

        result = driver.encode_instance(instance, True)
        expected = {'id': instance['id'], '_is_precooked': False}
        self.assertThat(result, matchers.DictMatches(expected))
        # Orig dict not changed
        self.assertNotEqual(result, instance)

        result = driver.encode_instance(instance, False)
        expected = {}
        expected.update(instance)
        expected['_is_precooked'] = True
        self.assertThat(result, matchers.DictMatches(expected))
        # Orig dict not changed
        self.assertNotEqual(result, instance)
Exemplo n.º 9
0
    def _provision_resource(self, context, weighted_host, request_spec,
            reservations, filter_properties, kwargs):
        """Create the requested resource in this Zone."""
        instance = self.create_instance_db_entry(context, request_spec,
                                                 reservations)

        # Add a retry entry for the selected compute host:
        self._add_retry_host(filter_properties, weighted_host.host_state.host)

        payload = dict(request_spec=request_spec,
                       weighted_host=weighted_host.to_dict(),
                       instance_id=instance['uuid'])
        notifier.notify(context, notifier.publisher_id("scheduler"),
                        'scheduler.run_instance.scheduled', notifier.INFO,
                        payload)

        driver.cast_to_compute_host(context, weighted_host.host_state.host,
                'run_instance', instance_uuid=instance['uuid'],
                request_spec=request_spec, filter_properties=filter_properties,
                **kwargs)
        inst = driver.encode_instance(instance, local=True)

        # So if another instance is created, create_instance_db_entry will
        # actually create a new entry, instead of assume it's been created
        # already
        del request_spec['instance_properties']['uuid']

        return inst
Exemplo n.º 10
0
 def schedule_run_instance(self, context, request_spec,
                           admin_password, injected_files,
                           requested_networks, is_first_time,
                           filter_properties, reservations):
     """Create and run an instance or instances"""
     num_instances = request_spec.get('num_instances', 1)
     instances = []
     for num in xrange(num_instances):
         host = self._schedule(context, 'compute', request_spec,
                               filter_properties)
         request_spec['instance_properties']['launch_index'] = num
         instance = self.create_instance_db_entry(context, request_spec,
                                                  reservations)
         updated_instance = driver.instance_update_db(context,
                 instance['uuid'], host)
         self.compute_rpcapi.run_instance(context,
                 instance=updated_instance, host=host,
                 requested_networks=requested_networks,
                 injected_files=injected_files,
                 admin_password=admin_password, is_first_time=is_first_time,
                 request_spec=request_spec,
                 filter_properties=filter_properties)
         instances.append(driver.encode_instance(updated_instance))
         # So if we loop around, create_instance_db_entry will actually
         # create a new entry, instead of assume it's been created
         # already
         del request_spec['instance_properties']['uuid']
     return instances
Exemplo n.º 11
0
 def schedule_run_instance(self, context, request_spec,
                           admin_password, injected_files,
                           requested_networks, is_first_time,
                           filter_properties, reservations):
     """Create and run an instance or instances"""
     if 'instance_uuids' not in request_spec:
         return self._legacy_schedule_run_instance(context, request_spec,
                 admin_password, injected_files, requested_networks,
                 is_first_time, filter_properties, reservations)
     instances = []
     instance_uuids = request_spec.get('instance_uuids')
     for num, instance_uuid in enumerate(instance_uuids):
         host = self._schedule(context, 'compute', request_spec,
                               filter_properties)
         request_spec['instance_properties']['launch_index'] = num
         updated_instance = driver.instance_update_db(context,
                 instance_uuid, host)
         self.compute_rpcapi.run_instance(context,
                 instance=updated_instance, host=host,
                 requested_networks=requested_networks,
                 injected_files=injected_files,
                 admin_password=admin_password, is_first_time=is_first_time,
                 request_spec=request_spec,
                 filter_properties=filter_properties)
         instances.append(driver.encode_instance(updated_instance))
     return instances
Exemplo n.º 12
0
 def _provision_resource_locally(self, context, weighted_host, request_spec,
                                 kwargs):
     """Create the requested resource in this Zone."""
     instance = self.create_instance_db_entry(context, request_spec)
     driver.cast_to_compute_host(context, weighted_host.host,
             'run_instance', instance_uuid=instance['uuid'], **kwargs)
     return driver.encode_instance(instance, local=True)
Exemplo n.º 13
0
    def test_encode_instance(self):
        instance = {"id": 31337, "test_arg": "meow"}

        result = driver.encode_instance(instance, True)
        expected = {"id": instance["id"], "_is_precooked": False}
        self.assertThat(result, matchers.DictMatches(expected))
        # Orig dict not changed
        self.assertNotEqual(result, instance)

        result = driver.encode_instance(instance, False)
        expected = {}
        expected.update(instance)
        expected["_is_precooked"] = True
        self.assertThat(result, matchers.DictMatches(expected))
        # Orig dict not changed
        self.assertNotEqual(result, instance)
Exemplo n.º 14
0
    def _provision_resource(self, context, weighted_host, request_spec,
                            reservations, filter_properties, kwargs):
        """Create the requested resource in this Zone."""
        instance = self.create_instance_db_entry(context, request_spec,
                                                 reservations)

        # Add a retry entry for the selected compute host:
        self._add_retry_host(filter_properties, weighted_host.host_state.host)

        payload = dict(request_spec=request_spec,
                       weighted_host=weighted_host.to_dict(),
                       instance_id=instance['uuid'])
        notifier.notify(context, notifier.publisher_id("scheduler"),
                        'scheduler.run_instance.scheduled', notifier.INFO,
                        payload)

        driver.cast_to_compute_host(context,
                                    weighted_host.host_state.host,
                                    'run_instance',
                                    instance_uuid=instance['uuid'],
                                    request_spec=request_spec,
                                    filter_properties=filter_properties,
                                    **kwargs)
        inst = driver.encode_instance(instance, local=True)

        # So if another instance is created, create_instance_db_entry will
        # actually create a new entry, instead of assume it's been created
        # already
        del request_spec['instance_properties']['uuid']

        return inst
Exemplo n.º 15
0
 def rpc_call_wrapper(context, topic, msg):
     """Stub out the scheduler creating the instance entry"""
     if topic == FLAGS.scheduler_topic and msg["method"] == "run_instance":
         scheduler = scheduler_driver.Scheduler
         instance = scheduler().create_instance_db_entry(context, msg["args"]["request_spec"])
         return [scheduler_driver.encode_instance(instance)]
     else:
         return orig_rpc_call(context, topic, msg)
Exemplo n.º 16
0
 def _provision_resource_locally(self, context, build_plan_item,
         request_spec, kwargs):
     """Create the requested resource in this Zone."""
     host = build_plan_item['hostname']
     instance = self.create_instance_db_entry(context, request_spec)
     driver.cast_to_compute_host(context, host,
             'run_instance', instance_id=instance['id'], **kwargs)
     return driver.encode_instance(instance, local=True)
Exemplo n.º 17
0
    def test_encode_instance(self):
        instance = {'id': 31337,
                    'test_arg': 'meow'}

        result = driver.encode_instance(instance, True)
        expected = {'id': instance['id'], '_is_precooked': False}
        self.assertThat(result, matchers.DictMatches(expected))
        # Orig dict not changed
        self.assertNotEqual(result, instance)

        result = driver.encode_instance(instance, False)
        expected = {}
        expected.update(instance)
        expected['_is_precooked'] = True
        self.assertThat(result, matchers.DictMatches(expected))
        # Orig dict not changed
        self.assertNotEqual(result, instance)
Exemplo n.º 18
0
 def schedule_run_instance(self, context, request_spec, *_args, **_kwargs):
     num_instances = request_spec.get("num_instances", 1)
     instances = []
     for num in xrange(num_instances):
         host = self._schedule_instance(context, request_spec["instance_properties"], *_args, **_kwargs)
         instance_ref = self.create_instance_db_entry(context, request_spec)
         driver.cast_to_compute_host(context, host, "run_instance", instance_id=instance_ref["id"], **_kwargs)
         instances.append(driver.encode_instance(instance_ref))
     return instances
Exemplo n.º 19
0
 def rpc_call_wrapper(context, topic, msg):
     """Stub out the scheduler creating the instance entry"""
     if (topic == FLAGS.scheduler_topic
             and msg['method'] == 'run_instance'):
         scheduler = scheduler_driver.Scheduler
         instance = scheduler().create_instance_db_entry(
             context, msg['args']['request_spec'])
         return [scheduler_driver.encode_instance(instance)]
     else:
         return orig_rpc_call(context, topic, msg)
Exemplo n.º 20
0
Arquivo: zone.py Projeto: Oneiroi/nova
 def schedule_run_instance(self, context, request_spec, *_args, **kwargs):
     """Builds and starts instances on selected hosts"""
     num_instances = request_spec.get('num_instances', 1)
     instances = []
     for num in xrange(num_instances):
         host = self._schedule(context, 'compute', request_spec, **kwargs)
         instance = self.create_instance_db_entry(context, request_spec)
         driver.cast_to_compute_host(context, host,
                 'run_instance', instance_id=instance['id'], **kwargs)
         instances.append(driver.encode_instance(instance))
     return instances
 def rpc_call_wrapper(context, topic, msg):
     """Stub out the scheduler creating the instance entry"""
     if (topic == FLAGS.scheduler_topic and
         msg['method'] == 'run_instance'):
         scheduler = scheduler_driver.Scheduler
         instance = scheduler().create_instance_db_entry(
                 context,
                 msg['args']['request_spec'])
         return [scheduler_driver.encode_instance(instance)]
     else:
         return orig_rpc_call(context, topic, msg)
Exemplo n.º 22
0
 def _provision_resource_locally(self, context, weighted_host, request_spec, kwargs):
     """Create the requested resource in this Zone."""
     instance = self.create_instance_db_entry(context, request_spec)
     driver.cast_to_compute_host(
         context, weighted_host.host, "run_instance", instance_uuid=instance["uuid"], **kwargs
     )
     inst = driver.encode_instance(instance, local=True)
     # So if another instance is created, create_instance_db_entry will
     # actually create a new entry, instead of assume it's been created
     # already
     del request_spec["instance_properties"]["uuid"]
     return inst
Exemplo n.º 23
0
 def _provision_resource_locally(self, context, weighted_host, request_spec,
                                 kwargs):
     """Create the requested resource in this Zone."""
     instance = self.create_instance_db_entry(context, request_spec)
     driver.cast_to_compute_host(context, weighted_host.host,
             'run_instance', instance_uuid=instance['uuid'], **kwargs)
     inst = driver.encode_instance(instance, local=True)
     # So if another instance is created, create_instance_db_entry will
     # actually create a new entry, instead of assume it's been created
     # already
     del request_spec['instance_properties']['uuid']
     return inst
Exemplo n.º 24
0
    def schedule_run_instance(self, context, request_spec, *_args, **kwargs):
        """Create and run an instance or instances"""
        elevated = context.elevated()
        num_instances = request_spec.get("num_instances", 1)
        instances = []
        for num in xrange(num_instances):
            host = self._schedule(context, "compute", **kwargs)
            instance = self.create_instance_db_entry(elevated, request_spec)
            driver.cast_to_compute_host(context, host, "run_instance", instance_id=instance["id"], **kwargs)
            instances.append(driver.encode_instance(instance))

        return instances
Exemplo n.º 25
0
 def schedule_run_instance(self, context, request_spec, *_args, **_kwargs):
     num_instances = request_spec.get('num_instances', 1)
     instances = []
     for num in xrange(num_instances):
         host = self._schedule_instance(context,
                 request_spec['instance_properties'], *_args, **_kwargs)
         instance_ref = self.create_instance_db_entry(context,
                 request_spec)
         driver.cast_to_compute_host(context, host, 'run_instance',
                 instance_uuid=instance_ref['uuid'], **_kwargs)
         instances.append(driver.encode_instance(instance_ref))
     return instances
Exemplo n.º 26
0
 def schedule_run_instance(self, context, request_spec, *_args, **_kwargs):
     num_instances = request_spec.get("num_instances", 1)
     instances = []
     for num in xrange(num_instances):
         host = self._schedule_instance(context, request_spec["instance_properties"], *_args, **_kwargs)
         request_spec["instance_properties"]["launch_index"] = num
         instance_ref = self.create_instance_db_entry(context, request_spec)
         driver.cast_to_compute_host(context, host, "run_instance", instance_uuid=instance_ref["uuid"], **_kwargs)
         instances.append(driver.encode_instance(instance_ref))
         # So if we loop around, create_instance_db_entry will actually
         # create a new entry, instead of assume it's been created
         # already
         del request_spec["instance_properties"]["uuid"]
     return instances
Exemplo n.º 27
0
 def schedule_run_instance(self, context, request_spec, *_args, **kwargs):
     """Create and run an instance or instances"""
     num_instances = request_spec.get('num_instances', 1)
     instances = []
     for num in xrange(num_instances):
         host = self._schedule(context, 'compute', request_spec, **kwargs)
         instance = self.create_instance_db_entry(context, request_spec)
         driver.cast_to_compute_host(context, host,
                 'run_instance', instance_uuid=instance['uuid'], **kwargs)
         instances.append(driver.encode_instance(instance))
         # So if we loop around, create_instance_db_entry will actually
         # create a new entry, instead of assume it's been created
         # already
         del request_spec['instance_properties']['uuid']
     return instances
Exemplo n.º 28
0
    def schedule_run_instance(self, context, request_spec, *_args, **kwargs):
        """Create and run an instance or instances"""
        elevated = context.elevated()
        num_instances = request_spec.get('num_instances', 1)
        instances = []
        for num in xrange(num_instances):
            host = self._schedule(context, 'compute', request_spec, **kwargs)
            instance = self.create_instance_db_entry(elevated, request_spec)
            driver.cast_to_compute_host(context,
                                        host,
                                        'run_instance',
                                        instance_uuid=instance['uuid'],
                                        **kwargs)
            instances.append(driver.encode_instance(instance))

        return instances
Exemplo n.º 29
0
 def schedule_run_instance(self, context, request_spec, *_args, **kwargs):
     """Create and run an instance or instances"""
     num_instances = request_spec.get('num_instances', 1)
     instances = []
     for num in xrange(num_instances):
         host = self._schedule(context, 'compute', request_spec, **kwargs)
         instance = self.create_instance_db_entry(context, request_spec)
         driver.cast_to_compute_host(context,
                                     host,
                                     'run_instance',
                                     instance_uuid=instance['uuid'],
                                     **kwargs)
         instances.append(driver.encode_instance(instance))
         # So if we loop around, create_instance_db_entry will actually
         # create a new entry, instead of assume it's been created
         # already
         del request_spec['instance_properties']['uuid']
     return instances
Exemplo n.º 30
0
 def schedule_run_instance(self, context, request_spec, reservations,
                           *_args, **_kwargs):
     num_instances = request_spec.get('num_instances', 1)
     instances = []
     for num in xrange(num_instances):
         host = self._schedule_instance(context,
                 request_spec['instance_properties'], *_args, **_kwargs)
         request_spec['instance_properties']['launch_index'] = num
         instance_ref = self.create_instance_db_entry(context,
                 request_spec, reservations)
         driver.cast_to_compute_host(context, host, 'run_instance',
                 instance_uuid=instance_ref['uuid'], **_kwargs)
         instances.append(driver.encode_instance(instance_ref))
         # So if we loop around, create_instance_db_entry will actually
         # create a new entry, instead of assume it's been created
         # already
         del request_spec['instance_properties']['uuid']
     return instances
Exemplo n.º 31
0
 def schedule_run_instance(self, context, request_spec, reservations,
                           *_args, **_kwargs):
     num_instances = request_spec.get('num_instances', 1)
     instances = []
     for num in xrange(num_instances):
         host = self._schedule_instance(context,
                                        request_spec['instance_properties'],
                                        *_args, **_kwargs)
         request_spec['instance_properties']['launch_index'] = num
         instance_ref = self.create_instance_db_entry(
             context, request_spec, reservations)
         driver.cast_to_compute_host(context,
                                     host,
                                     'run_instance',
                                     instance_uuid=instance_ref['uuid'],
                                     **_kwargs)
         instances.append(driver.encode_instance(instance_ref))
         # So if we loop around, create_instance_db_entry will actually
         # create a new entry, instead of assume it's been created
         # already
         del request_spec['instance_properties']['uuid']
     return instances
Exemplo n.º 32
0
 def schedule_run_instance(self, context, request_spec, *_args, **_kwargs):
     num_instances = request_spec.get('num_instances', 1)
     instances = []
     #Grazie ad xrange cicla num parte da 0 e arriva a num_instances-1
     for num in xrange(num_instances):
         host = self._schedule_instance(context, 
                 request_spec['instance_properties'], *_args, **_kwargs)
         request_spec['instance_properties']['launch_index'] = num
         instance_ref = self.create_instance_db_entry(context, 
                 request_spec)
         driver.cast_to_compute_host(context, host, 'run_instance', 
                 instance_uuid=instance_ref['uuid'], **_kwargs)
         instances.append(driver.encode_instance(instance_ref))
         # So if we loop around, create_instance_db_entry will actually
         # create a new entry, instead of assume it's been created
         # already
         del request_spec['instance_properties']['uuid']
         
         #Chiamo la funzione per aggiornare/creare le informazioni sulla VM che deve essere messa in esecuzione 
         #set_vm_information(instance_ref, context, "information")
         
     return instances
Exemplo n.º 33
0
    def _provision_resource(self, context, weighted_host, request_spec,
                            reservations, filter_properties,
                            requested_networks, injected_files, admin_password,
                            is_first_time):
        """Create the requested resource in this Zone."""
        instance = self.create_instance_db_entry(context, request_spec,
                                                 reservations)

        # Add a retry entry for the selected compute host:
        self._add_retry_host(filter_properties, weighted_host.host_state.host)

        payload = dict(request_spec=request_spec,
                       weighted_host=weighted_host.to_dict(),
                       instance_id=instance['uuid'])
        notifier.notify(context, notifier.publisher_id("scheduler"),
                        'scheduler.run_instance.scheduled', notifier.INFO,
                        payload)

        updated_instance = driver.instance_update_db(
            context, instance['uuid'], weighted_host.host_state.host)

        self.compute_rpcapi.run_instance(context,
                                         instance=updated_instance,
                                         host=weighted_host.host_state.host,
                                         request_spec=request_spec,
                                         filter_properties=filter_properties,
                                         requested_networks=requested_networks,
                                         injected_files=injected_files,
                                         admin_password=admin_password,
                                         is_first_time=is_first_time)

        inst = driver.encode_instance(updated_instance, local=True)

        # So if another instance is created, create_instance_db_entry will
        # actually create a new entry, instead of assume it's been created
        # already
        del request_spec['instance_properties']['uuid']

        return inst
Exemplo n.º 34
0
 def schedule_run_instance(self, context, request_spec, admin_password,
                           injected_files, requested_networks,
                           is_first_time, filter_properties):
     """Create and run an instance or instances"""
     instances = []
     instance_uuids = request_spec.get('instance_uuids')
     for num, instance_uuid in enumerate(instance_uuids):
         host = self._schedule(context, 'compute', request_spec,
                               filter_properties)
         request_spec['instance_properties']['launch_index'] = num
         updated_instance = driver.instance_update_db(
             context, instance_uuid, host)
         self.compute_rpcapi.run_instance(
             context,
             instance=updated_instance,
             host=host,
             requested_networks=requested_networks,
             injected_files=injected_files,
             admin_password=admin_password,
             is_first_time=is_first_time,
             request_spec=request_spec,
             filter_properties=filter_properties)
         instances.append(driver.encode_instance(updated_instance))
     return instances
Exemplo n.º 35
0
    def test_scheduler_includes_launch_index(self):
        ctxt = context.RequestContext('fake', 'fake', False)
        instance_opts = {'fake_opt1': 'meow'}
        request_spec = {
            'num_instances': 2,
            'instance_properties': instance_opts
        }
        instance1 = {'uuid': 'fake-uuid1'}
        instance2 = {'uuid': 'fake-uuid2'}

        # create_instance_db_entry() usually does this, but we're
        # stubbing it.
        def _add_uuid(num):
            """Return a function that adds the provided uuid number."""
            def _add_uuid_num(_, spec, reservations):
                spec['instance_properties']['uuid'] = 'fake-uuid%d' % num

            return _add_uuid_num

        def _has_launch_index(expected_index):
            """Return a function that verifies the expected index."""
            def _check_launch_index(value):
                if 'instance_properties' in value:
                    if 'launch_index' in value['instance_properties']:
                        index = value['instance_properties']['launch_index']
                        if index == expected_index:
                            return True
                return False

            return _check_launch_index

        self.mox.StubOutWithMock(self.driver, '_schedule')
        self.mox.StubOutWithMock(self.driver, 'create_instance_db_entry')
        self.mox.StubOutWithMock(driver, 'encode_instance')
        self.mox.StubOutWithMock(driver, 'instance_update_db')
        self.mox.StubOutWithMock(compute_rpcapi.ComputeAPI, 'run_instance')

        # instance 1
        self.driver._schedule(ctxt, 'compute', request_spec,
                              {}).AndReturn('host')
        self.driver.create_instance_db_entry(
            ctxt, mox.Func(_has_launch_index(0)),
            None).WithSideEffects(_add_uuid(1)).AndReturn(instance1)
        driver.instance_update_db(ctxt, instance1['uuid'],
                                  'host').AndReturn(instance1)
        compute_rpcapi.ComputeAPI.run_instance(ctxt,
                                               host='host',
                                               instance=instance1,
                                               requested_networks=None,
                                               injected_files=None,
                                               admin_password=None,
                                               is_first_time=None,
                                               request_spec=request_spec,
                                               filter_properties={})
        driver.encode_instance(instance1).AndReturn(instance1)
        # instance 2
        self.driver._schedule(ctxt, 'compute', request_spec,
                              {}).AndReturn('host')
        self.driver.create_instance_db_entry(
            ctxt, mox.Func(_has_launch_index(1)),
            None).WithSideEffects(_add_uuid(2)).AndReturn(instance2)
        driver.instance_update_db(ctxt, instance2['uuid'],
                                  'host').AndReturn(instance2)
        compute_rpcapi.ComputeAPI.run_instance(ctxt,
                                               host='host',
                                               instance=instance2,
                                               requested_networks=None,
                                               injected_files=None,
                                               admin_password=None,
                                               is_first_time=None,
                                               request_spec=request_spec,
                                               filter_properties={})
        driver.encode_instance(instance2).AndReturn(instance2)
        self.mox.ReplayAll()

        self.driver.schedule_run_instance(ctxt, request_spec, None, None, None,
                                          None, {}, None)
Exemplo n.º 36
0
class DistributedScheduler(driver.Scheduler):
    """Scheduler that can work across any nova deployment, from simple
    deployments to multiple nested zones.
    """
    def __init__(self, *args, **kwargs):
        super(DistributedScheduler, self).__init__(*args, **kwargs)
        self.cost_function_cache = {}
        self.options = scheduler_options.SchedulerOptions()

    def schedule(self, context, topic, method, *args, **kwargs):
        """The schedule() contract requires we return the one
        best-suited host for this request.

        NOTE: We're only focused on compute instances right now,
        so this method will always raise NoValidHost()."""
        msg = _("No host selection for %s defined." % topic)
        raise exception.NoValidHost(reason=msg)

    def schedule_run_instance(self, context, request_spec, *args, **kwargs):
        """This method is called from nova.compute.api to provision
        an instance. However we need to look at the parameters being
        passed in to see if this is a request to:
        1. Create build plan (a list of WeightedHosts) and then provision, or
        2. Use the WeightedHost information in the request parameters
           to simply create the instance (either in this zone or
           a child zone).

        returns a list of the instances created.
        """

        elevated = context.elevated()
        num_instances = request_spec.get('num_instances', 1)
        LOG.debug(_("Attempting to build %(num_instances)d instance(s)") %
                locals())

        weighted_hosts = []

        # Having a 'blob' hint means we've already provided a build plan.
        # We need to turn this back into a WeightedHost object.
        blob = request_spec.get('blob', None)
        if blob:
            weighted_hosts.append(self._make_weighted_host_from_blob(blob))
        else:
            # No plan ... better make one.
            weighted_hosts = self._schedule(elevated, "compute", request_spec,
                                        *args, **kwargs)

        if not weighted_hosts:
            raise exception.NoValidHost(reason=_(""))

        instances = []
        for num in xrange(num_instances):
            if not weighted_hosts:
                break
            weighted_host = weighted_hosts.pop(0)

            instance = None
            if weighted_host.host:
                instance = self._provision_resource_locally(elevated,
                                        weighted_host, request_spec, kwargs)
            else:
                instance = self._ask_child_zone_to_create_instance(elevated,
                                        weighted_host, request_spec, kwargs)

            if instance:
                instances.append(instance)

        return instances

    def schedule_prep_resize(self, context, request_spec, *args, **kwargs):
        """Select a target for resize.

        Selects a target host for the instance, post-resize, and casts
        the prep_resize operation to it.
        """

        # We need the new instance type ID...
        instance_type_id = kwargs['instance_type_id']

        elevated = context.elevated()
        LOG.debug(_("Attempting to determine target host for resize to "
                    "instance type %(instance_type_id)s") % locals())

        # Convert it to an actual instance type
        instance_type = db.instance_type_get(elevated, instance_type_id)

        # Now let's grab a possibility
        hosts = self._schedule(elevated, 'compute', request_spec,
                               *args, **kwargs)
        if not hosts:
            raise exception.NoValidHost(reason=_(""))
        host = hosts.pop(0)

        # Forward off to the host
        driver.cast_to_host(context, 'compute', host.host, 'prep_resize',
                            **kwargs)

    def select(self, context, request_spec, *args, **kwargs):
        """Select returns a list of weights and zone/host information
        corresponding to the best hosts to service the request. Any
        internal zone information will be encrypted so as not to reveal
        anything about our inner layout.
        """
        elevated = context.elevated()
        weighted_hosts = self._schedule(elevated, "compute", request_spec,
                *args, **kwargs)
        return [weighted_host.to_dict() for weighted_host in weighted_hosts]

    def _call_zone_method(self, context, method, specs, zones):
        """Call novaclient zone method. Broken out for testing."""
        return api.call_zone_method(context, method, specs=specs, zones=zones)

    def _provision_resource_locally(self, context, weighted_host, request_spec,
                                    kwargs):
        """Create the requested resource in this Zone."""
        instance = self.create_instance_db_entry(context, request_spec)
        driver.cast_to_compute_host(context, weighted_host.host,
                'run_instance', instance_uuid=instance['uuid'], **kwargs)
        inst = driver.encode_instance(instance, local=True)
        # So if another instance is created, create_instance_db_entry will
        # actually create a new entry, instead of assume it's been created
        # already
        del request_spec['instance_properties']['uuid']
        return inst

    def _make_weighted_host_from_blob(self, blob):
        """Returns the decrypted blob as a WeightedHost object
        or None if invalid. Broken out for testing.
        """
        decryptor = crypto.decryptor(FLAGS.build_plan_encryption_key)
        try:
            json_entry = decryptor(blob)
            # Extract our WeightedHost values
            wh_dict = json.loads(json_entry)
            host = wh_dict.get('host', None)
            blob = wh_dict.get('blob', None)
            zone = wh_dict.get('zone', None)
            return least_cost.WeightedHost(wh_dict['weight'],
                        host=host, blob=blob, zone=zone)

        except M2Crypto.EVP.EVPError:
            raise InvalidBlob()

    def _ask_child_zone_to_create_instance(self, context, weighted_host,
            request_spec, kwargs):
        """Once we have determined that the request should go to one
        of our children, we need to fabricate a new POST /servers/
        call with the same parameters that were passed into us.
        This request is always for a single instance.

        Note that we have to reverse engineer from our args to get back the
        image, flavor, ipgroup, etc. since the original call could have
        come in from EC2 (which doesn't use these things).
        """
        instance_type = request_spec['instance_type']
        instance_properties = request_spec['instance_properties']

        name = instance_properties['display_name']
        image_ref = instance_properties['image_ref']
        meta = instance_properties['metadata']
        flavor_id = instance_type['flavorid']
        reservation_id = instance_properties['reservation_id']
        files = kwargs['injected_files']

        zone = db.zone_get(context.elevated(), weighted_host.zone)
        zone_name = zone.name
        url = zone.api_url
        LOG.debug(_("Forwarding instance create call to zone '%(zone_name)s'. "
                "ReservationID=%(reservation_id)s") % locals())
        nova = None
        try:
            # This operation is done as the caller, not the zone admin.
            nova = novaclient.Client(zone.username, zone.password, None, url,
                                     token=context.auth_token,
                                     region_name=zone_name)
            nova.authenticate()
        except novaclient_exceptions.BadRequest, e:
            raise exception.NotAuthorized(_("Bad credentials attempting "
                    "to talk to zone at %(url)s.") % locals())
        # NOTE(Vek): Novaclient has two different calling conventions
        #            for this call, depending on whether you're using
        #            1.0 or 1.1 API: in 1.0, there's an ipgroups
        #            argument after flavor_id which isn't present in
        #            1.1.  To work around this, all the extra
        #            arguments are passed as keyword arguments
        #            (there's a reasonable default for ipgroups in the
        #            novaclient call).
        instance = nova.servers.create(name, image_ref, flavor_id,
                            meta=meta, files=files,
                            zone_blob=weighted_host.blob,
                            reservation_id=reservation_id)
        return driver.encode_instance(instance._info, local=False)
Exemplo n.º 37
0
    def test_basic_schedule_run_instance(self):
        ctxt = context.RequestContext('fake', 'fake', False)
        ctxt_elevated = 'fake-context-elevated'
        fake_args = (1, 2, 3)
        instance_opts = {'fake_opt1': 'meow'}
        request_spec = {
            'num_instances': 2,
            'instance_properties': instance_opts
        }
        instance1 = {'uuid': 'fake-uuid1'}
        instance2 = {'uuid': 'fake-uuid2'}
        instance1_encoded = {'uuid': 'fake-uuid1', '_is_precooked': False}
        instance2_encoded = {'uuid': 'fake-uuid2', '_is_precooked': False}
        reservations = ['resv1', 'resv2']

        # create_instance_db_entry() usually does this, but we're
        # stubbing it.
        def _add_uuid1(ctxt, request_spec, reservations):
            request_spec['instance_properties']['uuid'] = 'fake-uuid1'

        def _add_uuid2(ctxt, request_spec, reservations):
            request_spec['instance_properties']['uuid'] = 'fake-uuid2'

        self.mox.StubOutWithMock(ctxt, 'elevated')
        self.mox.StubOutWithMock(self.driver, 'hosts_up')
        self.mox.StubOutWithMock(random, 'random')
        self.mox.StubOutWithMock(self.driver, 'create_instance_db_entry')
        self.mox.StubOutWithMock(driver, 'encode_instance')
        self.mox.StubOutWithMock(driver, 'instance_update_db')
        self.mox.StubOutWithMock(compute_rpcapi.ComputeAPI, 'run_instance')

        ctxt.elevated().AndReturn(ctxt_elevated)
        # instance 1
        self.driver.hosts_up(ctxt_elevated, 'compute').AndReturn(
            ['host1', 'host2', 'host3', 'host4'])
        random.random().AndReturn(.5)
        self.driver.create_instance_db_entry(
            ctxt, request_spec,
            reservations).WithSideEffects(_add_uuid1).AndReturn(instance1)
        driver.instance_update_db(ctxt, instance1['uuid'],
                                  'host3').AndReturn(instance1)
        compute_rpcapi.ComputeAPI.run_instance(ctxt,
                                               host='host3',
                                               instance=instance1,
                                               requested_networks=None,
                                               injected_files=None,
                                               admin_password=None,
                                               is_first_time=None,
                                               request_spec=request_spec,
                                               filter_properties={})

        driver.encode_instance(instance1).AndReturn(instance1_encoded)
        # instance 2
        ctxt.elevated().AndReturn(ctxt_elevated)
        self.driver.hosts_up(ctxt_elevated, 'compute').AndReturn(
            ['host1', 'host2', 'host3', 'host4'])
        random.random().AndReturn(.2)
        self.driver.create_instance_db_entry(
            ctxt, request_spec,
            reservations).WithSideEffects(_add_uuid2).AndReturn(instance2)
        driver.instance_update_db(ctxt, instance2['uuid'],
                                  'host1').AndReturn(instance2)
        compute_rpcapi.ComputeAPI.run_instance(ctxt,
                                               host='host1',
                                               instance=instance2,
                                               requested_networks=None,
                                               injected_files=None,
                                               admin_password=None,
                                               is_first_time=None,
                                               request_spec=request_spec,
                                               filter_properties={})

        driver.encode_instance(instance2).AndReturn(instance2_encoded)

        self.mox.ReplayAll()
        result = self.driver.schedule_run_instance(ctxt, request_spec, None,
                                                   None, None, None, {},
                                                   reservations)
        expected = [instance1_encoded, instance2_encoded]
        self.assertEqual(result, expected)
Exemplo n.º 38
0
    def test_scheduler_includes_launch_index(self):
        ctxt = context.RequestContext('fake', 'fake', False)
        instance_opts = {'fake_opt1': 'meow'}
        request_spec = {'num_instances': 2,
                        'instance_properties': instance_opts}
        instance1 = {'uuid': 'fake-uuid1'}
        instance2 = {'uuid': 'fake-uuid2'}

        # create_instance_db_entry() usually does this, but we're
        # stubbing it.
        def _add_uuid(num):
            """Return a function that adds the provided uuid number."""
            def _add_uuid_num(_, spec, reservations):
                spec['instance_properties']['uuid'] = 'fake-uuid%d' % num
            return _add_uuid_num

        def _has_launch_index(expected_index):
            """Return a function that verifies the expected index."""
            def _check_launch_index(value):
                if 'instance_properties' in value:
                    if 'launch_index' in value['instance_properties']:
                        index = value['instance_properties']['launch_index']
                        if index == expected_index:
                            return True
                return False
            return _check_launch_index

        self.mox.StubOutWithMock(self.driver, '_schedule')
        self.mox.StubOutWithMock(self.driver, 'create_instance_db_entry')
        self.mox.StubOutWithMock(driver, 'encode_instance')
        self.mox.StubOutWithMock(driver, 'instance_update_db')
        self.mox.StubOutWithMock(compute_rpcapi.ComputeAPI, 'run_instance')

        # instance 1
        self.driver._schedule(ctxt, 'compute', request_spec,
                              {}).AndReturn('host')
        self.driver.create_instance_db_entry(
            ctxt, mox.Func(_has_launch_index(0)), None
            ).WithSideEffects(_add_uuid(1)).AndReturn(instance1)
        driver.instance_update_db(ctxt, instance1['uuid'],
                'host').AndReturn(instance1)
        compute_rpcapi.ComputeAPI.run_instance(ctxt, host='host',
                instance=instance1, requested_networks=None,
                injected_files=None, admin_password=None, is_first_time=None,
                request_spec=request_spec, filter_properties={})
        driver.encode_instance(instance1).AndReturn(instance1)
        # instance 2
        self.driver._schedule(ctxt, 'compute', request_spec,
                              {}).AndReturn('host')
        self.driver.create_instance_db_entry(
            ctxt, mox.Func(_has_launch_index(1)), None
            ).WithSideEffects(_add_uuid(2)).AndReturn(instance2)
        driver.instance_update_db(ctxt, instance2['uuid'],
                'host').AndReturn(instance2)
        compute_rpcapi.ComputeAPI.run_instance(ctxt, host='host',
                instance=instance2, requested_networks=None,
                injected_files=None, admin_password=None, is_first_time=None,
                request_spec=request_spec, filter_properties={})
        driver.encode_instance(instance2).AndReturn(instance2)
        self.mox.ReplayAll()

        self.driver.schedule_run_instance(ctxt, request_spec, None, None,
                None, None, {}, None)