nfv/guest-client/guest-client-3.0.1/guest_client_api/sample_guest_app.c

361 lines
12 KiB
C
Executable File

/*
* Copyright (c) 2013-2016, Wind River Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* 3) Neither the name of Wind River Systems nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <errno.h>
#include "guest_api_types.h"
#include "guest_api_debug.h"
#include "guest_heartbeat_api.h"
static int _heartbeat_selobj = -1;
static bool _heartbeat_registered = false;
static bool _heartbeat_registering = false;
static char _application_name[40] = "sample-guest-app";
static GuestHeartbeatApiActionT _corrective_action;
static sig_atomic_t _stay_on = 1;
// ****************************************************************************
// Guest Application - Register State Callback
// ===========================================
static void guest_app_register_state_callback( bool state )
{
if (state)
_heartbeat_registering = false;
_heartbeat_registered = state;
}
// ****************************************************************************
// ****************************************************************************
// Guest Application - Health Check Callback
// =========================================
static void guest_app_health_check_callback(
bool* healthy, GuestHeartbeatApiActionT* corrective_action,
char log_msg[GUEST_HEARTBEAT_API_LOG_MAX] )
{
char filename[80];
int result;
snprintf(filename, sizeof(filename), "/tmp/%s_unhealthy",
_application_name);
result = access(filename, F_OK);
if (0 == result)
{
*healthy = false;
*corrective_action = _corrective_action;
snprintf(log_msg, GUEST_HEARTBEAT_API_LOG_MAX, "File %s exists.",
filename);
} else {
*healthy = true;
*corrective_action = GUEST_HEARTBEAT_API_ACTION_NONE;
log_msg[0] = '\0';
}
}
// ****************************************************************************
// ****************************************************************************
// Guest Application - Action Notify Callback
// ==========================================
static void guest_app_action_notify_callback(
int invocation_id, GuestHeartbeatApiEventT event,
GuestHeartbeatApiNotifyTypeT notify_type )
{
char filename[80];
GuestHeartbeatApiVoteResultT vote_result;
char log_msg[GUEST_HEARTBEAT_API_LOG_MAX];
GuestApiErrorT error;
int result;
snprintf(filename, sizeof(filename), "/tmp/%s_event_timeout",
_application_name);
result = access(filename, F_OK);
if (0 == result)
return;
if (GUEST_HEARTBEAT_API_NOTIFY_TYPE_REVOCABLE == notify_type)
{
switch (event)
{
case GUEST_HEARTBEAT_API_EVENT_STOP:
snprintf(filename, sizeof(filename),
"/tmp/%s_vote_no_to_stop", _application_name);
break;
case GUEST_HEARTBEAT_API_EVENT_REBOOT:
snprintf(filename, sizeof(filename),
"/tmp/%s_vote_no_to_reboot", _application_name);
break;
case GUEST_HEARTBEAT_API_EVENT_SUSPEND:
case GUEST_HEARTBEAT_API_EVENT_PAUSE:
snprintf(filename, sizeof(filename),
"/tmp/%s_vote_no_to_suspend", _application_name);
break;
case GUEST_HEARTBEAT_API_EVENT_RESIZE_BEGIN:
snprintf(filename, sizeof(filename),
"/tmp/%s_vote_no_to_resize", _application_name);
break;
case GUEST_HEARTBEAT_API_EVENT_LIVE_MIGRATE_BEGIN:
case GUEST_HEARTBEAT_API_EVENT_COLD_MIGRATE_BEGIN:
snprintf(filename, sizeof(filename),
"/tmp/%s_vote_no_to_migrate", _application_name);
break;
default:
DPRINTFE("Should never be asked to vote on event %s.",
guest_heartbeat_api_event_str(event));
return;
}
result = access(filename, F_OK);
if (0 == result)
{
vote_result = GUEST_HEARTBEAT_API_VOTE_RESULT_REJECT;
snprintf(log_msg, GUEST_HEARTBEAT_API_LOG_MAX, "File %s exists.",
filename);
} else {
vote_result = GUEST_HEARTBEAT_API_VOTE_RESULT_ACCEPT;
log_msg[0] = '\0';
}
} else {
vote_result = GUEST_HEARTBEAT_API_VOTE_RESULT_COMPLETE;
}
error = guest_heartbeat_api_send_action_response(invocation_id, event,
notify_type, vote_result, log_msg);
if (GUEST_API_OKAY != error)
{
DPRINTFE("Failed to send action response, error=%s.",
guest_api_error_str(error));
return;
}
}
// ****************************************************************************
// ****************************************************************************
// Guest Application - Signal Handler
// ==================================
static void guest_app_signal_handler( int signum )
{
switch (signum)
{
case SIGINT:
case SIGTERM:
case SIGQUIT:
_stay_on = 0;
break;
case SIGCONT:
DPRINTFD("Ignoring signal SIGCONT (%i).", signum);
break;
case SIGPIPE:
DPRINTFD("Ignoring signal SIGPIPE (%i).", signum);
break;
default:
DPRINTFD("Signal (%i) ignored.", signum);
break;
}
}
// ****************************************************************************
// ****************************************************************************
// Guest Application - Main
// ========================
int main( int argc, char *argv[], char *envp[] )
{
GuestHeartbeatApiCallbacksT callbacks;
GuestApiErrorT error;
error = guest_api_debug_initialize("Guest-Application");
if (GUEST_API_OKAY != error)
{
printf("Debug initialization failed, error=%s.\n",
guest_api_error_str(error));
return EXIT_FAILURE;
}
DPRINTFI("Starting.");
signal(SIGINT, guest_app_signal_handler);
signal(SIGTERM, guest_app_signal_handler);
signal(SIGQUIT, guest_app_signal_handler);
signal(SIGCONT, guest_app_signal_handler);
signal(SIGPIPE, guest_app_signal_handler);
_corrective_action = GUEST_HEARTBEAT_API_ACTION_REBOOT;
unsigned int arg_i;
for (arg_i=1; arg_i < argc; ++arg_i)
{
if (0 == strcmp("--name", argv[arg_i]))
{
arg_i++;
if (arg_i < argc)
snprintf(_application_name, sizeof(_application_name), "%s",
argv[arg_i]);
} else if (0 == strcmp("--corrective-action", argv[arg_i])) {
arg_i++;
if (arg_i < argc)
{
if (0 == strcmp("reboot", argv[arg_i]))
{
_corrective_action = GUEST_HEARTBEAT_API_ACTION_REBOOT;
} else if (0 == strcmp("stop", argv[arg_i])) {
_corrective_action = GUEST_HEARTBEAT_API_ACTION_STOP;
} else if (0 == strcmp("log", argv[arg_i])) {
_corrective_action = GUEST_HEARTBEAT_API_ACTION_LOG;
}
}
}
}
memset(&callbacks, 0, sizeof(callbacks));
callbacks.register_state = guest_app_register_state_callback;
callbacks.health_check = guest_app_health_check_callback;
callbacks.action_notify = guest_app_action_notify_callback;
error = guest_heartbeat_api_initialize(&callbacks);
if (GUEST_API_OKAY != error)
{
DPRINTFE("Failed to initialize guest heartbeat api, error=%s.",
guest_api_error_str(error));
return EXIT_FAILURE;
}
DPRINTFI("Started.");
while (_stay_on)
{
int num_fds;
fd_set fds;
struct timeval tv;
int result;
tv.tv_sec = 1;
tv.tv_usec = 0;
num_fds = 0;
FD_ZERO(&fds);
if (!_heartbeat_registered)
{
GuestHeartbeatApiInitDataT init_data;
snprintf(init_data.application_name,
sizeof(init_data.application_name), "%s",
_application_name);
init_data.heartbeat_interval_ms = 1000;
init_data.vote_secs = 8;
init_data.shutdown_notice_secs = 5;
init_data.suspend_notice_secs = 5;
init_data.resume_notice_secs = 5;
init_data.corrective_action = _corrective_action;
error = guest_heartbeat_api_register(&init_data);
if (GUEST_API_OKAY == error)
{
_heartbeat_registering = true;
} else {
_heartbeat_registering = false;
if (GUEST_API_TRY_AGAIN != error)
{
DPRINTFE("Failed to register for guest heartbeating, "
"error=%s.", guest_api_error_str(error));
return EXIT_FAILURE;
}
}
}
if (_heartbeat_registering || _heartbeat_registered)
{
_heartbeat_selobj = guest_heartbeat_api_get_selobj();
FD_SET(_heartbeat_selobj, &fds);
num_fds = _heartbeat_selobj;
}
result = select(num_fds+1, &fds, NULL, NULL, &tv);
if (0 > result)
{
if (errno == EINTR)
{
DPRINTFD("Interrupted by a signal.");
} else {
DPRINTFE("Select failed, error=%s.", strerror(errno));
}
} else if (0 == result) {
DPRINTFD("Nothing selected.");
} else {
if (FD_ISSET(_heartbeat_selobj, &fds))
{
guest_heartbeat_api_dispatch(_heartbeat_selobj);
}
}
}
DPRINTFI("Shutting down.");
error = guest_heartbeat_api_deregister("Exiting");
if (GUEST_API_OKAY != error)
{
DPRINTFE("Failed to deregister from guest heartbeat api, error=%s.",
guest_api_error_str(error));
}
error = guest_heartbeat_api_finalize();
if (GUEST_API_OKAY != error)
{
DPRINTFE("Failed to finalize guest heartbeat api, error=%s.",
guest_api_error_str(error));
}
DPRINTFI("Shutdown complete.");
error = guest_api_debug_finalize();
if (GUEST_API_OKAY != error)
{
printf("Debug finalization failed, error=%s.\n",
guest_api_error_str(error));
}
return EXIT_SUCCESS;
}
// ****************************************************************************