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
13 class PlcapiUrlScanner:
15 # turns out the config has an ip but no name..
16 def __init__ (self, auth, hostname=None, ip=None, verbose=False):
18 if not hostname and not ip:
19 raise Exception("PlcapiUrlScanner needs _some_ input")
23 ip = socket.gethostbyname(hostname)
25 hostname = "{}.pl.sophia.inria.fr".format(hostname)
26 ip = socket.gethostbyname(hostname)
28 hostname=socket.gethostbyaddr(ip)[0]
29 self.hostname = hostname
31 self.verbose = verbose
33 def try_url (self, url):
35 proxy = xmlrpc.client.ServerProxy(url, verbose=self.verbose, allow_none=True,
36 context=ssl._create_unverified_context())
37 nodes = proxy.GetNodes(self.auth)
40 except xmlrpc.client.ProtocolError as e:
41 print('... (http error {})'.format(e.errcode), url)
43 except Exception as e:
44 print('---', type(e).__name__, url, e)
49 def try_url_required (self, url, required):
50 result = self.try_url(url)
51 if required and not result:
58 for protocol in ['http','https']:
59 for dest in [ self.hostname, self.ip ]:
60 for port in [ '', ':80', ':443']:
61 for path in ['PLCAPI', 'PLCAPI/']:
62 if protocol=='http' and port==':443':
64 if protocol=='https' and port==':80':
66 required = (protocol=='https') and (path=='PLCAPI/')
67 url="{}://{}{}/{}".format(protocol, dest, port, path)
68 if not self.try_url_required (url,required):
72 from optparse import OptionParser
75 auth={'AuthMethod':'password','Username':'root@test.onelab.eu','AuthString':'test++'}
78 usage = "%prog hostname"
79 parser = OptionParser()
80 parser.add_option("-v", "--verbose", dest='verbose', action='store_true', default=False)
81 (options,args) = parser.parse_args()
86 success = PlcapiUrlScanner (auth=auth, hostname=hostname,verbose=options.verbose).scan()
87 sys.exit(0 if success else -1)
89 if __name__ == '__main__':