mirror of
https://github.com/samba-team/samba.git
synced 2025-01-11 05:18:09 +03:00
merge from tridge
(This used to be ctdb commit eda3caa77be352967a41ff9bddda5296c94797a9)
This commit is contained in:
commit
ab1c8c074e
@ -165,15 +165,11 @@ int ctdb_sys_send_tcp(int s,
|
||||
we try to bind to it, and if that fails then we don't have that IP
|
||||
on an interface
|
||||
*/
|
||||
bool ctdb_sys_have_ip(struct sockaddr_in ip, bool *is_loopback, TALLOC_CTX *mem_ctx, char **ifname)
|
||||
bool ctdb_sys_have_ip(struct sockaddr_in ip)
|
||||
{
|
||||
int s;
|
||||
int ret;
|
||||
|
||||
if (is_loopback) {
|
||||
DEBUG(0,(__location__ " NOT IMPLEMENTED YET: ctdb_sys_have_ip() does not yet support is_loopback on AIX. This needs to be implemented similar to system_linux.c\n"));
|
||||
}
|
||||
|
||||
ip.sin_port = 0;
|
||||
s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (s == -1) {
|
||||
|
@ -241,100 +241,21 @@ int ctdb_sys_send_tcp(int s,
|
||||
|
||||
we try to bind to it, and if that fails then we don't have that IP
|
||||
on an interface
|
||||
if is_loopback is specified it will also return whether the ip address
|
||||
is attached to the loopback interface or not
|
||||
|
||||
ifname, if non-NULL, will return the name of the interface this ip is tied to
|
||||
*/
|
||||
bool ctdb_sys_have_ip(struct sockaddr_in ip, bool *is_loopback, TALLOC_CTX *mem_ctx, char **ifname)
|
||||
bool ctdb_sys_have_ip(struct sockaddr_in ip)
|
||||
{
|
||||
struct ifreq *ifr = NULL;
|
||||
struct ifconf ifc;
|
||||
int s, i, num_ifs;
|
||||
int s;
|
||||
int ret;
|
||||
|
||||
if (is_loopback) {
|
||||
*is_loopback = false;
|
||||
}
|
||||
if (*ifname) {
|
||||
*ifname = NULL;
|
||||
}
|
||||
|
||||
ip.sin_port = 0;
|
||||
s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (s == -1) {
|
||||
return false;
|
||||
}
|
||||
ret = bind(s, (struct sockaddr *)&ip, sizeof(ip));
|
||||
if (ret) {
|
||||
goto finished;
|
||||
}
|
||||
|
||||
|
||||
/* find out how much space we need to store the interface details */
|
||||
ifc.ifc_len = 0;
|
||||
ifc.ifc_req = NULL;
|
||||
ret = ioctl(s, SIOCGIFCONF, &ifc);
|
||||
if (ret) {
|
||||
DEBUG(0,(__location__ " ioctl to read interface list failed\n"));
|
||||
goto finished;
|
||||
}
|
||||
|
||||
ifr = talloc_size(mem_ctx, ifc.ifc_len);
|
||||
|
||||
/* get a list of all interface names and addresses */
|
||||
ifc.ifc_req = ifr;
|
||||
ret = ioctl(s, SIOCGIFCONF, &ifc);
|
||||
if (ret) {
|
||||
DEBUG(0,(__location__ " ioctl to read interface list failed\n"));
|
||||
goto finished;
|
||||
}
|
||||
|
||||
/* loop over all interfaces and search for the one matching ip */
|
||||
num_ifs = ifc.ifc_len/sizeof(struct ifreq);
|
||||
for (i=0; i<num_ifs;i++) {
|
||||
struct sockaddr_in *sa;
|
||||
|
||||
/* we only care bout ipv4 addresses */
|
||||
sa = (struct sockaddr_in *)&ifr[i].ifr_addr;
|
||||
if (sa->sin_family != AF_INET) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* this is not the interface you are looking for */
|
||||
if (!ctdb_same_ip(sa, &ip)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* this is the ifr entry for this interface/address
|
||||
read the interface flags so we can tell if it is
|
||||
loopback or not
|
||||
*/
|
||||
ret = ioctl(s, SIOCGIFFLAGS, &ifr[i]);
|
||||
if (ret) {
|
||||
DEBUG(0,(__location__ " failed to read interface flags for interface %s\n", ifr[i].ifr_name));
|
||||
goto finished;
|
||||
}
|
||||
|
||||
/* was this ip tied to a loopback interface ? */
|
||||
if (ifr[i].ifr_flags & IFF_LOOPBACK) {
|
||||
if (is_loopback != NULL) {
|
||||
*is_loopback = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (ifname) {
|
||||
*ifname = talloc_asprintf(mem_ctx, "%s", ifr[i].ifr_name);
|
||||
}
|
||||
|
||||
/* if we got this far, we have found our interface so we can
|
||||
exit the loop.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
|
||||
finished:
|
||||
talloc_free(ifr);
|
||||
close(s);
|
||||
return ret == 0;
|
||||
}
|
||||
|
@ -92,6 +92,8 @@ start() {
|
||||
stop() {
|
||||
echo -n $"Shutting down ctdbd service: "
|
||||
ctdb shutdown
|
||||
sleep 1
|
||||
killall -q -9 ctdbd
|
||||
RETVAL=$?
|
||||
case $init_style in
|
||||
suse)
|
||||
|
@ -16,22 +16,56 @@ shift
|
||||
}
|
||||
|
||||
[ ! -f "$CTDB_PUBLIC_ADDRESSES" ] && {
|
||||
echo "No public addresses file found. Nothing to do for 10.interfaces"
|
||||
echo "`date` No public addresses file found. Nothing to do for 10.interfaces"
|
||||
exit 0
|
||||
}
|
||||
|
||||
################################################
|
||||
# kill off any TCP connections with the given IP
|
||||
kill_tcp_connections() {
|
||||
_IP="$1"
|
||||
_failed=0
|
||||
|
||||
_killcount=0
|
||||
connfile="/etc/ctdb/state/connections.$_IP"
|
||||
netstat -tn |egrep "^tcp.*\s+$_IP:.*ESTABLISHED" | awk '{print $4" "$5}' > $connfile
|
||||
while read dest src; do
|
||||
srcip=`echo $src | cut -d: -f1`
|
||||
srcport=`echo $src | cut -d: -f2`
|
||||
destip=`echo $dest | cut -d: -f1`
|
||||
destport=`echo $dest | cut -d: -f2`
|
||||
ctdb killtcp $srcip:$srcport $destip:$destport >/dev/null 2>&1 || _failed=1
|
||||
_killcount=`expr $_killcount + 1`
|
||||
done < $connfile
|
||||
/bin/rm -f $connfile
|
||||
[ $_failed = 0 ] || {
|
||||
echo "`date` Failed to send killtcp control"
|
||||
return;
|
||||
}
|
||||
[ $_killcount -gt 0 ] || {
|
||||
return;
|
||||
}
|
||||
_count=0
|
||||
while netstat -tn |egrep "^tcp.*\s+$_IP:.*ESTABLISHED" > /dev/null; do
|
||||
sleep 1
|
||||
_count=`expr $_count + 1`
|
||||
[ $_count -gt 3 ] && {
|
||||
echo "`date` Timed out killing tcp connections for IP $_IP"
|
||||
return;
|
||||
}
|
||||
done
|
||||
echo "`date` killed $_killcount TCP connections to released IP $_IP"
|
||||
}
|
||||
|
||||
case $cmd in
|
||||
#############################
|
||||
# called when ctdbd starts up
|
||||
startup)
|
||||
# make sure that we only respond to ARP messages from the NIC where
|
||||
# a particular ip address is associated.
|
||||
echo 1 > /proc/sys/ipv4/conf/all/arp_filter
|
||||
|
||||
# move all public addresses onto loopback
|
||||
cat $CTDB_PUBLIC_ADDRESSES | cut -d/ -f1 | while read ip; do
|
||||
/sbin/ip addr add $ip/32 dev lo >/dev/null 2>/dev/null
|
||||
done
|
||||
[ -f /proc/sys/net/ipv4/conf/all/arp_filter ] && {
|
||||
echo 1 > /proc/sys/net/ipv4/conf/all/arp_filter
|
||||
}
|
||||
;;
|
||||
|
||||
|
||||
@ -39,7 +73,7 @@ case $cmd in
|
||||
# called when ctdbd wants to claim an IP address
|
||||
takeip)
|
||||
if [ $# != 3 ]; then
|
||||
echo "must supply interface, IP and maskbits"
|
||||
echo "`date` must supply interface, IP and maskbits"
|
||||
exit 1
|
||||
fi
|
||||
iface=$1
|
||||
@ -51,11 +85,12 @@ case $cmd in
|
||||
echo "`/bin/date` Failed to bringup interface $iface"
|
||||
exit 1
|
||||
}
|
||||
/sbin/ip addr del $ip/32 dev lo >/dev/null 2>/dev/null
|
||||
/sbin/ip addr add $ip/$maskbits dev $iface || {
|
||||
echo "`/bin/date` Failed to add $ip/$maskbits on dev $iface"
|
||||
exit 1
|
||||
}
|
||||
# cope with the script being killed while we have the interface blocked
|
||||
/sbin/iptables -D INPUT -i $iface -d $ip -j DROP 2> /dev/null
|
||||
|
||||
# flush our route cache
|
||||
echo 1 > /proc/sys/net/ipv4/route/flush
|
||||
@ -69,14 +104,32 @@ case $cmd in
|
||||
echo "`/bin/date` must supply interface, IP and maskbits"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# releasing an IP is a bit more complex than it seems. Once the IP
|
||||
# is released, any open tcp connections to that IP on this host will end
|
||||
# up being stuck. Some of them (such as NFS connections) will be unkillable
|
||||
# so we need to use the killtcp ctdb function to kill them off. We also
|
||||
# need to make sure that no new connections get established while we are
|
||||
# doing this! So what we do is this:
|
||||
# 1) firewall this IP, so no new external packets arrive for it
|
||||
# 2) use netstat -tn to find existing connections, and kill them
|
||||
# 3) remove the IP from the interface
|
||||
# 4) remove the firewall rule
|
||||
iface=$1
|
||||
ip=$2
|
||||
maskbits=$3
|
||||
/sbin/ip addr del $ip/$maskbits dev $iface || {
|
||||
|
||||
failed=0
|
||||
# we do an extra delete to cope with the script being killed
|
||||
/sbin/iptables -D INPUT -i $iface -d $ip -j DROP 2> /dev/null
|
||||
/sbin/iptables -I INPUT -i $iface -d $ip -j DROP
|
||||
kill_tcp_connections $ip
|
||||
/sbin/ip addr del $ip/$maskbits dev $iface || failed=1
|
||||
/sbin/iptables -D INPUT -i $iface -d $ip -j DROP
|
||||
[ $failed = 0 ] || {
|
||||
echo "`/bin/date` Failed to del $ip on dev $iface"
|
||||
exit 1
|
||||
}
|
||||
/sbin/ip addr add $ip/32 dev lo >/dev/null 2>/dev/null
|
||||
|
||||
# flush our route cache
|
||||
echo 1 > /proc/sys/net/ipv4/route/flush
|
||||
@ -95,12 +148,21 @@ case $cmd in
|
||||
|
||||
monitor)
|
||||
[ -x /usr/sbin/ethtool ] && {
|
||||
cat $CTDB_PUBLIC_ADDRESSES | sed -e "s/^[^\t ]*[\t ]*//" -e "s/[\t ]*$//" | sort | uniq | while read IFACE; do
|
||||
/usr/sbin/ethtool $IFACE | grep 'Link detected: yes' > /dev/null || {
|
||||
echo "`date` ERROR: No link on the public network interface $IFACE"
|
||||
exit 1
|
||||
}
|
||||
done
|
||||
[ -z "$CTDB_PUBLIC_INTERFACE" ] || {
|
||||
/usr/sbin/ethtool $CTDB_PUBLIC_INTERFACE | grep 'Link detected: yes' > /dev/null || {
|
||||
echo "`date` ERROR: No link on the public network interface $CTDB_PUBLIC_INTERFACE"
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
cat $CTDB_PUBLIC_ADDRESSES | sed -e "s/^[^\t ]*[\t ]*//" -e "s/[\t ]*$//" |
|
||||
sort | uniq | while read IFACE; do
|
||||
[ -z "$IFACE" ] || {
|
||||
/usr/sbin/ethtool $IFACE | grep 'Link detected: yes' > /dev/null || {
|
||||
echo "`date` ERROR: No link on the public network interface $IFACE"
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
done
|
||||
}
|
||||
;;
|
||||
|
||||
|
@ -55,37 +55,7 @@ case $cmd in
|
||||
maskbits=$3
|
||||
|
||||
echo $ip >> /etc/ctdb/state/statd/restart
|
||||
|
||||
/bin/rm -f /etc/ctdb/state/statd/ip/$ip
|
||||
|
||||
# RST all tcp connections to the lockmanager
|
||||
[ ! -z "$LOCKD_TCPPORT" ] && {
|
||||
# RST all tcp connections used for NLM to ensure that they do
|
||||
# not survive in ESTABLISHED state across a failover/failback
|
||||
# and create an ack storm
|
||||
netstat -tn |egrep "^tcp.*\s+$ip:${LOCKD_TCPPORT}\s+.*ESTABLISHED" | awk '{print $4" "$5}' | while read dest src; do
|
||||
srcip=`echo $src | cut -d: -f1`
|
||||
srcport=`echo $src | cut -d: -f2`
|
||||
destip=`echo $dest | cut -d: -f1`
|
||||
destport=`echo $dest | cut -d: -f2`
|
||||
ctdb killtcp $srcip:$srcport $destip:$destport >/dev/null 2>&1
|
||||
# ctdb killtcp $destip:$destport $srcip:$srcport >/dev/null 2>&1
|
||||
done
|
||||
} > /dev/null 2>&1
|
||||
|
||||
|
||||
# RST the local side for all tcp connections used for NFS to ensure
|
||||
# that they do not survive in ESTABLISHED state across a
|
||||
# failover/failback and create an ack storm
|
||||
netstat -tn |egrep "^tcp.*\s+$ip:2049\s+.*ESTABLISHED" | awk '{print $4" "$5}' | while read dest src; do
|
||||
srcip=`echo $src | cut -d: -f1`
|
||||
srcport=`echo $src | cut -d: -f2`
|
||||
destip=`echo $dest | cut -d: -f1`
|
||||
destport=`echo $dest | cut -d: -f2`
|
||||
ctdb killtcp $srcip:$srcport $destip:$destport >/dev/null 2>&1
|
||||
# ctdb killtcp $destip:$destport $srcip:$srcport >/dev/null 2>&1
|
||||
done
|
||||
|
||||
exit 0
|
||||
;;
|
||||
|
||||
|
@ -66,11 +66,11 @@ ctdb_wait_tcp_ports() {
|
||||
all_ok=1
|
||||
for p in $wait_ports; do
|
||||
if [ -x /usr/bin/netcat ]; then
|
||||
/usr/bin/netcat -z 127.0.0.1 $p || all_ok=0
|
||||
/usr/bin/netcat -z 127.0.0.1 $p > /dev/null || all_ok=0
|
||||
elif [ -x /usr/bin/nc ]; then
|
||||
/usr/bin/nc -z 127.0.0.1 $p || all_ok=0
|
||||
/usr/bin/nc -z 127.0.0.1 $p > /dev/null || all_ok=0
|
||||
elif [ -x /usr/bin/netstat ]; then
|
||||
(/usr/bin/netstat -a -n | egrep "0.0.0.0:$p .*LISTEN") || all_ok=0
|
||||
(/usr/bin/netstat -a -n | egrep "0.0.0.0:$p\s*LISTEN" > /dev/null) || all_ok=0
|
||||
else
|
||||
echo "`date` - No tool to check tcp ports availabe. can not check in ctdb_wait_tcp_ports"
|
||||
return
|
||||
@ -157,11 +157,11 @@ ctdb_check_tcp_ports() {
|
||||
for p in $wait_ports; do
|
||||
all_ok=1
|
||||
if [ -x /usr/bin/netcat ]; then
|
||||
/usr/bin/netcat -z 127.0.0.1 $p || all_ok=0
|
||||
/usr/bin/netcat -z 127.0.0.1 $p > /dev/null || all_ok=0
|
||||
elif [ -x /usr/bin/nc ]; then
|
||||
/usr/bin/nc -z 127.0.0.1 $p || all_ok=0
|
||||
/usr/bin/nc -z 127.0.0.1 $p > /dev/null || all_ok=0
|
||||
elif [ -x /usr/bin/netstat ]; then
|
||||
(/usr/bin/netstat -a -n | egrep "0.0.0.0:$p .*LISTEN") || all_ok=0
|
||||
(/usr/bin/netstat -a -n | egrep "0.0.0.0:$p .*LISTEN" > /dev/null ) || all_ok=0
|
||||
fi
|
||||
[ $all_ok -eq 1 ] || {
|
||||
echo "`date` ERROR: $service_name tcp port $p is not responding"
|
||||
|
@ -1062,7 +1062,7 @@ int ctdb_ctrl_get_public_ips(struct ctdb_context *ctdb,
|
||||
|
||||
/* from takeover/system.c */
|
||||
int ctdb_sys_send_arp(const struct sockaddr_in *saddr, const char *iface);
|
||||
bool ctdb_sys_have_ip(struct sockaddr_in ip, bool *is_loopback, TALLOC_CTX *mem_ctx, char **ifname);
|
||||
bool ctdb_sys_have_ip(struct sockaddr_in ip);
|
||||
int ctdb_sys_send_tcp(int fd,
|
||||
const struct sockaddr_in *dest,
|
||||
const struct sockaddr_in *src,
|
||||
|
@ -210,7 +210,7 @@ int daemon_register_message_handler(struct ctdb_context *ctdb, uint32_t client_i
|
||||
DEBUG(0,(__location__ " Failed to register handler %llu in daemon\n",
|
||||
(unsigned long long)srvid));
|
||||
} else {
|
||||
DEBUG(2,(__location__ " Registered message handler for srvid=%llu\n",
|
||||
DEBUG(1,(__location__ " Registered message handler for srvid=%llu\n",
|
||||
(unsigned long long)srvid));
|
||||
}
|
||||
|
||||
@ -218,7 +218,7 @@ int daemon_register_message_handler(struct ctdb_context *ctdb, uint32_t client_i
|
||||
if ((srvid & 0xFFFFFFFF) == srvid &&
|
||||
kill(srvid, 0) == 0) {
|
||||
client->pid = srvid;
|
||||
DEBUG(3,(__location__ " Registered PID %u for client %u\n",
|
||||
DEBUG(1,(__location__ " Registered PID %u for client %u\n",
|
||||
(unsigned)client->pid, client_id));
|
||||
}
|
||||
return res;
|
||||
|
@ -42,6 +42,7 @@ struct ctdb_recoverd {
|
||||
struct timeval first_recover_time;
|
||||
struct ban_state **banned_nodes;
|
||||
struct timeval priority_time;
|
||||
bool need_takeover_run;
|
||||
};
|
||||
|
||||
#define CONTROL_TIMEOUT() timeval_current_ofs(ctdb->tunable.recover_timeout, 0)
|
||||
@ -904,6 +905,7 @@ static int do_recovery(struct ctdb_recoverd *rec,
|
||||
if enabled, tell nodes to takeover their public IPs
|
||||
*/
|
||||
if (ctdb->vnn) {
|
||||
rec->need_takeover_run = false;
|
||||
ret = ctdb_takeover_run(ctdb, nodemap);
|
||||
if (ret != 0) {
|
||||
DEBUG(0, (__location__ " Unable to setup public takeover addresses\n"));
|
||||
@ -1154,6 +1156,7 @@ static void monitor_handler(struct ctdb_context *ctdb, uint64_t srvid,
|
||||
TALLOC_CTX *tmp_ctx;
|
||||
uint32_t changed_flags;
|
||||
int i;
|
||||
struct ctdb_recoverd *rec = talloc_get_type(private_data, struct ctdb_recoverd);
|
||||
|
||||
if (data.dsize != sizeof(*c)) {
|
||||
DEBUG(0,(__location__ "Invalid data in ctdb_node_flag_change\n"));
|
||||
@ -1212,13 +1215,7 @@ static void monitor_handler(struct ctdb_context *ctdb, uint64_t srvid,
|
||||
during recovery
|
||||
*/
|
||||
if (changed_flags & NODE_FLAGS_DISABLED) {
|
||||
ret = ctdb_takeover_run(ctdb, nodemap);
|
||||
if (ret != 0) {
|
||||
DEBUG(0, (__location__ " Unable to setup public takeover addresses\n"));
|
||||
}
|
||||
/* send a message to all clients telling them that the
|
||||
cluster has been reconfigured */
|
||||
ctdb_send_message(ctdb, CTDB_BROADCAST_CONNECTED, CTDB_SRVID_RECONFIGURE, tdb_null);
|
||||
rec->need_takeover_run = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1419,7 +1416,6 @@ static void monitor_cluster(struct ctdb_context *ctdb)
|
||||
struct ctdb_vnn_map *vnnmap=NULL;
|
||||
struct ctdb_vnn_map *remote_vnnmap=NULL;
|
||||
int i, j, ret;
|
||||
bool need_takeover_run;
|
||||
struct ctdb_recoverd *rec;
|
||||
|
||||
rec = talloc_zero(ctdb, struct ctdb_recoverd);
|
||||
@ -1444,8 +1440,6 @@ static void monitor_cluster(struct ctdb_context *ctdb)
|
||||
ctdb_set_message_handler(ctdb, CTDB_SRVID_UNBAN_NODE, unban_handler, rec);
|
||||
|
||||
again:
|
||||
need_takeover_run = false;
|
||||
|
||||
if (mem_ctx) {
|
||||
talloc_free(mem_ctx);
|
||||
mem_ctx = NULL;
|
||||
@ -1538,7 +1532,7 @@ again:
|
||||
/* if we are not the recmaster then we do not need to check
|
||||
if recovery is needed
|
||||
*/
|
||||
if (pnn!=recmaster) {
|
||||
if (pnn != recmaster) {
|
||||
goto again;
|
||||
}
|
||||
|
||||
@ -1658,7 +1652,7 @@ again:
|
||||
matches in this code) */
|
||||
if (nodemap->nodes[j].flags != remote_nodemap->nodes[j].flags) {
|
||||
nodemap->nodes[j].flags = remote_nodemap->nodes[j].flags;
|
||||
need_takeover_run = true;
|
||||
rec->need_takeover_run = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1746,10 +1740,13 @@ again:
|
||||
}
|
||||
|
||||
/* we might need to change who has what IP assigned */
|
||||
if (need_takeover_run && ctdb->vnn) {
|
||||
if (rec->need_takeover_run) {
|
||||
rec->need_takeover_run = false;
|
||||
ret = ctdb_takeover_run(ctdb, nodemap);
|
||||
if (ret != 0) {
|
||||
DEBUG(0, (__location__ " Unable to setup public takeover addresses\n"));
|
||||
DEBUG(0, (__location__ " Unable to setup public takeover addresses - starting recovery\n"));
|
||||
do_recovery(rec, mem_ctx, pnn, num_active, nodemap,
|
||||
vnnmap, nodemap->nodes[j].pnn);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -205,29 +205,22 @@ int32_t ctdb_control_takeover_ip(struct ctdb_context *ctdb,
|
||||
TDB_DATA indata,
|
||||
bool *async_reply)
|
||||
{
|
||||
TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
|
||||
int ret;
|
||||
struct takeover_callback_state *state;
|
||||
struct ctdb_public_ip *pip = (struct ctdb_public_ip *)indata.dptr;
|
||||
struct ctdb_vnn *vnn;
|
||||
bool have_ip, is_loopback;
|
||||
char *ifname = NULL;
|
||||
|
||||
/* update out vnn list */
|
||||
vnn = find_public_ip_vnn(ctdb, pip->sin);
|
||||
if (vnn == NULL) {
|
||||
DEBUG(0,("takeoverip called for an ip '%s' that is not a public address\n",
|
||||
inet_ntoa(pip->sin.sin_addr)));
|
||||
talloc_free(tmp_ctx);
|
||||
return 0;
|
||||
}
|
||||
vnn->pnn = pip->pnn;
|
||||
|
||||
/* if our kernel already has this IP, do nothing */
|
||||
have_ip = ctdb_sys_have_ip(pip->sin, &is_loopback, tmp_ctx, &ifname);
|
||||
/* if we have the ip and it is not set to a loopback address */
|
||||
if (have_ip && !is_loopback) {
|
||||
talloc_free(tmp_ctx);
|
||||
if (ctdb_sys_have_ip(pip->sin)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -257,7 +250,6 @@ int32_t ctdb_control_takeover_ip(struct ctdb_context *ctdb,
|
||||
if (ret != 0) {
|
||||
DEBUG(0,(__location__ " Failed to takeover IP %s on interface %s\n",
|
||||
inet_ntoa(pip->sin.sin_addr), vnn->iface));
|
||||
talloc_free(tmp_ctx);
|
||||
talloc_free(state);
|
||||
return -1;
|
||||
}
|
||||
@ -265,7 +257,6 @@ int32_t ctdb_control_takeover_ip(struct ctdb_context *ctdb,
|
||||
/* tell ctdb_control.c that we will be replying asynchronously */
|
||||
*async_reply = true;
|
||||
|
||||
talloc_free(tmp_ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -276,11 +267,17 @@ static void release_kill_clients(struct ctdb_context *ctdb, struct sockaddr_in i
|
||||
{
|
||||
struct ctdb_client_ip *ip;
|
||||
|
||||
DEBUG(1,("release_kill_clients for ip %s\n", inet_ntoa(in.sin_addr)));
|
||||
|
||||
for (ip=ctdb->client_ip_list; ip; ip=ip->next) {
|
||||
DEBUG(2,("checking for client %u with IP %s\n",
|
||||
ip->client_id, inet_ntoa(ip->ip.sin_addr)));
|
||||
if (ctdb_same_ip(&ip->ip, &in)) {
|
||||
struct ctdb_client *client = ctdb_reqid_find(ctdb,
|
||||
ip->client_id,
|
||||
struct ctdb_client);
|
||||
DEBUG(1,("matched client %u with IP %s and pid %u\n",
|
||||
ip->client_id, inet_ntoa(ip->ip.sin_addr), client->pid));
|
||||
if (client->pid != 0) {
|
||||
DEBUG(0,(__location__ " Killing client pid %u for IP %s on client_id %u\n",
|
||||
(unsigned)client->pid, inet_ntoa(in.sin_addr),
|
||||
@ -328,30 +325,28 @@ int32_t ctdb_control_release_ip(struct ctdb_context *ctdb,
|
||||
TDB_DATA indata,
|
||||
bool *async_reply)
|
||||
{
|
||||
TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
|
||||
int ret;
|
||||
struct takeover_callback_state *state;
|
||||
struct ctdb_public_ip *pip = (struct ctdb_public_ip *)indata.dptr;
|
||||
struct ctdb_vnn *vnn;
|
||||
bool have_ip, is_loopback;
|
||||
char *ifname = NULL;
|
||||
|
||||
/* update our vnn list */
|
||||
vnn = find_public_ip_vnn(ctdb, pip->sin);
|
||||
if (vnn == NULL) {
|
||||
DEBUG(0,("releaseip called for an ip '%s' that is not a public address\n",
|
||||
inet_ntoa(pip->sin.sin_addr)));
|
||||
talloc_free(tmp_ctx);
|
||||
return 0;
|
||||
}
|
||||
vnn->pnn = pip->pnn;
|
||||
|
||||
have_ip = ctdb_sys_have_ip(pip->sin, &is_loopback, tmp_ctx, &ifname);
|
||||
if ( (!have_ip) || is_loopback) {
|
||||
DEBUG(0,("Redundant release of IP %s/%u on interface %s (ip not held)\n",
|
||||
/* stop any previous arps */
|
||||
talloc_free(vnn->takeover_ctx);
|
||||
vnn->takeover_ctx = NULL;
|
||||
|
||||
if (!ctdb_sys_have_ip(pip->sin)) {
|
||||
DEBUG(2,("Redundant release of IP %s/%u on interface %s (ip not held)\n",
|
||||
inet_ntoa(pip->sin.sin_addr), vnn->public_netmask_bits,
|
||||
vnn->iface));
|
||||
talloc_free(tmp_ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -359,10 +354,6 @@ int32_t ctdb_control_release_ip(struct ctdb_context *ctdb,
|
||||
inet_ntoa(pip->sin.sin_addr), vnn->public_netmask_bits,
|
||||
vnn->iface));
|
||||
|
||||
/* stop any previous arps */
|
||||
talloc_free(vnn->takeover_ctx);
|
||||
vnn->takeover_ctx = NULL;
|
||||
|
||||
state = talloc(ctdb, struct takeover_callback_state);
|
||||
CTDB_NO_MEMORY(ctdb, state);
|
||||
|
||||
@ -385,15 +376,12 @@ int32_t ctdb_control_release_ip(struct ctdb_context *ctdb,
|
||||
if (ret != 0) {
|
||||
DEBUG(0,(__location__ " Failed to release IP %s on interface %s\n",
|
||||
inet_ntoa(pip->sin.sin_addr), vnn->iface));
|
||||
talloc_free(tmp_ctx);
|
||||
talloc_free(state);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* tell the control that we will be reply asynchronously */
|
||||
*async_reply = true;
|
||||
|
||||
talloc_free(tmp_ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -767,7 +755,7 @@ try_again:
|
||||
}
|
||||
}
|
||||
if (maxnode == -1) {
|
||||
DEBUG(0,(__location__ " Could not find maxnode. May not be able to server ip '%s'\n", inet_ntoa(tmp_ip->sin.sin_addr)));
|
||||
DEBUG(0,(__location__ " Could not find maxnode. May not be able to serve ip '%s'\n", inet_ntoa(tmp_ip->sin.sin_addr)));
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -845,8 +833,8 @@ try_again:
|
||||
ip.sin.sin_addr = tmp_ip->sin.sin_addr;
|
||||
|
||||
ret = ctdb_ctrl_takeover_ip(ctdb, TAKEOVER_TIMEOUT(),
|
||||
tmp_ip->pnn,
|
||||
&ip);
|
||||
tmp_ip->pnn,
|
||||
&ip);
|
||||
if (ret != 0) {
|
||||
DEBUG(0,("Failed asking vnn %u to take over IP %s\n",
|
||||
tmp_ip->pnn,
|
||||
@ -866,6 +854,8 @@ try_again:
|
||||
*/
|
||||
static int ctdb_client_ip_destructor(struct ctdb_client_ip *ip)
|
||||
{
|
||||
DEBUG(3,("destroying client tcp for %s:%u (client_id %u)\n",
|
||||
inet_ntoa(ip->ip.sin_addr), ntohs(ip->ip.sin_port), ip->client_id));
|
||||
DLIST_REMOVE(ip->ctdb->client_ip_list, ip);
|
||||
return 0;
|
||||
}
|
||||
@ -888,10 +878,21 @@ int32_t ctdb_control_tcp_client(struct ctdb_context *ctdb, uint32_t client_id,
|
||||
|
||||
vnn = find_public_ip_vnn(ctdb, p->dest);
|
||||
if (vnn == NULL) {
|
||||
DEBUG(3,("Could not add client IP %s. This is not a public address.\n", inet_ntoa(p->dest.sin_addr)));
|
||||
if (ntohl(p->dest.sin_addr.s_addr) != INADDR_LOOPBACK) {
|
||||
DEBUG(0,("Could not add client IP %s. This is not a public address.\n",
|
||||
inet_ntoa(p->dest.sin_addr)));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (vnn->pnn != ctdb->pnn) {
|
||||
DEBUG(0,("Attempt to register tcp client for IP %s we don't hold - failing (client_id %u pid %u)\n",
|
||||
inet_ntoa(p->dest.sin_addr),
|
||||
client_id, client->pid));
|
||||
/* failing this call will tell smbd to die */
|
||||
return -1;
|
||||
}
|
||||
|
||||
ip = talloc(client, struct ctdb_client_ip);
|
||||
CTDB_NO_MEMORY(ctdb, ip);
|
||||
|
||||
@ -915,10 +916,10 @@ int32_t ctdb_control_tcp_client(struct ctdb_context *ctdb, uint32_t client_id,
|
||||
data.dptr = (uint8_t *)&t;
|
||||
data.dsize = sizeof(t);
|
||||
|
||||
DEBUG(2,("registered tcp client for %u->%s:%u\n",
|
||||
DEBUG(1,("registered tcp client for %u->%s:%u (client_id %u pid %u)\n",
|
||||
(unsigned)ntohs(p->dest.sin_port),
|
||||
inet_ntoa(p->src.sin_addr),
|
||||
(unsigned)ntohs(p->src.sin_port)));
|
||||
(unsigned)ntohs(p->src.sin_port), client_id, client->pid));
|
||||
|
||||
/* tell all nodes about this tcp connection */
|
||||
ret = ctdb_daemon_send_control(ctdb, CTDB_BROADCAST_CONNECTED, 0,
|
||||
@ -1128,21 +1129,17 @@ void ctdb_takeover_client_destructor_hook(struct ctdb_client *client)
|
||||
void ctdb_release_all_ips(struct ctdb_context *ctdb)
|
||||
{
|
||||
struct ctdb_vnn *vnn;
|
||||
TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
|
||||
bool have_ip, is_loopback;
|
||||
char *ifname = NULL;
|
||||
|
||||
for (vnn=ctdb->vnn;vnn;vnn=vnn->next) {
|
||||
have_ip = ctdb_sys_have_ip(vnn->public_address, &is_loopback, tmp_ctx, &ifname);
|
||||
if (have_ip && !is_loopback) {
|
||||
ctdb_event_script(ctdb, "releaseip %s %s %u",
|
||||
vnn->iface,
|
||||
inet_ntoa(vnn->public_address.sin_addr),
|
||||
vnn->public_netmask_bits);
|
||||
release_kill_clients(ctdb, vnn->public_address);
|
||||
if (!ctdb_sys_have_ip(vnn->public_address)) {
|
||||
continue;
|
||||
}
|
||||
ctdb_event_script(ctdb, "releaseip %s %s %u",
|
||||
vnn->iface,
|
||||
inet_ntoa(vnn->public_address.sin_addr),
|
||||
vnn->public_netmask_bits);
|
||||
release_kill_clients(ctdb, vnn->public_address);
|
||||
}
|
||||
talloc_free(tmp_ctx);
|
||||
}
|
||||
|
||||
|
||||
|
@ -46,6 +46,7 @@ static struct {
|
||||
const char *logfile;
|
||||
const char *recovery_lock_file;
|
||||
const char *db_dir;
|
||||
const char *public_interface;
|
||||
int no_setsched;
|
||||
} options = {
|
||||
.nlist = ETCDIR "/ctdb/nodes",
|
||||
@ -100,6 +101,7 @@ int main(int argc, const char *argv[])
|
||||
POPT_CTDB_CMDLINE
|
||||
{ "interactive", 'i', POPT_ARG_NONE, &interactive, 0, "don't fork", NULL },
|
||||
{ "public-addresses", 0, POPT_ARG_STRING, &options.public_address_list, 0, "public address list file", "filename" },
|
||||
{ "public-interface", 0, POPT_ARG_STRING, &options.public_interface, 0, "public interface", "interface"},
|
||||
{ "event-script-dir", 0, POPT_ARG_STRING, &options.event_script_dir, 0, "event script directory", "dirname" },
|
||||
{ "logfile", 0, POPT_ARG_STRING, &options.logfile, 0, "log file location", "filename" },
|
||||
{ "nlist", 0, POPT_ARG_STRING, &options.nlist, 0, "node list file", "filename" },
|
||||
@ -198,6 +200,11 @@ int main(int argc, const char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
if (options.public_interface) {
|
||||
ctdb->default_public_interface = talloc_strdup(ctdb, options.public_interface);
|
||||
CTDB_NO_MEMORY(ctdb, ctdb->default_public_interface);
|
||||
}
|
||||
|
||||
if (options.public_address_list) {
|
||||
ret = ctdb_set_public_addresses(ctdb, options.public_address_list);
|
||||
if (ret == -1) {
|
||||
|
@ -375,7 +375,7 @@ static int kill_tcp(struct ctdb_context *ctdb, int argc, const char **argv)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -123,6 +123,7 @@ show_all "/sbin/ip addr list"
|
||||
show_all "/sbin/route -n"
|
||||
show_all "crontab -l"
|
||||
show_all "sysctl -a"
|
||||
show_all "/sbin/iptables -L -n"
|
||||
|
||||
[ -d /usr/lpp/mmfs ] && {
|
||||
cat <<EOF
|
||||
|
Loading…
Reference in New Issue
Block a user