-1

I'm using Xen Hypervisor in ubuntu and I have a VM. When live-migrating vm to another host, the vm will be Unavailable from a range of about a few milliseconds to no more than a few seconds tops (depending on the environment). I need to be able to determine that short time as accurate as possible. so I need to 'somehow' check the vm say every 100 milliseconds. and the number of times in which I find the vm UNAVAILABLE continuously, multiplied by 100, will be the total milliseconds that my vm was down.

ping doesn't work since it's not being accurate and in case of vm being unavailable, ping command waits and retries sending ICMP packets and This spoils the goal to find out if the server is available in that EXACT CHECKING MOMENT. Plus I asked a question in here and the feedback was "don't use ping!"
so NO USING PING!

I need to write my own piece of code in python/perl/whathever which could do the job. How could I do that?

Community
  • 1
  • 1
Ali
  • 1,152
  • 2
  • 14
  • 33
  • maybe set short timeouts? then the result would come quicker – Lawrence Benson Sep 15 '15 at 13:50
  • @LawrenceBenson and what the exact command would be? – Ali Sep 15 '15 at 13:55
  • Maybe instead of checking the VM, let the VM send some confirmation about its existence. Something like a `SYN` packets being sent from the VM to some other machine running the server instance, that might be accepting the connections, logging them and dropping them. http://www.secdev.org/projects/scapy/doc/usage.html#tcp-port-scanning – ρss Sep 15 '15 at 14:04
  • Are you confusing the advice of "Don't use the ping(1) command" with "Don't use ICMP echo-request/echo-response packets"? I think ICMP is perfectly reasonable for this sort of problem; I just wouldn't use the ping command to send them. Maybe you want to stick with ICMP but use your own custom logic to send it. – LeoNerd Sep 16 '15 at 07:44

2 Answers2

1

ping doesn't work since it's not being accurate and in case of vm being unavailable, ping command waits and retries sending ICMP packets

That's the default, but you can tell it to only send one.

$ ping -q -c 1 9.9.9.9 >/dev/null

$ echo $?
1

$ ping -q -c 1 8.8.8.8 >/dev/null

$ echo $?
0

So

while ! ping -q -c 1 -W 1 x.x.x.x >/dev/null ; do true ; done

Plus I asked a question in here and the feedback was "don't use ping!" so NO USING PING!

Yet you asked for a (UDP-based) ping instead of a means of checking if the needed service is up.

ikegami
  • 367,544
  • 15
  • 269
  • 518
0

Here is a ZeroMQ UDP ping function adapted from UDP discovery, model 1 in Python by disabling broadcasting, pinging just one IP address, returning after the first reply, adding a counter to limit the number of ping attempts and adding extra error handling during message receive. The latter was done since one host in my net forcibly closed the connection causing socket.error: [Errno 10054]. It has been tested and found to work with Python 2.7.10 and 3.4.3.

from __future__ import print_function
import os
import socket
import sys
import time
import zmq

def udpping(ip):
    PING_PORT_NUMBER = 9999
    PING_MSG_SIZE = 1
    PING_INTERVAL = 1 # once per second, sets minimum initial timeout

    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
    # uncomment the line below for broadcast to 255.255.255.255
    # sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
    sock.bind(('', PING_PORT_NUMBER))
    poller = zmq.Poller()
    poller.register(sock, zmq.POLLIN)
    ping_at = time.time()

    limit = 5 # only limit ping attempts will be made
    count = 0
    while True:
        count += 1
        timeout = ping_at - time.time()
        if timeout < 0:
            timeout = 0
        try:
            events = dict(poller.poll(1000* timeout))
        except KeyboardInterrupt:
            return (1,None,None)
        try:
            if sock.fileno() in events:
                msg, addrinfo = sock.recvfrom(PING_MSG_SIZE)
                return (2,"found %s:%d" % addrinfo,None)
        except socket.error as e:
            return (3,'error during msg receive:',e)
        if time.time() >= ping_at:
            # the line below is for broadcasting
            # sock.sendto(b'!', 0, ("255.255.255.255", PING_PORT_NUMBER))
            sock.sendto(b'!', 0, (ip, PING_PORT_NUMBER))
            ping_at = time.time() + PING_INTERVAL
        if count == limit:
            return (4,limit,None)

ip = '192.168.159.21'
c,m,e = udpping(ip)

Below is shown output handling. For binary decision, the ping succeeded only if c == 2.

if c == 1:
    print('ping attempt stopped by KeyboardInterrupt')
elif c == 2:
    print(m)
elif c == 3:
    print(m,e)
elif c == 4:
    print('no response from',ip,'after',m,'attempts')

# prints 'found 192.168.159.21:9999' immediately in my net