You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
heartbeat/include/heartbeat.h

406 lines
14 KiB

/*
* heartbeat.h: core definitions for the Linux-HA heartbeat program
*
* Copyright (C) 2000 Alan Robertson <alanr@unix.sh>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#ifndef _HEARTBEAT_H
# define _HEARTBEAT_H 1
#ifdef SYSV
# include <sys/termio.h>
# define TERMIOS termio
# define GETATTR(fd, s) ioctl(fd, TCGETA, s)
# define SETATTR(fd, s) ioctl(fd, TCSETA, s)
# define FLUSH(fd) ioctl(fd, TCFLSH, 2)
#else
# define TERMIOS termios
# include <termios.h>
# define GETATTR(fd, s) tcgetattr(fd, s)
# define SETATTR(fd, s) tcsetattr(fd, TCSAFLUSH, s)
# define FLUSH(fd) tcflush(fd, TCIOFLUSH)
#endif
#include <hb_config.h>
#include <limits.h>
#include <syslog.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <time.h>
#include <sys/times.h>
#include <netinet/in.h>
#include <HBauth.h>
#include <ha_msg.h>
#include <HBcomm.h>
#include <stonith/stonith.h>
#include <clplumbing/cl_log.h>
#include <clplumbing/longclock.h>
#include <clplumbing/ipc.h>
#include <clplumbing/proctrack.h>
#include <clplumbing/cl_malloc.h>
#include <clplumbing/GSource.h>
#define index FooIndex
#define time FooTime
#include <glib.h>
#undef index
#undef time
/*
* <syslog.h> might not contain LOG_PRI...
* So, we define it ourselves, or error out if we can't...
*/
#ifndef LOG_PRI
# ifdef LOG_PRIMASK
/* David Lee <T.D.Lee@durham.ac.uk> reports this works on Solaris */
# define LOG_PRI(p) ((p) & LOG_PRIMASK)
# else
# error "Syslog.h does not define either LOG_PRI or LOG_PRIMASK."
# endif
#endif
#define MAXFIELDS 30 /* Max # of fields in a msg */
#define HOSTLENG 100 /* Maximum size of "uname -a" return */
#define STATUSLENG 32 /* Maximum size of status field */
#define MAXIFACELEN 30 /* Maximum interface length */
#define MAXSERIAL 4
#define MAXMEDIA 64
#define MAXNODE 100
#define MAXPROCS ((2*MAXMEDIA)+2)
#define FIFOMODE 0600
#define RQSTDELAY 10
#define ACK_MSG_DIV 10
#define RSC_TMPDIR HA_VARRUNDIR "/heartbeat/rsctmp"
#define HA_MODULE_D HA_LIBHBDIR "/modules"
#define HA_PLUGIN_D HA_LIBHBDIR "/plugins"
/* For compatability with older external facing headers
* These variables are no longer used internally
*/
#define HA_D HA_RC_DIR
#define HB_RC_DIR HA_RC_DIR
#define VAR_RUN_D HA_VARRUNDIR
#define VAR_LOG_D HA_VARLOGDIR
#define VAR_LIB_D HA_VARLIBHBDIR
#define HALIB HA_LIBDIR
/* #define HA_DEBUG */
#define DEFAULTLOG HA_VARLOGDIR "/ha-log"
#define DEFAULTDEBUG HA_VARLOGDIR "/ha-debug"
#define DEVNULL "/dev/null"
#define HA_OKEXIT 0
#define HA_FAILEXIT 1
#define WHITESPACE " \t\n\r\f"
#define DELIMS ", \t\n\r\f"
#define COMMENTCHAR '#'
#define CRLF "\r\n"
#define STATUS "STATUS"
#define INITSTATUS "init" /* Status of a node we've never heard from */
#define UPSTATUS "up" /* Listening (we might not be xmitting) */
#define ACTIVESTATUS "active" /* fully functional, and all links are up */
#define DEADSTATUS "dead" /* Status of non-working link or machine */
#define PINGSTATUS "ping" /* Status of a working ping node */
#define JOINSTATUS "join" /* Status when an api client joins */
#define LEAVESTATUS "leave" /* Status when an api client leaves */
#define ONLINESTATUS "online" /* Status of an online client */
#define OFFLINESTATUS "offline" /* Status of an offline client */
#define LINKUP "up" /* The status assigned to a working link */
#define LOADAVG "/proc/loadavg"
#define PIDFILE HA_VARRUNDIR "/heartbeat.pid"
#define KEYFILE HA_HBCONF_DIR "/authkeys"
#define HA_SERVICENAME "ha-cluster" /* Our official reg'd service name */
#define UDPPORT 694 /* Our official reg'd port number */
/* Environment variables we pass to our scripts... */
#define CURHOSTENV "HA_CURHOST"
#define OLDSTATUS "HA_OSTATUS"
#define DATEFMT "HA_DATEFMT" /* Format string for date(1) */
#define LOGFENV "HA_LOGFILE" /* well-formed log file :-) */
#define DEBUGFENV "HA_DEBUGLOG" /* Debug log file */
#define LOGFACILITY "HA_LOGFACILITY"/* Facility to use for logger */
#define HADIRENV "HA_DIR" /* The base HA directory */
#define HAFUNCENV "HA_FUNCS" /* Location of ha shell functions */
#define HANICEFAILBACK "HA_NICEFAILBACK" /* "yes" when nice_failback is on */
#define HADONTASK "HA_DONTASK" /* "yes" when no other nodes "active" ...*/
#define HADEBUGVAL "HA_DEBUG" /* current debug value (if nonzero) */
#define HALOGD "HA_LOGD" /* whether we use logging daemon or not */
#define DEFAULTBAUD B19200 /* Default serial link speed */
#define DEFAULTBAUDRATE 19200 /* Default serial link speed as int */
#define DEFAULTBAUDSTR "19200" /* Default serial link speed as string */
/* multicast defaults */
#define DEFAULT_MCAST_IPADDR "225.0.0.1" /* Default multicast group */
#define DEFAULT_MCAST_TTL 1 /* Default multicast TTL */
#define DEFAULT_MCAST_LOOP 0 /* Default mulitcast loopback option */
#define HB_STATIC_PRIO 1 /* Used with soft realtime scheduling */
#define PPP_D HA_VARRUNDIR "/ppp.d"
#define FIFONAME HA_VARLIBHBDIR "/fifo"
#define HOSTUUIDCACHEFILE HA_VARLIBHBDIR "/hostcache"
#define DELHOSTCACHEFILE HA_VARLIBHBDIR "/delhostcache"
#define HOSTUUIDCACHEFILETMP HOSTUUIDCACHEFILE ".tmp"
#define DELHOSTCACHEFILETMP DELHOSTCACHEFILE ".tmp"
#define RCSCRIPT HA_HBCONF_DIR "/harc"
#define CONFIG_NAME HA_HBCONF_DIR "/ha.cf"
#define RESOURCE_CFG HA_HBCONF_DIR "/haresources"
/* dynamic module directories */
#define COMM_MODULE_DIR HA_MODULE_D "/comm"
#define AUTH_MODULE_DIR HA_MODULE_D "/auth"
#define STATIC /* static */
#define HA_DATEFMT "%Y/%m/%d_%T\t"
#define HA_FUNCS HA_HBCONF_DIR "/shellfuncs"
#define RC_ARG0 "harc"
#define ENV_PREFIX "HA_"
/* Which side of a pipe is which? */
#define P_READFD 0
#define P_WRITEFD 1
#define FD_STDIN 0
#define FD_STDOUT 1
#define FD_STDERR 2
#define PROTOCOL_VERSION 1
typedef unsigned long seqno_t;
#define MAXMSGHIST 500
#define MAXMISSING MAXMSGHIST
#define NOSEQUENCE 0xffffffffUL
struct seqtrack {
longclock_t last_rexmit_req;
int nmissing;
seqno_t generation; /* Heartbeat generation # */
seqno_t last_seq;
seqno_t first_missing_seq; /* the smallest missing seq number*/
GList* client_status_msg_queue; /*client status message queue*/
seqno_t seqmissing[MAXMISSING];
const char * last_iface;
seqno_t ack_trigger; /*whenever a message received
*with seq % ACK_MSG_DIV == ack_trigger
*we send back an ACK
*/
seqno_t ackseq; /* ACKed seq*/
};
struct link {
longclock_t lastupdate;
const char * name;
int isping;
char status[STATUSLENG]; /* up or down */
TIME_T rmt_lastupdate; /* node's idea of last update time for this link */
};
#define NORMALNODE_I 0
#define PINGNODE_I 1
#define NORMALNODE "normal"
#define PINGNODE "ping"
#define UNKNOWNNODE "unknown"
struct node_info {
int nodetype;
char nodename[HOSTLENG]; /* Host name from config file */
cl_uuid_t uuid;
char site[HOSTLENG];
int weight;
char status[STATUSLENG]; /* Status from heartbeat */
gboolean status_suppressed; /* Status reports suppressed
for now */
struct ha_msg* saved_status_msg; /* Last status (ignored) */
struct link links[MAXMEDIA];
int nlinks;
TIME_T rmt_lastupdate; /* node's idea of last update time */
seqno_t status_seqno; /* Seqno of last status update */
longclock_t dead_ticks; /* # ticks to declare dead */
longclock_t local_lastupdate;/* Date of last update in clock_t time*/
int anypacketsyet; /* True after reception of 1st pkt */
struct seqtrack track;
int has_resources; /* TRUE if node may have resources */
};
typedef enum {
HB_JOIN_NONE = 0, /* Don't allow runtime joins of unknown nodes */
HB_JOIN_OTHER = 1, /* Allow runtime joins of other nodes */
HB_JOIN_ANY = 2, /* Don't even require _us_ to be in ha.cf */
}hbjointype_t;
#define MAXAUTH 16
struct sys_config {
TIME_T cfg_time; /* Timestamp of config file */
TIME_T auth_time; /* Timestamp of authorization file */
TIME_T rsc_time; /* Timestamp of haresources file */
int format_vers; /* Version of this info */
int nodecount; /* Number of nodes in cluster */
long heartbeat_ms; /* Milliseconds between heartbeats */
long deadtime_ms; /* Ticks before declaring dead */
long deadping_ms; /* Ticks before declaring ping nodes */
long initial_deadtime_ms; /* Ticks before saying dead 1st time*/
long warntime_ms; /* Ticks before issuing warning */
int hopfudge; /* hops beyond nodecount allowed */
int log_facility; /* syslog facility, if any */
char facilityname[PATH_MAX]; /* syslog facility name (if any) */
char logfile[PATH_MAX]; /* path to log file, if any */
int use_logfile; /* Flag to use the log file*/
char dbgfile[PATH_MAX]; /* path to debug file, if any */
int use_dbgfile; /* Flag to use the debug file*/
int memreserve; /* number of kbytes to preallocate in heartbeat */
int rereadauth; /* 1 if we need to reread auth file */
seqno_t generation; /* Heartbeat generation # */
cl_uuid_t uuid; /* uuid for this node*/
int uuidfromname; /* do we get uuid from nodename?*/
char cluster[PATH_MAX]; /* the name of cluster*/
char quorum_server[PATH_MAX];/* the quorum_server*/
hbjointype_t rtjoinconfig; /* Runtime join behavior */
int authnum;
Stonith* stonith; /* Stonith method - r1-style cluster only */
struct HBauth_info* authmethod; /* auth_config[authnum] */
struct node_info nodes[MAXNODE];
struct HBauth_info auth_config[MAXAUTH];
GList* client_list;
/* List data: struct client_child */
GList* last_client;/* Last in client_list */
};
typedef enum {
MEDIA_OK = 0,
MEDIA_INRECOVERY=1,
MEDIA_DELAYEDRECOVERY=2
}media_recov_t;
struct hb_media {
void * pd; /* Private Data */
const char * name; /* Unique medium name */
char* type; /* Medium type */
char* description; /* Medium description */
const struct hb_media_fns*vf; /* Virtual Functions */
media_recov_t recovery_state; /* What's up with media? */
gboolean suppresserrs; /* TRUE if errors shouldn't be logged */
int ourproc; /* Value of ourproc for 1st process */
IPC_Channel* wchan[2];
/* Read by the write child processes. */
IPC_Channel* rchan[2];
/* Written to by the read child processes. */
GCHSource* readsource;
GCHSource* writesource;
};
int parse_authfile(void);
struct msg_xmit_hist {
struct ha_msg* msgq[MAXMSGHIST];
seqno_t seqnos[MAXMSGHIST];
longclock_t lastrexmit[MAXMSGHIST];
int lastmsg;
seqno_t hiseq;
seqno_t lowseq; /* one less than min actually present */
seqno_t ackseq;
struct node_info* lowest_acknode;
};
/*
* client_child: information on clients that we spawn and keep track of
* They don't strictly have to use the client API, but most probably do.
* We start them when we start up, and shut them down when we shut down.
* Normally, if they they die, we restart them.
*/
struct client_child {
pid_t pid; /* Process id of child process */
ProcTrack* proctrack; /* Process tracking structure */
gboolean respawn; /* Respawn it if it dies? */
gboolean rebootifitdies; /* Reboot system it if it dies? */
uid_t u_runas; /* Which user to run as? */
gid_t g_runas; /* Which group id to run as? */
int respawncount; /* Last time we respawned */
int shortrcount; /* Count of fast respawns */
char* command; /* What command to run? */
char* path; /* Path (argv[0])? */
};
int api_remove_client_pid(pid_t c_pid, const char * reason);
extern struct sys_config * config;
extern int debug_level;
extern int udpport;
extern int RestartRequested;
extern char * localnodename;
#define ha_log cl_log
#define ha_perror cl_perror
/* Generally useful exportable HA heartbeat routines... */
extern void ha_assert(const char *s, int line, const char * file);
gboolean heartbeat_on_congestion(void);
extern int send_cluster_msg(struct ha_msg*msg);
extern void cleanexit(int exitcode);
extern void check_auth_change(struct sys_config *);
extern void (*localdie)(void);
extern int should_ring_copy_msg(struct ha_msg* m);
extern int controlipc2msg(IPC_Channel * channel
, struct ha_msg **);
extern int add_msg_auth(struct ha_msg * msg);
extern unsigned char * calc_cksum(const char * authmethod, const char * key, const char * value);
struct node_info * lookup_node(const char *);
struct link * lookup_iface(struct node_info * hip, const char *iface);
struct link * iface_lookup_node(const char *);
int add_node(const char * value, int nodetype);
int set_node_weight(const char * value, int weight);
int set_node_site(const char * value, const char * site);
int remove_node(const char * value, int);
void SetParameterValue(const char * name, const char * value);
gint uuid_equal(gconstpointer v, gconstpointer v2);
guint uuid_hash(gconstpointer key);
int write_cache_file(struct sys_config * cfg);
int read_cache_file(struct sys_config * cfg);
int write_delnode_file(struct sys_config * cfg);
void add_nametable(const char* nodename, struct node_info* value);
void add_uuidtable(cl_uuid_t*, struct node_info* value);
const char * uuid2nodename(cl_uuid_t* uuid);
int nodename2uuid(const char* nodename, cl_uuid_t*);
int inittable(void);
gboolean update_tables(const char* nodename, cl_uuid_t* uuid);
struct node_info* lookup_tables(const char* nodename, cl_uuid_t* uuid);
void cleanuptable(void);
int tables_remove(const char* nodename, cl_uuid_t* uuid);
int GetUUID(struct sys_config*, const char*, cl_uuid_t* uuid);
void remove_from_dellist( const char* nodename);
void append_to_dellist(struct node_info* hip);
void request_msg_rexmit(struct node_info *node, seqno_t lowseq, seqno_t hiseq);
int remove_msg_rexmit(struct node_info *node, seqno_t seq);
int init_rexmit_hash_table(void);
int destroy_rexmit_hash_table(void);
#endif /* _HEARTBEAT_H */