try to work around the broken gethostbyaddr more thoroughly
[tests.git] / system / PlcapiUrlScanner.py
1 #!/usr/bin/env python
2 #
3 # this checks various forms of URLS for reaching a PLCAPI
4 # i.e. with http:// or https:// (only the latter is expected to work)
5 # with or without a trailing slash
6 # using a hostname or an IP
7
8 import socket
9 import xmlrpc.client
10 import traceback
11 import ssl
12
13 from gethostbyaddr import workaround_gethostbyaddr
14
15
16 class PlcapiUrlScanner:
17
18     # turns out the config has an ip but no name..
19     def __init__ (self, auth, hostname=None, ip=None, verbose=False):
20         self.auth = auth
21         if not hostname and not ip:
22             raise Exception("PlcapiUrlScanner needs _some_ input")
23         if not hostname:
24             hostname = workaround_gethostbyaddr(ip)
25         elif hostname and not ip:
26             try:
27                 ip = socket.gethostbyname(hostname)
28             except:
29                 hostname = "{}.pl.sophia.inria.fr".format(hostname)
30                 ip = socket.gethostbyname(hostname)
31         self.hostname = hostname
32         self.ip = ip
33         self.verbose = verbose
34
35     def try_url (self, url):
36         try:
37             proxy = xmlrpc.client.ServerProxy(url, verbose=self.verbose, allow_none=True,
38                                               context=ssl._create_unverified_context())
39             nodes = proxy.GetNodes(self.auth)
40             print('YES', url)
41             return True
42         except xmlrpc.client.ProtocolError as e:
43             print('... (http error {})'.format(e.errcode), url)
44             return False
45         except Exception as e:
46             print('---', type(e).__name__, url, e)
47             if self.verbose:
48                 traceback.print_exc()
49             return False
50
51     def try_url_required (self, url, required):
52         result = self.try_url(url)
53         if required and not result:
54             return False
55         else:
56             return True
57
58     def scan(self):
59         overall = True
60         for protocol in ['http','https']:
61             for dest in [ self.hostname, self.ip ]:
62                 for port in [ '', ':80', ':443']:
63                     for path in ['PLCAPI', 'PLCAPI/']:
64                         if protocol=='http' and port==':443':
65                             continue
66                         if protocol=='https' and port==':80':
67                             continue
68                         required = (protocol=='https') and (path=='PLCAPI/')
69                         url="{}://{}{}/{}".format(protocol, dest, port, path)
70                         if not self.try_url_required (url,required):
71                             overall=False
72         return overall
73
74 from optparse import OptionParser
75 import sys
76
77 auth={'AuthMethod':'password','Username':'root@test.onelab.eu','AuthString':'test++'}
78
79 def main ():
80     usage = "%prog hostname"
81     parser = OptionParser()
82     parser.add_option("-v", "--verbose", dest='verbose', action='store_true', default=False)
83     (options,args) = parser.parse_args()
84     if len(args) != 1:
85         parser.print_help()
86         sys.exit(1)
87     hostname = args[0]
88     success = PlcapiUrlScanner (auth=auth, hostname=hostname,verbose=options.verbose).scan()
89     sys.exit(0 if success else -1)
90
91 if __name__ == '__main__':
92     main()