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
12 class PlcapiUrlScanner:
14 # turns out the config has an ip but no name..
15 def __init__ (self, auth, hostname=None, ip=None, verbose=False):
17 if not hostname and not ip:
18 raise Exception("PlcapiUrlScanner needs _some_ input")
22 ip = socket.gethostbyname(hostname)
24 hostname = "{}.pl.sophia.inria.fr".format(hostname)
25 ip = socket.gethostbyname(hostname)
27 hostname=socket.gethostbyaddr(ip)[0]
28 self.hostname = hostname
30 self.verbose = verbose
32 def try_url (self, url):
34 xmlrpc.client.ServerProxy (url, verbose=self.verbose, allow_none=True).GetNodes(self.auth)
37 except xmlrpc.client.ProtocolError as e:
38 print('... (http error {})'.format(e.errcode), url)
40 except Exception as e:
41 print('---', type(e).__name__, url, e)
46 def try_url_required (self, url, required):
47 result = self.try_url(url)
48 if required and not result:
55 for protocol in ['http','https']:
56 for dest in [ self.hostname, self.ip ]:
57 for port in [ '', ':80', ':443']:
58 for path in ['PLCAPI', 'PLCAPI/']:
59 if protocol=='http' and port==':443':
61 if protocol=='https' and port==':80':
63 required = (protocol=='https') and (path=='PLCAPI/')
64 url="{}://{}{}/{}".format(protocol, dest, port, path)
65 if not self.try_url_required (url,required):
69 from optparse import OptionParser
72 auth={'AuthMethod':'password','Username':'root@test.onelab.eu','AuthString':'test++'}
75 usage = "%prog hostname"
76 parser = OptionParser()
77 parser.add_option("-v", "--verbose", dest='verbose', action='store_true', default=False)
78 (options,args) = parser.parse_args()
83 success = PlcapiUrlScanner (auth=auth, hostname=hostname,verbose=options.verbose).scan()
84 sys.exit(0 if success else -1)
86 if __name__ == '__main__':