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)
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)
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)
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)
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
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
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)
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
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
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
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)
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)
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)
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)
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
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)
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 _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 _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 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
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
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
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
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
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
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
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
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
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
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)
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)
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)
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)