示例#1
0
def schedule_queued_recipes(*args):
    session.begin()
    try:
        # This query returns a queued host recipe and and the guest which has
        # the most recent distro tree. It is to be used as a derived table.
        latest_guest_distro = select([machine_guest_map.c.machine_recipe_id.label('host_id'),
            func.max(DistroTree.date_created).label('latest_distro_date')],
            from_obj=[machine_guest_map.join(GuestRecipe.__table__,
                    machine_guest_map.c.guest_recipe_id==GuestRecipe.__table__.c.id). \
                join(Recipe.__table__).join(DistroTree.__table__)],
            whereclause=Recipe.status=='Queued',
            group_by=machine_guest_map.c.machine_recipe_id).alias()

        hosts_lab_controller_distro_map = aliased(LabControllerDistroTree)
        hosts_distro_tree = aliased(DistroTree)
        guest_recipe = aliased(Recipe)
        guests_distro_tree = aliased(DistroTree)
        guests_lab_controller = aliased(LabController)

        # This query will return queued recipes that are eligible to be scheduled.
        # They are determined to be eligible if:
        # * They are clean
        # * There are systems available (see the filter criteria) in lab controllers where
        #   the recipe's distro tree is available.
        # * If it is a host recipe, the most recently created distro of all
        #   the guest recipe's distros is available in at least one of the same
        #   lab controllers as that of the host's distro tree.
        #
        # Also note that we do not try to handle the situation where the guest and host never
        # have a common labcontroller. In that situation the host and guest would stay queued
        # until that situation was rectified.
        recipes = MachineRecipe.query\
            .join(Recipe.recipeset, RecipeSet.job)\
            .filter(Job.dirty_version == Job.clean_version)\
            .outerjoin((guest_recipe, MachineRecipe.guests))\
            .outerjoin((guests_distro_tree, guest_recipe.distro_tree_id == guests_distro_tree.id))\
            .outerjoin((latest_guest_distro,
                and_(latest_guest_distro.c.host_id == MachineRecipe.id,
                    latest_guest_distro.c.latest_distro_date == \
                    guests_distro_tree.date_created)))\
            .outerjoin(guests_distro_tree.lab_controller_assocs, guests_lab_controller)\
            .join(Recipe.systems)\
            .join((hosts_distro_tree, hosts_distro_tree.id == MachineRecipe.distro_tree_id))\
            .join((hosts_lab_controller_distro_map, hosts_distro_tree.lab_controller_assocs),
                (LabController, and_(
                    hosts_lab_controller_distro_map.lab_controller_id == LabController.id,
                    System.lab_controller_id == LabController.id)))\
            .filter(
                and_(Recipe.status == TaskStatus.queued,
                    System.user == None,
                    LabController.disabled == False,
                    or_(
                        RecipeSet.lab_controller == None,
                        RecipeSet.lab_controller_id == System.lab_controller_id,
                       ),
                    or_(
                        System.loan_id == None,
                        System.loan_id == Job.owner_id,
                       ),
                    or_(
                        # We either have no guest
                        guest_recipe.id == None,
                        # Or we have a guest of which the latest
                        # is in a common lab controller.
                        and_(guests_lab_controller.id == LabController.id,
                            latest_guest_distro.c.latest_distro_date != None
                            ),
                        ) # or
                    ) # and
                  )
        # Get out of here if we have no recipes
        if not recipes.count():
            return False
        # This should be the guest recipe with the latest distro.
        # We return it in this query, to save us from re-running the
        # derived table query in schedule_queued_recipe()
        recipes = recipes.add_column(guest_recipe.id)
        # Effective priority is given in the following order:
        # * Multi host recipes with already scheduled siblings
        # * Priority level (i.e Normal, High etc)
        # * RecipeSet id
        # * Recipe id
        recipes = recipes.order_by(RecipeSet.lab_controller == None). \
            order_by(RecipeSet.priority.desc()). \
            order_by(RecipeSet.id). \
            order_by(MachineRecipe.id)
        # Don't do a GROUP BY before here, it is not needed.
        recipes = recipes.group_by(MachineRecipe.id)
        log.debug("Entering schedule_queued_recipes")
        for recipe_id, guest_recipe_id in recipes.values(MachineRecipe.id, guest_recipe.id):
            session.begin(nested=True)
            try:
                schedule_queued_recipe(recipe_id, guest_recipe_id)
                session.commit()
            except (StaleSystemUserException, InsufficientSystemPermissions,
                 StaleTaskStatusException), e:
                # Either
                # System user has changed before
                # system allocation
                # or
                # System permissions have changed before
                # system allocation
                # or
                # Something has moved our status on from queued
                # already.
                log.warn(str(e))
                session.rollback()
            except Exception, e:
                log.exception('Error in schedule_queued_recipe(%s)', recipe_id)
                session.rollback()
                session.begin(nested=True)
                try:
                    recipe=MachineRecipe.by_id(recipe_id)
                    recipe.recipeset.abort(u"Aborted in schedule_queued_recipe: %s" % e)
                    session.commit()
                except Exception, e:
                    log.exception("Error during error handling in schedule_queued_recipe: %s" % e)
                    session.rollback()
示例#2
0
def schedule_queued_recipes(*args):
    work_done = False
    session.begin()
    try:
        # This query returns a queued host recipe and and the guest which has
        # the most recent distro tree. It is to be used as a derived table.
        latest_guest_distro = select([machine_guest_map.c.machine_recipe_id.label('host_id'),
            func.max(DistroTree.date_created).label('latest_distro_date')],
            from_obj=[machine_guest_map.join(GuestRecipe.__table__,
                    machine_guest_map.c.guest_recipe_id==GuestRecipe.__table__.c.id). \
                join(Recipe.__table__).join(DistroTree.__table__)],
            whereclause=Recipe.status=='Queued',
            group_by=machine_guest_map.c.machine_recipe_id).alias()

        hosts_lab_controller_distro_map = aliased(LabControllerDistroTree)
        hosts_distro_tree = aliased(DistroTree)
        guest_recipe = aliased(Recipe)
        guests_distro_tree = aliased(DistroTree)
        guests_lab_controller = aliased(LabController)

        # This query will return queued recipes that are eligible to be scheduled.
        # They are determined to be eligible if:
        # * They are clean
        # * There are systems available (see the filter criteria) in lab controllers where
        #   the recipe's distro tree is available.
        # * If it is a host recipe, the most recently created distro of all
        #   the guest recipe's distros is available in at least one of the same
        #   lab controllers as that of the host's distro tree.
        #
        # Also note that we do not try to handle the situation where the guest and host never
        # have a common labcontroller. In that situation the host and guest would stay queued
        # until that situation was rectified.
        recipes = MachineRecipe.query\
            .join(Recipe.recipeset, RecipeSet.job)\
            .filter(Job.dirty_version == Job.clean_version)\
            .outerjoin((guest_recipe, MachineRecipe.guests))\
            .outerjoin((guests_distro_tree, guest_recipe.distro_tree_id == guests_distro_tree.id))\
            .outerjoin((latest_guest_distro,
                and_(latest_guest_distro.c.host_id == MachineRecipe.id,
                    latest_guest_distro.c.latest_distro_date == \
                    guests_distro_tree.date_created)))\
            .outerjoin(guests_distro_tree.lab_controller_assocs, guests_lab_controller)\
            .join(Recipe.systems)\
            .join((hosts_distro_tree, hosts_distro_tree.id == MachineRecipe.distro_tree_id))\
            .join((hosts_lab_controller_distro_map, hosts_distro_tree.lab_controller_assocs),
                (LabController, and_(
                    hosts_lab_controller_distro_map.lab_controller_id == LabController.id,
                    System.lab_controller_id == LabController.id)))\
            .filter(
                and_(Recipe.status == TaskStatus.queued,
                    System.user == None,
                    LabController.disabled == False,
                    or_(
                        RecipeSet.lab_controller == None,
                        RecipeSet.lab_controller_id == System.lab_controller_id,
                       ),
                    or_(
                        System.loan_id == None,
                        System.loan_id == Job.owner_id,
                       ),
                    or_(
                        # We either have no guest
                        guest_recipe.id == None,
                        # Or we have a guest of which the latest
                        # is in a common lab controller.
                        and_(guests_lab_controller.id == LabController.id,
                            latest_guest_distro.c.latest_distro_date != None
                            ),
                        ) # or
                    ) # and
                  )
        # This should be the guest recipe with the latest distro.
        # We return it in this query, to save us from re-running the
        # derived table query in schedule_queued_recipe()
        recipes = recipes.add_column(guest_recipe.id)
        # Effective priority is given in the following order:
        # * Multi host recipes with already scheduled siblings
        # * Priority level (i.e Normal, High etc)
        # * RecipeSet id
        # * Recipe id
        recipes = recipes.order_by(RecipeSet.lab_controller == None). \
            order_by(RecipeSet.priority.desc()). \
            order_by(RecipeSet.id). \
            order_by(MachineRecipe.id)
        # Don't do a GROUP BY before here, it is not needed.
        recipes = recipes.group_by(MachineRecipe.id)
        for recipe_id, guest_recipe_id in recipes.values(
                MachineRecipe.id, guest_recipe.id):
            session.begin(nested=True)
            try:
                schedule_queued_recipe(recipe_id, guest_recipe_id)
                session.commit()
            except (StaleSystemUserException, InsufficientSystemPermissions,
                    StaleTaskStatusException), e:
                # Either
                # System user has changed before
                # system allocation
                # or
                # System permissions have changed before
                # system allocation
                # or
                # Something has moved our status on from queued
                # already.
                log.warn(str(e))
                session.rollback()
            except Exception, e:
                log.exception('Error in schedule_queued_recipe(%s)', recipe_id)
                session.rollback()
                session.begin(nested=True)
                try:
                    recipe = MachineRecipe.by_id(recipe_id)
                    recipe.recipeset.abort(
                        u"Aborted in schedule_queued_recipe: %s" % e)
                    session.commit()
                except Exception, e:
                    log.exception(
                        "Error during error handling in schedule_queued_recipe: %s"
                        % e)
                    session.rollback()