Ejemplo n.º 1
0
def _nfvi_host_get_callback(nfvi_host_uuid, nfvi_host_name):
    """
    NFVI Host get callback
    """
    DLOG.debug("Host get, nfvi_host_uuid=%s, nfvi_host_name=%s." %
               (nfvi_host_uuid, nfvi_host_name))

    instances = 0
    instances_failed = 0
    instances_stopped = 0

    host_table = tables.tables_get_host_table()
    host = host_table.get(nfvi_host_name, None)
    if host is not None:
        instance_table = tables.tables_get_instance_table()
        for instance in instance_table.on_host(host.name):
            if instance.is_deleting() or instance.is_deleted():
                continue

            if instance.is_failed():
                instances_failed += 1

            if instance.is_locked():
                instances_stopped += 1

            instances += 1

    DLOG.info("Host %s has %s instances, failed=%s, stopped=%s." %
              (host.name, instances, instances_failed, instances_stopped))
    return True, instances, instances_failed, instances_stopped
Ejemplo n.º 2
0
def _audit_nfvi_instance_callback(instance_uuid):
    """
    Audit Instance
    """
    global _nfvi_instance_outstanding

    response = (yield)

    if instance_uuid in _nfvi_instance_outstanding:
        del _nfvi_instance_outstanding[instance_uuid]

    if response['completed']:
        nfvi_instance = response['result-data']

        DLOG.info("Audit-Instance callback for %s" % nfvi_instance.uuid)

        instance_table = tables.tables_get_instance_table()
        instance = instance_table.get(nfvi_instance.uuid, None)
        if instance is None:
            if nfvi.objects.v1.INSTANCE_AVAIL_STATUS.DELETED \
                    not in nfvi_instance.avail_status:
                instance = objects.Instance(nfvi_instance)
                instance_table[instance.uuid] = instance
                instance.nfvi_instance_update(nfvi_instance)
        else:
            if instance.nfvi_instance_audit_in_progress:
                # Show that the audit is complete
                instance.nfvi_instance_audit_in_progress = False
                instance.nfvi_instance_update(nfvi_instance)
            else:
                DLOG.info("Ignoring stale audit reply for %s" %
                          nfvi_instance.uuid)
    else:
        DLOG.error("Audit-Instance callback, not completed, response=%s." %
                   response)
Ejemplo n.º 3
0
def _nfvi_instance_delete_callback(nfvi_instance_uuid):
    """
    NFVI Instance delete callback
    """
    DLOG.info("Instance delete, nfvi_instance_uuid=%s." % nfvi_instance_uuid)

    instance_table = tables.tables_get_instance_table()
    instance = instance_table.get(nfvi_instance_uuid, None)
    if instance is not None:
        instance.nfvi_instance_delete()
Ejemplo n.º 4
0
def _nfvi_guest_services_query_callback(nfvi_host_uuid, nfvi_instance_uuid):
    """
    NFVI Guest Services query callback
    """
    DLOG.debug("Guest-Services query, nfvi_host_uuid=%s, "
               "nfvi_instance_uuid=%s." % (nfvi_host_uuid, nfvi_instance_uuid))

    # scope of instance
    if nfvi_instance_uuid is not None:
        instance_table = tables.tables_get_instance_table()
        instance = instance_table.get(nfvi_instance_uuid, None)
        if instance is None:
            return False, None

        result = dict()
        result['uuid'] = instance.uuid
        result['hostname'] = instance.host_name
        result['services'] = instance.guest_services.get_nfvi_guest_services()
        return True, result

    # scope of host
    host_table = tables.tables_get_host_table()
    host = host_table.get_by_uuid(nfvi_host_uuid)
    if host is None:
        return False, None

    instance_table = tables.tables_get_instance_table()
    instances = list()
    for instance in instance_table.on_host(host.name):
        guest_services = instance.guest_services
        if guest_services.are_provisioned():
            result = dict()
            result['uuid'] = instance.uuid
            result['hostname'] = instance.host_name
            result['services'] = guest_services.get_nfvi_guest_services()
            instances.append(result)

    results = dict()
    results['instances'] = instances
    return True, results
Ejemplo n.º 5
0
    def manage_alarms(self):
        """
        Manage alarms
        """
        from nfv_vim import tables

        instance_table = tables.tables_get_instance_table()

        for member_uuid in self.member_uuids:
            member = instance_table.get(member_uuid, None)
            if member is None or member.is_deleted():
                continue

            for peer_member_uuid in self.member_uuids:
                peer_member = instance_table.get(peer_member_uuid, None)
                if peer_member is None or peer_member.is_deleted():
                    continue

                if peer_member.uuid == member.uuid:
                    continue

                if INSTANCE_GROUP_POLICY.AFFINITY_BEST_EFFORT in self.policies:
                    if peer_member.host_name != member.host_name:
                        if not self._alarms:
                            additional_text = (
                                ", some instances are not on the same host")
                            self._alarms = \
                                alarm.raise_instance_group_policy_alarm(
                                    self,
                                    INSTANCE_GROUP_POLICY.AFFINITY_BEST_EFFORT,
                                    alarm.ALARM_TYPE.
                                    INSTANCE_GROUP_POLICY_CONFLICT,
                                    additional_text=additional_text)
                        return
                elif INSTANCE_GROUP_POLICY.ANTI_AFFINITY_BEST_EFFORT in \
                        self.policies:
                    if peer_member.host_name == member.host_name:
                        if not self._alarms:
                            additional_text = (
                                ", some instances are on the same host")
                            self._alarms = \
                                alarm.raise_instance_group_policy_alarm(
                                    self,
                                    INSTANCE_GROUP_POLICY.
                                    ANTI_AFFINITY_BEST_EFFORT,
                                    alarm.ALARM_TYPE.
                                    INSTANCE_GROUP_POLICY_CONFLICT,
                                    additional_text=additional_text)
                        return

        # No policy conflicts were detected
        self.clear_alarms()
Ejemplo n.º 6
0
def _audit_alarms():
    """
    Audit Alarms. This is being done to allow hold off times to be supported
    for instance alarms. By auditing the instance alarms every 10 seconds, it
    allows a held off alarm to be raised within 10 seconds of the hold off
    time expiring.
    """
    while True:
        timer_id = (yield)
        DLOG.verbose("Audit alarms called, timer_id=%s." % timer_id)
        instance_table = tables.tables_get_instance_table()
        for instance in instance_table.itervalues():
            if not instance.is_deleted():
                alarm.instance_manage_alarms(instance)
Ejemplo n.º 7
0
def _nfvi_instance_action_callback(nfvi_instance_uuid, nfvi_action_data):
    """
    NFVI Instance action callback
    """
    DLOG.debug("Instance action, uuid=%s, nfvi_action_data=%s" %
               (nfvi_instance_uuid, nfvi_action_data))

    instance_table = tables.tables_get_instance_table()
    instance = instance_table.get(nfvi_instance_uuid, None)
    if instance is not None:
        instance.nfvi_instance_action_update(nfvi_action_data)
        return True
    else:
        DLOG.error("Instance %s is not found" % nfvi_instance_uuid)
        return False
Ejemplo n.º 8
0
def _nfvi_guest_services_state_notify_callback(nfvi_instance_uuid,
                                               nfvi_host_name,
                                               nfvi_guest_services):
    """
    NFVI Guest Services notify callback for service type event
    """
    DLOG.debug("Guest-Services state notify, instance_uuid=%s, "
               "host_name=%s guest_services=%s." %
               (nfvi_instance_uuid, nfvi_host_name, nfvi_guest_services))

    instance_table = tables.tables_get_instance_table()
    instance = instance_table.get(nfvi_instance_uuid, None)
    if instance is not None:
        instance.nfvi_guest_services_update(nfvi_guest_services,
                                            nfvi_host_name)
Ejemplo n.º 9
0
def _audit_nfvi_guest_services():
    """
    Audit NFVI Guest Services
    """
    while True:
        timer_id = (yield)
        DLOG.verbose("Audit guest services called, timer_id=%s." % timer_id)
        instance_table = tables.tables_get_instance_table()
        for instance_uuid in instance_table.keys():
            instance = instance_table[instance_uuid]
            if instance is not None:
                if not instance.is_deleted():
                    if instance.guest_services.are_provisioned():
                        nfvi.nfvi_guest_services_query(
                            instance_uuid, _audit_nfvi_guest_services_callback())
Ejemplo n.º 10
0
def vim_instance_api_start_instance(connection, msg):
    """
    Handle Start-Instance API request
    """
    DLOG.verbose("Start instance %s." % msg.uuid)
    instance_table = tables.tables_get_instance_table()
    response = rpc.APIResponseStartInstance()
    instance = instance_table.get(msg.uuid, None)
    if instance is not None:
        instance.do_action(objects.INSTANCE_ACTION_TYPE.START)
        response.uuid = msg.uuid
    else:
        response.result = rpc.RPC_MSG_RESULT.NOT_FOUND
    connection.send(response.serialize())
    DLOG.verbose("Sent response=%s" % response)
    connection.close()
Ejemplo n.º 11
0
def _nfvi_instance_state_change_callback(nfvi_instance):
    """
    NFVI Instance state change callback
    """
    DLOG.debug("Instance state-change, nfvi_instance=%s." % nfvi_instance)

    instance_table = tables.tables_get_instance_table()
    instance = instance_table.get(nfvi_instance.uuid, None)
    if instance is None:
        if nfvi.objects.v1.INSTANCE_AVAIL_STATUS.DELETED \
                not in nfvi_instance.avail_status:
            nfvi.nfvi_get_instance(nfvi_instance.uuid,
                                   _query_nfvi_instance_callback())
    else:
        # We are handling a notification from nova, which will not have all
        # the data for the nfvi_instance we store as part of our instance
        # object. As part of the processing of the notification, we are going
        # to save the nfvi_instance to the database, so make sure we don't
        # overwrite data that did not come in the notification, by retrieving
        # it from the instance object. Yes - this is ugly. No - I'm not going
        # to rewrite this now.
        if nfvi_instance.tenant_id is None:
            nfvi_instance.tenant_id = instance.tenant_uuid

        if nfvi_instance.instance_type is None:
            nfvi_instance.instance_type = instance._nfvi_instance.instance_type

        if nfvi_instance.image_uuid is None:
            nfvi_instance.image_uuid = instance.image_uuid

        if not nfvi_instance.attached_volumes:
            nfvi_instance.attached_volumes = instance.attached_volumes

        if nfvi_instance.recovery_priority is None:
            nfvi_instance.recovery_priority = \
                instance._nfvi_instance.recovery_priority

        if nfvi_instance.live_migration_timeout is None:
            nfvi_instance.live_migration_timeout = \
                instance._nfvi_instance.live_migration_timeout

        instance.nfvi_instance_update(nfvi_instance)

        if nfvi.objects.v1.INSTANCE_AVAIL_STATUS.DELETED \
                in nfvi_instance.avail_status:
            instance.nfvi_instance_deleted()
    return True
Ejemplo n.º 12
0
def vim_instance_api_delete_instance(connection, msg):
    """
    Handle Delete-Instance API request
    """
    DLOG.verbose("Delete instance %s." % msg.uuid)
    instance_table = tables.tables_get_instance_table()
    response = rpc.APIResponseDeleteInstance()
    instance = instance_table.get(msg.uuid, None)
    if instance is not None:
        instance_director = directors.get_instance_director()
        instance_director.delete_instance(instance)
        response.uuid = msg.uuid
    else:
        response.result = rpc.RPC_MSG_RESULT.NOT_FOUND
    connection.send(response.serialize())
    DLOG.verbose("Sent response=%s" % response)
    connection.close()
Ejemplo n.º 13
0
def _create_instance_callback(success, instance_name, instance_uuid):
    """
    Handle Create-Instance callback
    """
    DLOG.verbose("Create instance callback, name=%s." % instance_name)
    connection = _instance_create_operations.get(instance_name, None)
    if connection is not None:
        instance_table = tables.tables_get_instance_table()
        response = rpc.APIResponseCreateInstance()
        if success:
            instance = instance_table.get(instance_uuid, None)
            if instance is not None:
                response.uuid = instance.uuid
                response.name = instance.name
                response.admin_state = instance.admin_state
                response.oper_state = instance.oper_state
                response.avail_status = instance.avail_status
                response.action = instance.action
                response.host_name = instance.host_name
                response.instance_type_original_name \
                    = instance.instance_type_original_name
                response.image_uuid = instance.image_uuid
                response.vcpus = instance.vcpus
                response.memory_mb = instance.memory_mb
                response.disk_gb = instance.disk_gb
                response.ephemeral_gb = instance.ephemeral_gb
                response.swap_gb = instance.swap_gb
                response.auto_recovery = instance.auto_recovery
                response.live_migration_timeout \
                    = instance.max_live_migrate_wait_in_secs
                response.live_migration_max_downtime \
                    = instance.max_live_migration_downtime_in_ms
                if instance.host_name is not None:
                    host_table = tables.tables_get_host_table()
                    host = host_table.get(instance.host_name, None)
                    if host is not None:
                        response.host_uuid = host.uuid
            else:
                response.result = rpc.RPC_MSG_RESULT.FAILED
        else:
            response.result = rpc.RPC_MSG_RESULT.FAILED

        connection.send(response.serialize())
        connection.close()
        DLOG.info("Sent response=%s" % response)
        del _instance_create_operations[instance_name]
Ejemplo n.º 14
0
def _audit_nfvi_instance():
    """
    Audit NFVI for Instance Details
    """
    global _nfvi_instances_to_audit, _nfvi_instance_outstanding

    while True:
        timer_id = (yield)
        DLOG.verbose("Audit instance called, timer_id=%s." % timer_id)

        instance_table = tables.tables_get_instance_table()
        for instance_uuid in _nfvi_instance_outstanding.keys():
            instance = instance_table.get(instance_uuid, None)
            if instance is None:
                del _nfvi_instance_outstanding[instance_uuid]

        if 0 < len(_nfvi_instance_outstanding):
            DLOG.info(
                "Audit instance queries still outstanding, outstanding=%s" %
                _nfvi_instance_outstanding)
            _audit_dump_debug_info()
        else:
            _audit_dump_debug_info(do_dump=False)

        for instance_uuid in _nfvi_instances_to_audit.keys():
            if 4 <= len(_nfvi_instance_outstanding):
                break

            do_audit = True
            instance = instance_table.get(instance_uuid, None)
            if instance is not None:
                if instance.nfvi_instance_is_deleted():
                    do_audit = False
                else:
                    # Indicate that audit is in progress
                    instance.nfvi_instance_audit_in_progress = True

            if do_audit:
                DLOG.info("Auditing instance %s." % instance_uuid)
                nfvi.nfvi_get_instance(
                    instance_uuid,
                    _audit_nfvi_instance_callback(instance_uuid))
                _nfvi_instance_outstanding[instance_uuid] \
                    = _nfvi_instances_to_audit[instance_uuid]

            del _nfvi_instances_to_audit[instance_uuid]
Ejemplo n.º 15
0
def _nfvi_instance_action_change_callback(nfvi_instance_uuid,
                                          nfvi_action_type,
                                          nfvi_action_state,
                                          reason=""):
    """
    NFVI Instance action change callback
    """
    DLOG.debug(
        "Instance action-change, uuid=%s, nfvi_action=%s, "
        "nfvi_action_state=%s, reason=%s." %
        (nfvi_instance_uuid, nfvi_action_type, nfvi_action_state, reason))

    instance_table = tables.tables_get_instance_table()
    instance = instance_table.get(nfvi_instance_uuid, None)
    if instance is not None:
        instance.nfvi_instance_action_change(nfvi_action_type,
                                             nfvi_action_state, reason)
    return True
Ejemplo n.º 16
0
def _nfvi_guest_services_action_notify_callback(nfvi_instance_uuid,
                                                nfvi_action_type,
                                                nfvi_action_state, reason):
    """
    NFVI Guest Services notify callback for action type event
    """
    DLOG.debug(
        "Guest-Services action notify, instance_uuid=%s, "
        "nfvi_action_type=%s, nfvi_action_state=%s, reason=%s." %
        (nfvi_instance_uuid, nfvi_action_type, nfvi_action_state, reason))

    instance_table = tables.tables_get_instance_table()
    instance = instance_table.get(nfvi_instance_uuid, None)
    if instance is None:
        return False

    instance.nfvi_instance_action_change(nfvi_action_type, nfvi_action_state,
                                         reason)
    return True
Ejemplo n.º 17
0
def vim_instance_api_get_instance(connection, msg):
    """
    Handle Get-Instance API request
    """
    DLOG.verbose("Get instance, filter_by_uuid=%s." % msg.filter_by_uuid)
    instance_table = tables.tables_get_instance_table()
    response = rpc.APIResponseGetInstance()
    instance = instance_table.get(msg.filter_by_uuid, None)
    if instance is not None:
        response.uuid = instance.uuid
        response.name = instance.name
        response.admin_state = instance.admin_state
        response.oper_state = instance.oper_state
        response.avail_status = instance.avail_status
        response.action = instance.action
        response.host_name = instance.host_name
        response.instance_type_original_name \
            = instance.instance_type_original_name
        response.image_uuid = instance.image_uuid
        response.vcpus = instance.vcpus
        response.memory_mb = instance.memory_mb
        response.disk_gb = instance.disk_gb
        response.ephemeral_gb = instance.ephemeral_gb
        response.swap_gb = instance.swap_gb
        response.auto_recovery = instance.auto_recovery
        response.live_migration_timeout \
            = instance.max_live_migrate_wait_in_secs
        response.live_migration_max_downtime \
            = instance.max_live_migration_downtime_in_ms
        if instance.host_name is not None:
            host_table = tables.tables_get_host_table()
            host = host_table.get(instance.host_name, None)
            if host is not None:
                response.host_uuid = host.uuid

    else:
        response.result = rpc.RPC_MSG_RESULT.NOT_FOUND
    connection.send(response.serialize())
    DLOG.verbose("Sent response=%s" % response)
    connection.close()
Ejemplo n.º 18
0
def _audit_nfvi_guest_services_callback():
    """
    Audit Guest Services
    """
    response = (yield)
    DLOG.verbose("Audit-Guest-Services callback, response=%s." % response)

    if response['completed']:
        result_data = response.get('result-data', None)
        if result_data is not None:
            instance_uuid = result_data['instance_uuid']
            instance_table = tables.tables_get_instance_table()
            instance = instance_table.get(instance_uuid, None)
            if instance is not None:
                host_name = result_data.get('host_name', None)
                nfvi_guest_services = result_data.get('services', list())
                instance.nfvi_guest_services_update(nfvi_guest_services,
                                                    host_name)

    else:
        DLOG.error("Audit-Guest-Services callback, not completed, "
                   "response=%s." % response)
Ejemplo n.º 19
0
def _query_nfvi_instance_callback():
    """
    Query Instance
    """
    response = (yield)
    DLOG.verbose("Query-Instance callback, response=%s." % response)

    if response['completed']:
        nfvi_instance = response['result-data']
        instance_table = tables.tables_get_instance_table()
        instance = instance_table.get(nfvi_instance.uuid, None)
        if instance is None:
            if nfvi.objects.v1.INSTANCE_AVAIL_STATUS.DELETED \
                    not in nfvi_instance.avail_status:
                instance = objects.Instance(nfvi_instance)
                instance_table[instance.uuid] = instance
                instance.nfvi_instance_update(nfvi_instance)
        else:
            instance.nfvi_instance_update(nfvi_instance)
    else:
        DLOG.error("Query-Instance callback, not completed, responses=%s." %
                   response)
Ejemplo n.º 20
0
def _nfvi_guest_services_alarm_notify_callback(nfvi_instance_uuid,
                                               nfvi_avail_status,
                                               nfvi_repair_action):
    """
    NFVI Guest Services notify callback for alarm type event
    """
    DLOG.debug("Guest-Services alarm notify, instance_uuid=%s, "
               "avail_status=%s, repair_action=%s." %
               (nfvi_instance_uuid, nfvi_avail_status, nfvi_repair_action))

    instance_table = tables.tables_get_instance_table()
    instance = instance_table.get(nfvi_instance_uuid, None)
    if instance is None:
        return False

    if nfvi.objects.v1.INSTANCE_AVAIL_STATUS.FAILED == nfvi_avail_status:
        if nfvi.objects.v1.INSTANCE_ACTION_TYPE.REBOOT == nfvi_repair_action:
            instance.guest_services_failed(do_soft_reboot=True)
        elif nfvi.objects.v1.INSTANCE_ACTION_TYPE.STOP == nfvi_repair_action:
            instance.guest_services_failed(do_stop=True)
        else:
            instance.guest_services_failed()

    elif nfvi.objects.v1.INSTANCE_AVAIL_STATUS.UNHEALTHY == nfvi_avail_status:
        if nfvi.objects.v1.INSTANCE_ACTION_TYPE.REBOOT == nfvi_repair_action:
            instance.guest_services_failed(do_soft_reboot=True,
                                           health_check_failed_only=True)
        elif nfvi.objects.v1.INSTANCE_ACTION_TYPE.STOP == nfvi_repair_action:
            instance.guest_services_failed(do_stop=True,
                                           health_check_failed_only=True)
        else:
            instance.guest_services_failed(health_check_failed_only=True)

    result = dict()
    result['uuid'] = instance.uuid
    result['hostname'] = instance.host_name
    result['services'] = instance.guest_services.get_nfvi_guest_services()
    return True, result
Ejemplo n.º 21
0
def _nfvi_host_notification_callback(host_ip, nfvi_notify_type,
                                     nfvi_notify_data):
    """
    NFVI Host notification callback
    """
    instance_count = 0
    status = 'error'

    if nfvi.objects.v1.HOST_NOTIFICATIONS.BOOTING == nfvi_notify_type:
        host_name = nfvi_notify_data.get('hostname', None)
        if host_name is not None:
            DLOG.info(
                "Booting notification received for host %s, host-ip=%s." %
                (host_name, host_ip))

            instance_table = tables.tables_get_instance_table()
            for instance in instance_table.on_host(host_name):
                if not (instance.is_deleting() or instance.is_deleted()
                        or instance.is_failed() or instance.is_locked()
                        or instance.is_rebuilding() or instance.is_migrating()
                        or instance.is_rebooting()):
                    DLOG.info(
                        "Failing instance %s because host %s is booting, "
                        "host-ip=%s." % (instance.name, host_name, host_ip))
                    instance.fail('host booting')
                    instance_count += 1

        if 0 == instance_count:
            status = 'okay'
        else:
            status = 'accepted'
    else:
        DLOG.error("Unknown host notification received, type=%s, data=%s" %
                   (nfvi_notify_type, nfvi_notify_data))

    return status
Ejemplo n.º 22
0
def _audit_nfvi_instances_callback(timer_id):
    """
    Audit Instances
    """
    global _main_audit_inprogress
    global _deletable_instances, _nfvi_instances_paging
    global _nfvi_instances_to_audit, _nfvi_instance_outstanding

    response = (yield)
    DLOG.verbose("Audit-Instances callback, response=%s." % response)

    trigger_recovery = False
    if response['completed']:
        if response[
                'page-request-id'] == _nfvi_instances_paging.page_request_id:
            instance_table = tables.tables_get_instance_table()

            if _deletable_instances is None:
                _deletable_instances = list(instance_table)

            for instance_uuid, instance_name in response['result-data']:
                instance = instance_table.get(instance_uuid, None)
                if instance is not None:
                    if instance.uuid in _deletable_instances:
                        _deletable_instances.remove(instance.uuid)
                if instance_uuid not in _nfvi_instances_to_audit:
                    _nfvi_instances_to_audit[instance_uuid] = instance_name

            if _nfvi_instances_paging.done:
                for instance_uuid in _deletable_instances:
                    instance = instance_table.get(instance_uuid, None)
                    if instance is not None:
                        DLOG.info("Deleting instance %s, audit mismatch" %
                                  instance_uuid)

                        instance.nfvi_instance_deleted()
                        if instance.is_deleted():
                            trigger_recovery = True
                            del instance_table[instance_uuid]
                            if instance_uuid in _nfvi_instances_to_audit:
                                del _nfvi_instances_to_audit[instance_uuid]
                            if instance_uuid in _nfvi_instance_outstanding:
                                del _nfvi_instance_outstanding[instance_uuid]

                _deletable_instances = list(instance_table)
                _nfvi_instances_paging.first_page()
            else:
                DLOG.verbose("Paging is not done for instances.")
        else:
            DLOG.error("Audit-Instances callback, page-request-id mismatch, "
                       "responses=%s, page-request-id=%s." %
                       (response, _nfvi_instances_paging.page_request_id))
            instance_table = tables.tables_get_instance_table()
            _deletable_instances = list(instance_table)
            _nfvi_instances_paging.first_page()
    else:
        DLOG.error("Audit-Instances callback, not completed, responses=%s." %
                   response)
        instance_table = tables.tables_get_instance_table()
        _deletable_instances = list(instance_table)
        _nfvi_instances_paging.first_page()

    _nfvi_instances_paging.set_page_request_id()
    _main_audit_inprogress = False
    timers.timers_reschedule_timer(timer_id, 2)  # 2 seconds later

    if trigger_recovery:
        # Resources have been freed, there is potential to recover instances.
        DLOG.info("Recover-Instances-Audit triggered by instance deletion.")
        instance_director = directors.get_instance_director()
        instance_director.recover_instances()