def test_coordination_configuration_parser(self): self.cfg_manager._set_value( CoordinationConfigurationParser.COORDINATOR_LABORATORY_SERVERS, { 'laboratory1:WL_SERVER1@WL_MACHINE1': { 'exp1|ud-fpga|FPGA experiments': 'fpga1@fpga boards', 'exp1|ud-pld|PLD experiments': 'pld1@pld boards', }, }) configuration = self.coordination_configuration_parser.parse_configuration( ) self.assertEquals(1, len(configuration)) lab_config = configuration['laboratory1:WL_SERVER1@WL_MACHINE1'] self.assertEquals(2, len(lab_config)) exp_fpga = ExperimentInstanceId("exp1", "ud-fpga", "FPGA experiments") exp_pld = ExperimentInstanceId("exp1", "ud-pld", "PLD experiments") fpga_resource = lab_config[exp_fpga] self.assertEquals(Resource("fpga boards", "fpga1"), fpga_resource) pld_resource = lab_config[exp_pld] self.assertEquals(Resource("pld boards", "pld1"), pld_resource)
def _fake_simple_lab_response(self): self.lab_mock.reserve_experiment( ExperimentInstanceId('inst', 'ud-dummy', 'Dummy experiments'), "{}", mocker.ANY) self.mocker.result((SessionId.SessionId('my_lab_session_id'), 'ok', { 'address': 'servexp:inst@mach' })) self.lab_mock.resolve_experiment_address('my_lab_session_id') self.mocker.result(CoordAddress("exp", "inst", "mach")) self.lab_mock.should_experiment_finish( SessionId.SessionId('my_lab_session_id')) self.mocker.result(0) self.mocker.replay()
def test_list_resources(self): session = self.session_maker() try: exp_id1 = ExperimentInstanceId("exp1", "ud-pld", "PLD Experiments") resource_instance1 = Resource("type1", "instance1") self.resources_manager.add_experiment_instance_id( "laboratory1:WL_SERVER1@WL_MACHINE1", exp_id1, resource_instance1) exp_id2 = ExperimentInstanceId("exp2", "ud-pld", "PLD Experiments") resource_instance2 = Resource("type2", "instance1") self.resources_manager.add_experiment_instance_id( "laboratory1:WL_SERVER1@WL_MACHINE1", exp_id2, resource_instance2) session.commit() finally: session.close() resources = self.resources_manager.list_resources() self.assertEquals(2, len(resources)) self.assertTrue('type1' in resources) self.assertTrue('type2' in resources)
def parse_configuration(self): # # configuration = { # "laboratory1:WL_SERVER1@WL_MACHINE1" : { # ExperimentInstanceId("exp1", "ud-pld", "PLD Experiments") : ("pld1", "ud-pld-boards") # } # } # configuration = {} laboratory_servers = self._cfg_manager.get_value( COORDINATOR_LABORATORY_SERVERS) for laboratory_server_coord_address_str in laboratory_servers: experiment_instances = laboratory_servers[ laboratory_server_coord_address_str] laboratory_configuration = {} configuration[ laboratory_server_coord_address_str] = laboratory_configuration for experiment_instance in experiment_instances: resource_instance = experiment_instances[experiment_instance] mo_experiment_instance = re.match( self.EXPERIMENT_INSTANCE_REGEX, experiment_instance) if mo_experiment_instance is None: raise coreExc.CoordinationConfigurationParsingError( "Error in coordination parsing: %s doesn't match the regular expression %s" % (experiment_instance, self.EXPERIMENT_INSTANCE_REGEX)) mo_resource_instance = re.match(self.RESOURCE_INSTANCE_REGEX, resource_instance) if mo_resource_instance is None: raise coreExc.CoordinationConfigurationParsingError( "Error in coordination parsing: %s doesn't match the regular expression %s" % (resource_instance, self.RESOURCE_INSTANCE_REGEX)) (inst_name, exp_name, exp_cat_name) = mo_experiment_instance.groups() experiment_instance_id = ExperimentInstanceId( inst_name, exp_name, exp_cat_name) (resource_instance, resource_type) = mo_resource_instance.groups() resource = Resource(resource_type, resource_instance) laboratory_configuration[experiment_instance_id] = resource return configuration
def _parse_assigned_experiments(self): assigned_experiments = self._cfg_manager.get_value( WEBLAB_LABORATORY_SERVER_ASSIGNED_EXPERIMENTS) parsed_experiments = [] for experiment_instance_id, data in assigned_experiments.items(): mo = re.match(self.EXPERIMENT_INSTANCE_ID_REGEX, experiment_instance_id) if mo == None: raise LaboratoryErrors.InvalidLaboratoryConfigurationError( "Invalid configuration entry. Expected format: %s; found: %s" % (LaboratoryServer.EXPERIMENT_INSTANCE_ID_REGEX, experiment_instance_id)) else: # ExperimentInstanceId groups = mo.groups() (exp_inst_name, exp_name, exp_cat_name) = groups experiment_instance_id = ExperimentInstanceId( exp_inst_name, exp_name, exp_cat_name) # CoordAddress try: coord_address = CoordAddress.CoordAddress.translate_address( data['coord_address']) except GeneratorErrors.GeneratorError: raise LaboratoryErrors.InvalidLaboratoryConfigurationError( "Invalid coordination address: %s" % data['coord_address']) # CheckingHandlers checkers = data.get('checkers', ()) checking_handlers = [] for checker in checkers: klazz = checker[0] if klazz in IsUpAndRunningHandler.HANDLERS: argss, kargss = (), {} if len(checker) >= 3: kargss = checker[2] if len(checker) >= 2: argss = checker[1] checking_handlers.append( eval('IsUpAndRunningHandler.' + klazz)(*argss, **kargss)) else: raise LaboratoryErrors.InvalidLaboratoryConfigurationError( "Invalid IsUpAndRunningHandler: %s" % klazz) parsed_experiments.append( (experiment_instance_id, coord_address, checking_handlers)) return parsed_experiments
def test_get_resource_instance_by_experiment_instance_id_failing(self): session = self.session_maker() try: exp_id = ExperimentInstanceId("exp1", "ud-pld", "PLD Experiments") self.resources_manager.add_experiment_instance_id( "laboratory1:WL_SERVER1@WL_MACHINE1", exp_id, Resource("type", "instance")) session.commit() finally: session.close() exp_invalid_type = ExperimentInstanceId("exp1", "ud-pld.invalid", "PLD Experiments") self.assertRaises( CoordExc.ExperimentNotFoundError, self.resources_manager. get_resource_instance_by_experiment_instance_id, exp_invalid_type) exp_invalid_inst = ExperimentInstanceId("exp.invalid", "ud-pld", "PLD Experiments") self.assertRaises( CoordExc.ExperimentNotFoundError, self.resources_manager. get_resource_instance_by_experiment_instance_id, exp_invalid_inst)
def setUp(self): self.cfg_manager = ConfigurationManager.ConfigurationManager() self.cfg_manager.append_module(configuration_module) self.fake_client = FakeClient() self.fake_locator = FakeLocator((self.fake_client, )) self.locator = EasyLocator.EasyLocator( CoordAddress.CoordAddress('mach', 'inst', 'serv'), self.fake_locator) self.experiment_instance_id = ExperimentInstanceId( "exp_inst", "exp_name", "exp_cat") self.experiment_instance_id_old = ExperimentInstanceId( "exp_inst", "exp_name", "exp_cat2") self.experiment_coord_address = CoordAddress.CoordAddress.translate_address( 'myserver:myinstance@mymachine') self.cfg_manager._set_value( 'laboratory_assigned_experiments', { 'exp_inst:exp_name@exp_cat': { 'coord_address': 'myserver:myinstance@mymachine', 'checkers': ( ('WebcamIsUpAndRunningHandler', ("https://...", )), ('HostIsUpAndRunningHandler', ("hostname", 80), {}), ) }, 'exp_inst:exp_name@exp_cat2': { 'coord_address': 'myserver:myinstance@mymachine', 'checkers': ( ('WebcamIsUpAndRunningHandler', ("https://...", )), ('HostIsUpAndRunningHandler', ("hostname", 80), {}), ), }, }) self._create_lab()
def test_get_resource_instance_by_experiment_instance_id(self): session = self.session_maker() try: exp_id = ExperimentInstanceId("exp1", "ud-pld", "PLD Experiments") self.resources_manager.add_experiment_instance_id( "laboratory1:WL_SERVER1@WL_MACHINE1", exp_id, Resource("type", "instance")) session.commit() finally: session.close() resource = self.resources_manager.get_resource_instance_by_experiment_instance_id( exp_id) expected_resource = Resource("type", "instance") self.assertEquals(expected_resource, resource)
def test_remove_resource_instance_id(self): exp_id = ExperimentInstanceId("exp1", "ud-pld", "PLD Experiments") self.resources_manager.add_experiment_instance_id( "laboratory1:WL_SERVER1@WL_MACHINE1", exp_id, Resource("type", "instance")) experiment_instances = self.resources_manager.list_experiment_instances_by_type( exp_id.to_experiment_id()) self.assertEquals(1, len(experiment_instances)) self.resources_manager.remove_resource_instance_id(exp_id) experiment_instances = self.resources_manager.list_experiment_instances_by_type( exp_id.to_experiment_id()) self.assertEquals(0, len(experiment_instances))
def test_confirm_experiment(self): lab_session_id = SessionId.SessionId("samplesession_id") mock_laboratory = self.mocker.mock() mock_laboratory.reserve_experiment( ExperimentInstanceId('inst1', 'exp1', 'cat1'), '"sample initial data"', mocker.ANY) self.mocker.result((lab_session_id, None, { 'address': 'server:inst@mach' })) self.mock_locator[coord_addr(self.lab_address)] self.mocker.result(mock_laboratory) self.mocker.count(min=1, max=None) self.mocker.replay() status, reservation1_id = self.coordinator.reserve_experiment( ExperimentId('exp1', 'cat1'), 30, 5, True, 'sample initial data', DEFAULT_REQUEST_INFO, {}) now = datetime.datetime.fromtimestamp(int( time.time())) # Remove milliseconds as MySQL do self.coordinator.confirmer._confirm_handler.join() self.assertEquals(None, self.confirmer._confirm_handler.raised_exc) status = self.coordinator.get_reservation_status(reservation1_id) expected_status = WSS.LocalReservedStatus( reservation1_id, CoordAddress.translate(self.lab_address), lab_session_id, {'address': 'server:inst@mach'}, 30, '{}', now, now, True, 30, 'http://www.weblab.deusto.es/weblab/client/adfas') self.assertTrue( hasattr(status, 'timestamp_before'), "Unexpected status. Expected\n %s\n, but the obtained does not have timestamp_before:\n %s\n" % (expected_status, status)) self.assertTrue( status.timestamp_before >= now and status.timestamp_before <= now + datetime.timedelta(seconds=10), "Unexpected status due to timestamp_before: %s; expected something like %s" % (status, expected_status)) self.assertTrue( status.timestamp_after >= now and status.timestamp_after <= now + datetime.timedelta(seconds=10), "Unexpected status due to timestamp_after: %s; expected something like %s" % (status, expected_status)) status.timestamp_before = now status.timestamp_after = now self.assertEquals(expected_status, status)
def test_add_experiment_instance_id_redundant(self): session = self.session_maker() try: resource_types = session.query(CoordinatorModel.ResourceType).all() self.assertEquals( 0, len(resource_types), "No resource expected in the beginning of the test") finally: session.close() exp_id = ExperimentInstanceId("exp1", "ud-pld", "PLD Experiments") self.resources_manager.add_experiment_instance_id( "laboratory1:WL_SERVER1@WL_MACHINE1", exp_id, Resource("type", "instance")) # No problem in adding twice the same self.resources_manager.add_experiment_instance_id( "laboratory1:WL_SERVER1@WL_MACHINE1", exp_id, Resource("type", "instance")) session = self.session_maker() try: # Everything is all right self._check_resource_added(session) self._check_experiment_instance_id_added(session) # However, we can't add another time the same experiment instance with a different laboratory id: self.assertRaises( CoordExc.InvalidExperimentConfigError, self.resources_manager.add_experiment_instance_id, "laboratory2:WL_SERVER1@WL_MACHINE1", exp_id, Resource("type", "instance")) # Or the same experiment instance with a different resource instance: self.assertRaises( CoordExc.InvalidExperimentConfigError, self.resources_manager.add_experiment_instance_id, "laboratory1:WL_SERVER1@WL_MACHINE1", exp_id, Resource("type", "instance2")) session.commit() finally: session.close()
def test_reject_experiment_laboratory_raises_exception(self): mock_laboratory = self.mocker.mock() mock_laboratory.reserve_experiment( ExperimentInstanceId('inst1', 'exp1', 'cat1'), '"sample initial data"', mocker.ANY) self.mocker.throw(Exception("Any unhandled exception")) self.mock_locator[coord_addr(self.lab_address)] self.mocker.result(mock_laboratory) self.mocker.replay() status, reservation1_id = self.coordinator.reserve_experiment( ExperimentId('exp1', 'cat1'), 30, 5, True, 'sample initial data', DEFAULT_REQUEST_INFO, {}) self.coordinator.confirmer._confirm_handler.join() self.assertEquals(None, self.confirmer._confirm_handler.raised_exc) status = self.coordinator.get_reservation_status(reservation1_id) expected_status = WSS.WaitingInstancesQueueStatus(reservation1_id, 0) self.assertEquals(expected_status, status)
def setUp(self): self.coord_address = CoordAddress.CoordAddress.translate_address( "server0:instance0@machine0") self.mock_locator = MockLocator() self.locator = EasyLocator.EasyLocator( self.coord_address, self.mock_locator ) self.cfg_manager = ConfigurationManager.ConfigurationManager() self.cfg_manager.append_module(configuration_module) self.cfg_manager._set_value(COORDINATOR_LABORATORY_SERVERS, { u'lab1:inst@machine' : { 'inst1|exp1|cat1' : 'res_inst@res_type' }, }) self.coordinator = coordinator_create(SQLALCHEMY, self.locator, self.cfg_manager) self.coordinator._clean() self.confirmer = self.coordinator.confirmer self.lab_address = u"lab1:inst@machine" self.coordinator.add_experiment_instance_id(self.lab_address, ExperimentInstanceId('inst1', 'exp1','cat1'), Resource("res_type", "res_inst"))
def test_remove_resource_instance_id(self): session = self.session_maker() try: exp_id = ExperimentInstanceId("exp1", "ud-pld", "PLD Experiments") self.resources_manager.add_experiment_instance_id( "laboratory1:WL_SERVER1@WL_MACHINE1", exp_id, Resource("type", "instance")) experiment_instances = session.query( CoordinatorModel.ExperimentInstance).all() self.assertEquals(1, len(experiment_instances)) self.resources_manager.remove_resource_instance_id(session, exp_id) experiment_instances = session.query( CoordinatorModel.ExperimentInstance).all() self.assertEquals(0, len(experiment_instances)) session.commit() finally: session.close()
def test_remove_resource_instance(self): exp_id = ExperimentInstanceId("exp1", "ud-pld", "PLD Experiments") resource_instance = Resource("type", "instance") self.resources_manager.add_experiment_instance_id( "laboratory1:WL_SERVER1@WL_MACHINE1", exp_id, resource_instance) # Checking that the resources are there experiment_instances = self.resources_manager.list_experiment_instances_by_type( exp_id.to_experiment_id()) self.assertEquals(1, len(experiment_instances)) resource_instances = self.resources_manager.list_resource_instances() self.assertEquals(1, len(resource_instances)) # Removing resource instance self.resources_manager.remove_resource_instance(resource_instance) # Checking that the resources are not there, neither the experiment instances resource_instances = self.resources_manager.list_resource_instances() self.assertEquals(0, len(resource_instances)) experiment_instances = self.resources_manager.list_experiment_instances_by_type( exp_id.to_experiment_id()) self.assertEquals(0, len(experiment_instances))
def test_add_experiment_instance_id(self): session = self.session_maker() try: resource_types = session.query(CoordinatorModel.ResourceType).all() self.assertEquals( 0, len(resource_types), "No resource expected in the beginning of the test") exp_id = ExperimentInstanceId("exp1", "ud-pld", "PLD Experiments") session.commit() finally: session.close() self.resources_manager.add_experiment_instance_id( "laboratory1:WL_SERVER1@WL_MACHINE1", exp_id, Resource("type", "instance")) session = self.session_maker() try: self._check_resource_added(session) self._check_experiment_instance_id_added(session) session.commit() finally: session.close()
def list_laboratories_addresses(self): client = self._redis_maker() laboratory_addresses = { # laboratory_coord_address : { # experiment_instance_id : resource_instance # } } for experiment_type in client.smembers(WEBLAB_EXPERIMENT_TYPES): experiment_id = ExperimentId.parse(experiment_type) experiment_instance_names = client.smembers(WEBLAB_EXPERIMENT_INSTANCES % experiment_type) for experiment_instance_name in experiment_instance_names: experiment_instance_id = ExperimentInstanceId(experiment_instance_name, experiment_id.exp_name, experiment_id.cat_name) weblab_experiment_instance = WEBLAB_EXPERIMENT_INSTANCE % (experiment_type, experiment_instance_name) laboratory_address = client.hget(weblab_experiment_instance, LAB_COORD) resource_str = client.hget(weblab_experiment_instance, RESOURCE_INST) resource = Resource.parse(resource_str) current = laboratory_addresses.get(laboratory_address, {}) current[experiment_instance_id] = resource laboratory_addresses[laboratory_address] = current return laboratory_addresses
def to_experiment_instance_id(self): exp_id = self.experiment_type.to_experiment_id() return ExperimentInstanceId(self.experiment_instance_id, exp_id.exp_name, exp_id.cat_name)
def test_free_experiment_raises_exception(self): self.mock_locator.real_mock = self.mocker.mock() self.mock_locator.real_mock.get_server_from_coordaddress( self.coord_address, coord_addr(self.lab_address), ServerType.Laboratory, 'all' ) self.mocker.throw( Exception('foo') ) self.mocker.replay() self.confirmer.enqueue_free_experiment(self.lab_address, '5', 'lab_session_id', ExperimentInstanceId('inst1','exp1','cat1')) self.confirmer._free_handler.join() self.assertEquals( None, self.confirmer._free_handler.raised_exc )
def setUp(self): self.experiment_id = ExperimentId('exp', 'cat') self.experiment_instance_id = ExperimentInstanceId( 'inst', 'exp', 'cat')
def test_scheduler_reservation_associations(self): exp_inst_id1 = ExperimentInstanceId("exp1", "ud-pld", "PLD experiments") exp_inst_id1b = ExperimentInstanceId("exp2", "ud-pld", "PLD experiments") exp_inst_id2 = ExperimentInstanceId("exp1", "ud-fpga", "FPGA experiments") exp_id1 = exp_inst_id1.to_experiment_id() exp_id2 = exp_inst_id2.to_experiment_id() session = self.session_maker() try: self.resources_manager.add_resource( session, Resource("pld_local", "instance")) self.resources_manager.add_resource( session, Resource("pld_remote", "instance")) self.resources_manager.add_resource( session, Resource("fpga_remote", "instance")) session.commit() finally: session.close() self.resources_manager.add_experiment_instance_id( "laboratory1:WL_SERVER1@WL_MACHINE1", exp_inst_id1, Resource("pld_local", "instance")) self.resources_manager.add_experiment_instance_id( "laboratory1:WL_SERVER1@WL_MACHINE1", exp_inst_id1b, Resource("pld_remote", "instance")) self.resources_manager.add_experiment_instance_id( "laboratory1:WL_SERVER1@WL_MACHINE1", exp_inst_id2, Resource("fpga_remote", "instance")) reservation1 = 'reservation1' reservation2 = 'reservation2' self.resources_manager.associate_scheduler_to_reservation( reservation1, exp_id1, 'pld_local') self.resources_manager.associate_scheduler_to_reservation( reservation1, exp_id1, 'pld_remote') self.resources_manager.associate_scheduler_to_reservation( reservation2, exp_id2, 'fpga_remote') resource_type_names = self.resources_manager.retrieve_schedulers_per_reservation( reservation1, exp_id1) self.assertEquals(set(('pld_local', 'pld_remote')), set(resource_type_names)) resource_type_names = self.resources_manager.retrieve_schedulers_per_reservation( reservation2, exp_id2) self.assertEquals(['fpga_remote'], list(resource_type_names)) self.resources_manager.dissociate_scheduler_from_reservation( reservation1, exp_id1, 'pld_remote') resource_type_names = self.resources_manager.retrieve_schedulers_per_reservation( reservation1, exp_id1) self.assertEquals(['pld_local'], list(resource_type_names)) self.resources_manager.clean_associations_for_reservation( reservation1, exp_id1) resource_type_names = self.resources_manager.retrieve_schedulers_per_reservation( reservation1, exp_id1) self.assertEquals(0, len(resource_type_names))
def setUp(self): self._assigned_micro_servers = AssignedExperiments.AssignedExperiments( ) self.exp_inst_id = ExperimentInstanceId("exp_inst", "exp_name", "exp_cat")
def list_experiment_instances_by_type(self, experiment_id): client = self._redis_maker() weblab_experiment_instances = WEBLAB_EXPERIMENT_INSTANCES % experiment_id.to_weblab_str() return [ ExperimentInstanceId(inst, experiment_id.exp_name, experiment_id.cat_name) for inst in client.smembers(weblab_experiment_instances) ]
def test_list_experiments(self): self.coordinator.add_experiment_instance_id("server:laboratoryserver@labmachine", ExperimentInstanceId('inst','ud-dummy2','Dummy experiments'), Resource("res_type", "res_inst")) expected = "ud-dummy@Dummy experiments\n" expected += "ud-dummy2@Dummy experiments\n" result = methods.list_experiments.call() self.assertEquals(expected, result)
def setUp(self): self.maxDiff = 2000 def _find_server(server_type, name): return self.ups self._find_server_backup = methods._find_server methods._find_server = _find_server self.locator = FakeLocator() self.cfg_manager = ConfigurationManager.ConfigurationManager() self.cfg_manager.append_module(configuration_module) self.cfg_manager._set_value(COORDINATOR_LABORATORY_SERVERS, { 'server:laboratoryserver@labmachine' : { 'inst|ud-dummy|Dummy experiments' : 'res_inst@res_type' } }) # With this one we clean everything before creating the UPS self.coordinator = coordinator_create(SQLALCHEMY, self.locator, self.cfg_manager, ConfirmerClass = ConfirmerMock) self.coordinator._clean() self.coord_address = CoordAddress.CoordAddress.translate_address( "server0:instance0@machine0" ) self.ups = UserProcessingServer.UserProcessingServer( self.coord_address, self.locator, self.cfg_manager ) self.ups._coordinator.stop() self.ups._coordinator = self.coordinator self.coordinator.add_experiment_instance_id("server:laboratoryserver@labmachine", ExperimentInstanceId('inst','ud-dummy','Dummy experiments'), Resource("res_type", "res_inst"))
def _parse_assigned_experiments(self): """ Parses the configuration that was provided to the server and loads every Experiment that is declared in it. This task is executed at the beginning. :return: List of tuples, each tuple containing information for an Experiment """ assigned_experiments = self._cfg_manager.get_value( WEBLAB_LABORATORY_SERVER_ASSIGNED_EXPERIMENTS) parsed_experiments = [] for experiment_instance_id, data in assigned_experiments.items(): mo = re.match(self.EXPERIMENT_INSTANCE_ID_REGEX, experiment_instance_id) if mo == None: raise LaboratoryErrors.InvalidLaboratoryConfigurationError( "Invalid configuration entry. Expected format: %s; found: %s" % (LaboratoryServer.EXPERIMENT_INSTANCE_ID_REGEX, experiment_instance_id)) else: number = data.get('number', 1) for n in range(1, number + 1): # ExperimentInstanceId groups = mo.groups() (exp_inst_name, exp_name, exp_cat_name) = groups if number > 1: exp_inst_name += '__%s' % n experiment_instance_id = ExperimentInstanceId( exp_inst_name, exp_name, exp_cat_name) # CoordAddress try: coord_address = CoordAddress.translate( data['coord_address']) except GeneratorError: raise LaboratoryErrors.InvalidLaboratoryConfigurationError( "Invalid coordination address: %s" % data['coord_address']) # CheckingHandlers checkers = data.get('checkers', ()) checking_handlers = {} for checker in checkers: klazz = checker[0] if klazz in IsUpAndRunningHandler.HANDLERS: argss, kargss = (), {} if len(checker) >= 3: kargss = checker[2] if len(checker) >= 2: argss = checker[1] checking_handlers[repr(checker)] = eval( 'IsUpAndRunningHandler.' + klazz)(*argss, **kargss) else: raise LaboratoryErrors.InvalidLaboratoryConfigurationError( "Invalid IsUpAndRunningHandler: %s" % klazz) # API api = data.get('api', None) # Polling: if it manages its own polling, the client does not need to manage it manages_polling = data.get('manages_polling', False) parsed_experiments.append( (experiment_instance_id, coord_address, { 'checkers': checking_handlers, 'api': api, 'manages_polling': manages_polling, 'number': number })) return parsed_experiments
def test_free_experiment_success(self): mock_laboratory = self.mocker.mock() mock_laboratory.free_experiment('lab_session_id') self.mock_locator.real_mock = self.mocker.mock() self.mock_locator.real_mock.get_server_from_coordaddress( self.coord_address, coord_addr(self.lab_address), ServerType.Laboratory, 'all' ) self.mocker.result((mock_laboratory,)) self.mocker.replay() self.confirmer.enqueue_free_experiment(self.lab_address, '5', 'lab_session_id', ExperimentInstanceId('inst1','exp1','cat1')) self.confirmer._free_handler.join()
def _update_queues(self): ########################################################### # There are reasons why a waiting reservation may not be # able to be promoted while the next one is. For instance, # if a user is waiting for "pld boards", but only for # instances of "pld boards" which have a "ud-binary@Binary # experiments" server running. If only a "ud-pld@PLD # Experiments" is available, then this user will not be # promoted and the another user which is waiting for a # "ud-pld@PLD Experiments" can be promoted. # # Therefore, we have a list of the IDs of the waiting # reservations we previously thought that they couldn't be # promoted in this iteration. They will have another # chance in the next run of _update_queues. # previously_waiting_reservation_ids = [] ########################################################### # While there are free instances and waiting reservations, # take the first waiting reservation and set it to current # reservation. Make this repeatedly because we want to # commit each change # while True: session = self.session_maker() try: resource_type = session.query(ResourceType).filter(ResourceType.name == self.resource_type_name).first() # # Retrieve the first waiting reservation. If there is no one that # we haven't tried already, return # first_waiting_reservations = session.query(WaitingReservation).filter(WaitingReservation.resource_type == resource_type).order_by(WaitingReservation.priority, WaitingReservation.id)[:len(previously_waiting_reservation_ids) + 1] first_waiting_reservation = None for waiting_reservation in first_waiting_reservations: if waiting_reservation.id not in previously_waiting_reservation_ids: first_waiting_reservation = waiting_reservation break if first_waiting_reservation is None: return # There is no waiting reservation for this resource that we haven't already tried previously_waiting_reservation_ids.append(first_waiting_reservation.id) # # For the current resource_type, let's ask for # all the resource instances available (i.e. those # who have no SchedulingSchemaIndependentSlotReservation # associated) # free_instances = session.query(CurrentResourceSlot)\ .select_from(join(CurrentResourceSlot, ResourceInstance))\ .filter(not_(CurrentResourceSlot.slot_reservations.any()))\ .filter(ResourceInstance.resource_type == resource_type)\ .order_by(CurrentResourceSlot.id).all() if len(free_instances) == 0: # If there is no free instance, just return return # # Select the correct free_instance for the current student among # all the free_instances # if self.randomize_instances: randomized_free_instances = [ free_instance for free_instance in free_instances ] random.shuffle(randomized_free_instances) else: randomized_free_instances = free_instances for free_instance in randomized_free_instances: resource_type = free_instance.resource_instance.resource_type if resource_type is None: continue # If suddenly the free_instance is not a free_instance anymore, try with other free_instance # # IMPORTANT: from here on every "continue" should first revoke the # reservations_manager and resources_manager confirmations # self.reservations_manager.confirm(session, first_waiting_reservation.reservation_id) slot_reservation = self.resources_manager.acquire_resource(session, free_instance) total_time = first_waiting_reservation.time initialization_in_accounting = first_waiting_reservation.initialization_in_accounting start_time = self.time_provider.get_time() concrete_current_reservation = ConcreteCurrentReservation(slot_reservation, first_waiting_reservation.reservation_id, total_time, start_time, first_waiting_reservation.priority, first_waiting_reservation.initialization_in_accounting) concrete_current_reservation.set_timestamp_before(self.time_provider.get_time()) client_initial_data = first_waiting_reservation.reservation.client_initial_data request_info = json.loads(first_waiting_reservation.reservation.request_info) username = request_info.get('username') username_unique = request_info.get('username_unique') locale = request_info.get('locale') reservation_id = first_waiting_reservation.reservation_id if reservation_id is None: break # If suddenly the waiting_reservation is not a waiting_reservation anymore, so reservation is None, go again to the while True. requested_experiment_type = first_waiting_reservation.reservation.experiment_type selected_experiment_instance = None for experiment_instance in free_instance.resource_instance.experiment_instances: if experiment_instance.experiment_type == requested_experiment_type: selected_experiment_instance = experiment_instance if selected_experiment_instance is None: # This resource is not valid for this user, other free_instance should be # selected. Try with other, but first clean the acquired resources self.reservations_manager.downgrade_confirmation(session, first_waiting_reservation.reservation_id) self.resources_manager.release_resource(session, slot_reservation) continue experiment_instance_id = ExperimentInstanceId(selected_experiment_instance.experiment_instance_id, requested_experiment_type.exp_name, requested_experiment_type.cat_name) laboratory_coord_address = selected_experiment_instance.laboratory_coord_address try: session.delete(first_waiting_reservation) session.add(concrete_current_reservation) session.commit() except IntegrityError as ie: if DEBUG: print("IntegrityError when adding concrete_current_reservation: ", sys.exc_info()) # Other scheduler confirmed the user or booked the reservation, rollback and try again # But log just in case log.log( PriorityQueueScheduler, log.level.Warning, "IntegrityError looping on update_queues: %s" % ie ) log.log_exc(PriorityQueueScheduler, log.level.Info) session.rollback() break except Exception as e: if DEBUG: print("Other error when adding concrete_current_reservation: ", sys.exc_info()) log.log( PriorityQueueScheduler, log.level.Warning, "Exception looping on update_queues: %s" % e ) log.log_exc(PriorityQueueScheduler, log.level.Info) session.rollback() break else: # # Enqueue the confirmation, since it might take a long time # (for instance, if the laboratory server does not reply because # of any network problem, or it just takes too much in replying), # so this method might take too long. That's why we enqueue these # petitions and run them in other threads. # timezone = time.timezone if (time.localtime().tm_isdst == 0) else time.altzone deserialized_server_initial_data = { 'priority.queue.slot.length' : '%s' % total_time, 'priority.queue.slot.start' : '%s' % datetime.datetime.fromtimestamp(start_time), 'priority.queue.slot.start.utc' : '%s' % datetime.datetime.utcfromtimestamp(start_time), 'priority.queue.slot.start.timestamp' : '%s' % start_time, 'priority.queue.slot.start.timezone' : '%s' % timezone, 'priority.queue.slot.initialization_in_accounting' : initialization_in_accounting, 'request.experiment_id.experiment_name' : experiment_instance_id.exp_name, 'request.experiment_id.category_name' : experiment_instance_id.cat_name, 'request.username' : username, 'request.username.unique' : username_unique, 'request.full_name' : username, 'request.locale' : locale, 'weblab_reservation_id' : first_waiting_reservation.reservation_id, } server_initial_data = json.dumps(deserialized_server_initial_data) # server_initial_data will contain information such as "what was the last experiment used?". # If a single resource was used by a binary experiment, then the next time may not require reprogramming the device self.confirmer.enqueue_confirmation(laboratory_coord_address, reservation_id, experiment_instance_id, client_initial_data, server_initial_data, self.resource_type_name) # # After it, keep in the while True in order to add the next # reservation # break except (ConcurrentModificationError, IntegrityError) as ie: # Something happened somewhere else, such as the user being confirmed twice, the experiment being reserved twice or so on. # Rollback and start again if DEBUG: print("Other ConcurrentModificationError or IntegrityError in update_queues: ", sys.exc_info()) log.log( PriorityQueueScheduler, log.level.Warning, "Exception while updating queues, reverting and trying again: %s" % ie ) log.log_exc(PriorityQueueScheduler, log.level.Info) session.rollback() finally: session.close()
def get_experiment_instance_id(self): return ExperimentInstanceId(None, self.name, self.category.name)