Spinlock until instance has gotten its ip address from Openstack - python

Im writing a program which automatically creates servers in openstack when needed. The problem is that I want the program to wait until the instance has gotten its ip address before proceeding. If the instance has not gotten its ip, novaclient will throw an exception and the object will die. Using the sleep function makes it work, but I dont want that to be the permanent solution.
ipAddress = None
try:
instance = nova.servers.create(name=self.hostName, image=image,
flavor=flavor, key_name="mykey",
nics=nics)
while(ipAddress == None): #<---Something like this, just actually working
for network in instance.networks['my_net']:
if re.match('\d+\.\d+\.\d+\.\d+', network):
self.ipAddress = network
break
print 'The server is waiting at IP address {0}.'.format(self.ipAddress)
except:
print "could not create webserver"
#WebManager.exception(hostname)
finally:
print("Execution Completed")
self.addToLoadbalancer()
Is there a way to write a sort of spinlock or similar that will wait unntil the server have gotten its ip?
Any tips would be great.

I managed to fix the issue. It turned out it was hard to detect when the machine was ready by using only novaclient. By using nova list I managed to get the ip address.
while 1 == 1:
result = getbash("nova list" + " | grep " + hostname + \\
" | awk '{print $12}'").split('=')
if re.match('\d+\.\d+\.\d+\.\d+', result[-1]):
self.ipAddress = result[-1]
print 'The server is waiting at IP address {0}.'.format(self.ipAddress)
break
sleep(1)
This code queries for the hostname and checks if the instance has recieved an ip address. The getbash() function is a simple subprocess function which return the output of subprocess.Popen(command,stdout=subprocess.PIPE, shell=True)

Related

Get ping time in python

I have made a program that tells me if I am connected to the internet or not. Now I want it to ping www.google.com and show me the ping time in ms. I don't want to use any 3rd party software or download anything.
Edit:
My code is:
def is_connected():
try:
# see if we can resolve the host name -- tells us if there is
# a DNS listening
host = socket.gethostbyname(REMOTE_SERVER)
# connect to the host -- tells us if the host is actually
# reachable
s = socket.create_connection((host, 80), 2)
return True
except:
pass
return False
The above code just tells me if I am connected to the internet.
What I want is a simple way to show the ping of a website.
This is not a duplicate as it doesn't answer my question.
A ping is not the same thing as a HTTP connection! The first is a low level ICMP packet that is used to test connectiviy and find round-trip time mainly on a local network. It is generaly not used on broad internet, because for security reasons it is often blocked by firewall and external routers.
If you want to know the time necessary to establish the connexion to a server, do what you would in real world: look at your watch, do the job, look again at your watch to see elapsed time. In Python it gives
#import time
...
def connect_time():
try:
# see if we can resolve the host name -- tells us if there is
# a DNS listening
host = socket.gethostbyname(REMOTE_SERVER)
# connect to the host -- tells us if the host is actually
# reachable
before = time.clock() # from Python 3.3 and above use before = time.perf_counter()
s = socket.create_connection((host, 80), 2)
after = time.clock() # from Python 3.3 and above use after = time.perf_counter()
return after - before
except:
return -1

How to telnet and collect logs, Whenever the IP is alive/active?

PING:
import os
ip=1.1.1.1
o=os.system("ping "+ip)
time.sleep(10)
print(o)
if res == 0:
print(ip,"is active")
Telnet:
tn = telnetlib.Telnet(IP)
tn.write(command+"\r\n")
f=open(filename,w)
while True:
response = tn.read_until("\n")
f.write(response)
Here, In between IP goes down. During that time i need to ping that IP & whenever it comes up i need to start collecting logs again. How can i do this ?
Actually, I need to collect logs through telnet (which is indefinite). I could able to do it. During this process, IP from which i'm collecting logs goes down. So, I need to track on this IP (Ping). Whenever IP comes up again, I've to start collecting the logs again. It would be great, if you can help me on this.
I found the solution:
tn=telnetlib.Telnet(IP)
tn.write(command+"\r\n")
f=open(filename,w)
while (os.system("ping -n 1 IP") == 0):
response = tn.read_until("\n")
f.write(response)
else:
call some module for telnetting again/goto
But, here is it possible to hide the console when we use (os.system(ping)). I know it can be done through subprocess. But since os.system is a one liner & very easy to verifY the result also.
Maybe pexpect is what you're looking for?
This snippet will start a ping process, and block until it sees the output "bytes from" or until it times out (1 minute by default):
import pexpect
def wait_until_online(host, timeout=60):
child = pexpect.spawn("ping %s" % host)
child.expect("bytes from", timeout)

How to keep a python 3 script (Bot) running

(Not native English, sorry for probably broken English. I'm also a newbie at programming).
Hello, I'm trying to connect to a TeamSpeak server using the QueryServer to make a bot. After days of struggling with it... it works, with only 1 problem, and I'm stuck with that one.
If you need to check, this is the TeamSpeak API that I'm using: http://py-ts3.readthedocs.org/en/latest/api/query.html
And this is the summary of what actually happens in my script:
It connects.
It checks for channel ID (and it's own client ID)
It joins the channel
Script ends so it disconnects.
My question is: How can I make it doesn't disconnects? How can I make the script stay in a "waiting" state so it can read if someone types "hi bot" in the channel? All the code needed to read texts and answer to them seems easy to program, however I'm facing a problem where I can't keep the bot "running" since it closes the file as soon as it ends running the script.
More info:
I am using Python 3.4.1.
I tried learning Threading http://www.tutorialspoint.com/python/python_multithreading.htm but either M'm dumb or it doesn't work the way I though it would.
In the API there's a function named on_event that I would like to keep running all the time. The bot code should only be run once and then stay "waiting" until an event happens. How should i do that? No clue.
Code:
import ts3
import telnetlib
import time
class BotPrincipal:
def Conectar(ts3conn):
MiID = [i["client_id"] for i in ts3conn.whoami()]
ChannelToJoin = "[Pruebas] Bots"
ts3conn.on_event = BotPrincipal.EventHappened()
try:
BuscandoIDCanal = ts3conn.channelfind(pattern=ChannelToJoin)
IDCanal = [i["cid"] for i in BuscandoIDCanal]
if not IDCanal:
print("No channel found with that name")
return None
else:
MiID = str(MiID).replace("'", "")
MiID = str(MiID).replace("]", "")
MiID = str(MiID).replace("[", "")
IDCanal = str(IDCanal).replace("'", "")
IDCanal = str(IDCanal).replace("]", "")
IDCanal = str(IDCanal).replace("[", "")
print("ID de canal " + ChannelToJoin + ": " + IDCanal)
print("ID de cliente " + Nickname + ": " + MiID)
try:
print("Moving you into: " + ChannelToJoin)
ts3conn.clientmove(cid=IDCanal, clid=MiID) #entra al canal
try:
print("Asking for notifications from: " + ChannelToJoin)
ts3conn.servernotifyregister(event="channel", id_=IDCanal)
ts3conn.servernotifyregister(event="textchannel", id_=IDCanal)
except ts3.query.TS3QueryError:
print("You have no permission to use the telnet command: servernotifyregister")
print("------- Bot Listo -------")
except ts3.query.TS3QueryError:
print("You have no permission to use the telnet command: clientmove")
except ts3.query.TS3QueryError:
print("Error finding ID for " + ChannelToJoin + ". telnet: channelfind")
def EventHappened():
print("Doesn't work")
# Data needed #
USER = "thisisafakename"
PASS = "something"
HOST = "111.111.111.111"
PORT = 10011
SID = 1
if __name__ == "__main__":
with ts3.query.TS3Connection(HOST, PORT) as ts3conn:
ts3conn.login(client_login_name=USER, client_login_password=PASS)
ts3conn.use(sid=SID)
print("Connected to "+HOST)
BotPrincipal.Conectar(ts3conn)
From a quick glimpse at the API, it looks like you need to explicitly tell the ts3conn object to wait for events. There seem to be a few ways to do it, but ts3conn.recv(True) seems like the most obvious:
Blocks untill all unfetched responses have been received or forever, if recv_forever is true.
Presumably as each command comes in, it will call your on_event handler, then when you return from that it will go back to waiting forever for the next command.
I don't know if you need threads here or not, but the docs for recv_in_thread make it sound like you might:
Calls recv() in a thread. This is useful, if you used servernotifyregister and you expect to receive events.
You presumably want to get both servernotify events and also commands, and I guess the way this library is written you need threads for that? If so, just call ts3conn.recv_in_thread() instead of ts3conn.recv(True). (If you look at the source, all that does is start a background thread and call self.recv(True) on that thread.)

WOL from outside WAN

A while ago, I wrote [with some help from Google] a small WOL script to switch on the computers in my network. Here is the script:
exec /usr/bin/python -x "$0" "$#"
#
node_lst = [
'srv1 0a:1b:8c:0d:2e:7f',
'srv2 0A-0B-4C-8D-CE:3F',
]
#
import os,sys,string,commands
import struct, socket
import re,random
retval = 0
mac_addr = "mac_addr.txt"
X = '([a-zA-Z0-9]{2}[:|\-|.]?){5}[a-zA-Z0-9]{2}'
S = re.compile(r'\s+')
mmap = {}
## First argument 'None' in str.translate is new in 2.6.
## Previously, it was a string of 256 characters
if sys.version_info < (2, 6):
f1_arg = ''.join(chr(i) for i in xrange(256))
else:
f1_arg = None
## broadcast address
sysOS = "uname -s"
BSD = "ifconfig | grep -w broadcast | cut -d\ -f 6"
LNX = "ip -o addr show | grep -w inet | grep -e eth | cut -d\ -f 9"
#
if commands.getoutput(sysOS) == "Linux":
bCast = commands.getoutput(LNX)
elif commands.getoutput(sysOS) == "Darwin":
bCast = commands.getoutput(BSD)
else:
print "System not supported!!"
sys_exit()
def WakeOnLan(mac_address):
## Building the Wake-On-LAN "Magic Packet"...
## Pad the synchronization stream.
data = ''.join(['FFFFFFFFFFFF', mac_address * 20])
msg = ''
## Split up the hex values and pack.
for i in range(0, len(data), 2):
msg = ''.join([msg, struct.pack('B', int(data[i: i + 2], 16))])
## ...and send it to the broadcast address using UDP
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
s.sendto(msg, (bCast, 9))
s.close()
def sys_exit():
sys.stdout.flush()
sys.exit(1)
## check if hostname is provided
if len(sys.argv) != 2:
print "Usage: %s <hostname>" % sys.argv[0]
sys_exit()
for i in node_lst:
# strip off everything from first "#" [if] found
i = i.split('#',1)[0]
if not re.search(X, i):
continue
h = S.split(i,1)[0] ## host name
m = S.split(i,1)[-1] ## MAC address
mmap[h] = m.strip('\t|" "')
for j, k in mmap.iteritems():
if sys.argv[1] == j:
if not re.search(X.replace('zA-Z','fA-F'), k):
print "Invalid MAC address [",k,"]; nothing to do!!"
sys_exit()
else:
WakeOnLan(k.translate(f1_arg,':.-'))
print "WOL request has been sent to %s [%s]" % (j,k)
break
else:
print "Host [%s] doesn't exist!!" % sys.argv[1]
sys_exit()
Which works just fine from inside my home network (or LAN). How can I change the script to make it work for outside of my LAN? Any idea or suggestions? Cheers!!
This is not possible because WOL packets are broadcast packets (since you can't know who to send it too). Home routers and especially ISP/Network routers discard all broadcast packets because else everytime you run this one script all the computers on the entire internet would receive your package, which would cause quite some clutter.
What you of course can do is write a small application that is on a computer that is running inside the WAN in which you wish to turn on all computers, and then have that application send a WOL packet. However this would require a computer with internet access to be turned on at all times.
Configure your router to forward packets on a selection of 10 non-sequential ports to a machine on your LAN.
Devise some scheme based on say GMT Time + a hash to generate the port trigger sequence.
Have a python program (use scappy) on your command box inside that network listen for a series of syn packets.
The listener code would be analogous to the following tcpdump syntax:
sudo tcpdump -ni eth0 'tcp[tcpflags] & (tcp-syn) !=0'
Where it captures just syn packets.
Your program just sits there, waiting for the right syn sequence. When it receives the sequence, it runs your WOL script.
Done.
If you don't want to open ports, your script could instead poll a remote website, waiting for changes. Or listen for email fetched via email.
Taking your idea further, you could do fancy stuff like turn on your lights or boot up the TV.

Check if remote host is up in Python

How would I check if the remote host is up without having a port number? Is there any other way I could check other then using regular ping.
There is a possibility that the remote host might drop ping packets
This worked fine for me:
HOST_UP = True if os.system("ping -c 1 " + SOMEHOST) is 0 else False
A protocol-level PING is best, i.e., connecting to the server and interacting with it in a way that doesn't do real work. That's because it is the only real way to be sure that the service is up. An ICMP ECHO (a.k.a. ping) would only tell you that the other end's network interface is up, and even then might be blocked; FWIW, I have seen machines where all user processes were bricked but which could still be pinged. In these days of application servers, even getting a network connection might not be enough; what if the hosted app is down or otherwise non-functional? As I said, talking sweet-nothings to the actual service that you are interested in is the best, surest approach.
HOST_UP = True if os.system("ping -c 5 " + SOMEHOST.strip(";")) is 0 else False
to remove nasty script execution just add .strip(";")
-c 5
to increase the number of ping requests, if all pass than True
PS. Works only on Linux, on Windows always returns True
The best you can do is:
Try and connect on a known port (eg port 80 or 443 for HTTP or HTTPS); or
Ping the site. See Ping a site in Python?
Many sites block ICMP (the portocol used to ping sites) so you must know beforehand if the host in question has it enabled or not.
Connecting to a port tells you mixed information. It really depends on what you want to know. A port might be open but the site is effectively hung so you may get a false positive. A more stringent approach might involve using a HTTP library to execute a Web request against a site and see if you get back a response.
It really all depends on what you need to know.
Many firewalls are configured to drop ping packets without responding. In addition, some network adapters will respond to ICMP ping requests without input from the operating system network stack, which means the operating system might be down, but the host still responds to pings (usually you'll notice if you reboot the server, say, it'll start responding to pings some time before the OS actually comes up and other services start up).
The only way to be certain that a host is up is to actually try to connect to it via some well-known port (e.g. web server port 80).
Why do you need to know if the host is "up", maybe there's a better way to do it.
What about trying something that requires a RPC like a 'tasklist' command in conjunction with a ping?
I would use a port scanner. Original question states that you don't want to use a port. Then you need to specify which Protocol (Yes, this needs a port) you want to monitor: HTTP, VNC, SSH, etc. In case you want to monitor via ICMP you can use subprocess and control ping parameters, number of pings, timeout, size, etc.
import subprocess
try:
res = subprocess.Popen(['ping -t2 -c 4 110.10.0.254 &> /dev/null; echo $?'],shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
out, err = res.communicate()
out = out.rstrip()
err = err.rstrip()
print 'general.connectivity() Out: ' + out
print 'general.connectivity() Err: ' + err
if(out == "0"):
print 'general.connectivity() Successful'
return True
print 'general.connectivity() Failed'
return False
except Exception,e:
print 'general.connectivity() Exception'
return False
In case you want a port scanner
import socket
from functools import partial
from multiprocessing import Pool
from multiprocessing.pool import ThreadPool
from errno import ECONNREFUSED
NUM_CORES = 4
def portscan(target,port):
try:
# Create Socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socketTimeout = 5
s.settimeout(socketTimeout)
s.connect((target,port))
print('port_scanner.is_port_opened() ' + str(port) + " is opened")
return port
except socket.error as err:
if err.errno == ECONNREFUSED:
return False
# Wrapper function that calls portscanner
def scan_ports(server=None,port=None,portStart=None,portEnd=None,**kwargs):
p = Pool(NUM_CORES)
ping_host = partial(portscan, server)
if portStart and portStart:
return filter(bool, p.map(ping_host, range(portStart, portStart)))
else:
return filter(bool, p.map(ping_host, range(port, port+1)))
# Check if port is opened
def is_port_opened(server=None,port=None, **kwargs):
print('port_scanner.is_port_opened() Checking port...')
try:
# Add More proccesses in case we look in a range
pool = ThreadPool(processes=1)
try:
ports = list(scan_ports(server=server,port=int(port)))
print("port_scanner.is_port_opened() Port scanner done.")
if len(ports)!=0:
print('port_scanner.is_port_opened() ' + str(len(ports)) + " port(s) available.")
return True
else:
print('port_scanner.is_port_opened() port not opened: (' + port +')')
return False
except Exception, e:
raise
except Exception,e:
print e
raise

Categories

Resources