PageRenderTime 41ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/monitor_batch/pymodules/python2.7/lib/python/ipython-2.2.0-py2.7.egg/IPython/parallel/engine/engine.py

https://gitlab.com/pooja043/Globus_Docker_4
Python | 305 lines | 267 code | 2 blank | 36 comment | 3 complexity | b02307b33df89ed03476c61f25852c8f MD5 | raw file
  1. """A simple engine that talks to a controller over 0MQ.
  2. it handles registration, etc. and launches a kernel
  3. connected to the Controller's Schedulers.
  4. Authors:
  5. * Min RK
  6. """
  7. #-----------------------------------------------------------------------------
  8. # Copyright (C) 2010-2011 The IPython Development Team
  9. #
  10. # Distributed under the terms of the BSD License. The full license is in
  11. # the file COPYING, distributed as part of this software.
  12. #-----------------------------------------------------------------------------
  13. from __future__ import print_function
  14. import sys
  15. import time
  16. from getpass import getpass
  17. import zmq
  18. from zmq.eventloop import ioloop, zmqstream
  19. from IPython.external.ssh import tunnel
  20. # internal
  21. from IPython.utils.localinterfaces import localhost
  22. from IPython.utils.traitlets import (
  23. Instance, Dict, Integer, Type, Float, Integer, Unicode, CBytes, Bool
  24. )
  25. from IPython.utils.py3compat import cast_bytes
  26. from IPython.parallel.controller.heartmonitor import Heart
  27. from IPython.parallel.factory import RegistrationFactory
  28. from IPython.parallel.util import disambiguate_url
  29. from IPython.kernel.zmq.session import Message
  30. from IPython.kernel.zmq.ipkernel import Kernel
  31. from IPython.kernel.zmq.kernelapp import IPKernelApp
  32. class EngineFactory(RegistrationFactory):
  33. """IPython engine"""
  34. # configurables:
  35. out_stream_factory=Type('IPython.kernel.zmq.iostream.OutStream', config=True,
  36. help="""The OutStream for handling stdout/err.
  37. Typically 'IPython.kernel.zmq.iostream.OutStream'""")
  38. display_hook_factory=Type('IPython.kernel.zmq.displayhook.ZMQDisplayHook', config=True,
  39. help="""The class for handling displayhook.
  40. Typically 'IPython.kernel.zmq.displayhook.ZMQDisplayHook'""")
  41. location=Unicode(config=True,
  42. help="""The location (an IP address) of the controller. This is
  43. used for disambiguating URLs, to determine whether
  44. loopback should be used to connect or the public address.""")
  45. timeout=Float(5.0, config=True,
  46. help="""The time (in seconds) to wait for the Controller to respond
  47. to registration requests before giving up.""")
  48. max_heartbeat_misses=Integer(50, config=True,
  49. help="""The maximum number of times a check for the heartbeat ping of a
  50. controller can be missed before shutting down the engine.
  51. If set to 0, the check is disabled.""")
  52. sshserver=Unicode(config=True,
  53. help="""The SSH server to use for tunneling connections to the Controller.""")
  54. sshkey=Unicode(config=True,
  55. help="""The SSH private key file to use when tunneling connections to the Controller.""")
  56. paramiko=Bool(sys.platform == 'win32', config=True,
  57. help="""Whether to use paramiko instead of openssh for tunnels.""")
  58. # not configurable:
  59. connection_info = Dict()
  60. user_ns = Dict()
  61. id = Integer(allow_none=True)
  62. registrar = Instance('zmq.eventloop.zmqstream.ZMQStream')
  63. kernel = Instance(Kernel)
  64. hb_check_period=Integer()
  65. # States for the heartbeat monitoring
  66. # Initial values for monitored and pinged must satisfy "monitored > pinged == False" so that
  67. # during the first check no "missed" ping is reported. Must be floats for Python 3 compatibility.
  68. _hb_last_pinged = 0.0
  69. _hb_last_monitored = 0.0
  70. _hb_missed_beats = 0
  71. # The zmq Stream which receives the pings from the Heart
  72. _hb_listener = None
  73. bident = CBytes()
  74. ident = Unicode()
  75. def _ident_changed(self, name, old, new):
  76. self.bident = cast_bytes(new)
  77. using_ssh=Bool(False)
  78. def __init__(self, **kwargs):
  79. super(EngineFactory, self).__init__(**kwargs)
  80. self.ident = self.session.session
  81. def init_connector(self):
  82. """construct connection function, which handles tunnels."""
  83. self.using_ssh = bool(self.sshkey or self.sshserver)
  84. if self.sshkey and not self.sshserver:
  85. # We are using ssh directly to the controller, tunneling localhost to localhost
  86. self.sshserver = self.url.split('://')[1].split(':')[0]
  87. if self.using_ssh:
  88. if tunnel.try_passwordless_ssh(self.sshserver, self.sshkey, self.paramiko):
  89. password=False
  90. else:
  91. password = getpass("SSH Password for %s: "%self.sshserver)
  92. else:
  93. password = False
  94. def connect(s, url):
  95. url = disambiguate_url(url, self.location)
  96. if self.using_ssh:
  97. self.log.debug("Tunneling connection to %s via %s", url, self.sshserver)
  98. return tunnel.tunnel_connection(s, url, self.sshserver,
  99. keyfile=self.sshkey, paramiko=self.paramiko,
  100. password=password,
  101. )
  102. else:
  103. return s.connect(url)
  104. def maybe_tunnel(url):
  105. """like connect, but don't complete the connection (for use by heartbeat)"""
  106. url = disambiguate_url(url, self.location)
  107. if self.using_ssh:
  108. self.log.debug("Tunneling connection to %s via %s", url, self.sshserver)
  109. url,tunnelobj = tunnel.open_tunnel(url, self.sshserver,
  110. keyfile=self.sshkey, paramiko=self.paramiko,
  111. password=password,
  112. )
  113. return str(url)
  114. return connect, maybe_tunnel
  115. def register(self):
  116. """send the registration_request"""
  117. self.log.info("Registering with controller at %s"%self.url)
  118. ctx = self.context
  119. connect,maybe_tunnel = self.init_connector()
  120. reg = ctx.socket(zmq.DEALER)
  121. reg.setsockopt(zmq.IDENTITY, self.bident)
  122. connect(reg, self.url)
  123. self.registrar = zmqstream.ZMQStream(reg, self.loop)
  124. content = dict(uuid=self.ident)
  125. self.registrar.on_recv(lambda msg: self.complete_registration(msg, connect, maybe_tunnel))
  126. # print (self.session.key)
  127. self.session.send(self.registrar, "registration_request", content=content)
  128. def _report_ping(self, msg):
  129. """Callback for when the heartmonitor.Heart receives a ping"""
  130. #self.log.debug("Received a ping: %s", msg)
  131. self._hb_last_pinged = time.time()
  132. def complete_registration(self, msg, connect, maybe_tunnel):
  133. # print msg
  134. self._abort_dc.stop()
  135. ctx = self.context
  136. loop = self.loop
  137. identity = self.bident
  138. idents,msg = self.session.feed_identities(msg)
  139. msg = self.session.unserialize(msg)
  140. content = msg['content']
  141. info = self.connection_info
  142. def url(key):
  143. """get zmq url for given channel"""
  144. return str(info["interface"] + ":%i" % info[key])
  145. if content['status'] == 'ok':
  146. self.id = int(content['id'])
  147. # launch heartbeat
  148. # possibly forward hb ports with tunnels
  149. hb_ping = maybe_tunnel(url('hb_ping'))
  150. hb_pong = maybe_tunnel(url('hb_pong'))
  151. hb_monitor = None
  152. if self.max_heartbeat_misses > 0:
  153. # Add a monitor socket which will record the last time a ping was seen
  154. mon = self.context.socket(zmq.SUB)
  155. mport = mon.bind_to_random_port('tcp://%s' % localhost())
  156. mon.setsockopt(zmq.SUBSCRIBE, b"")
  157. self._hb_listener = zmqstream.ZMQStream(mon, self.loop)
  158. self._hb_listener.on_recv(self._report_ping)
  159. hb_monitor = "tcp://%s:%i" % (localhost(), mport)
  160. heart = Heart(hb_ping, hb_pong, hb_monitor , heart_id=identity)
  161. heart.start()
  162. # create Shell Connections (MUX, Task, etc.):
  163. shell_addrs = url('mux'), url('task')
  164. # Use only one shell stream for mux and tasks
  165. stream = zmqstream.ZMQStream(ctx.socket(zmq.ROUTER), loop)
  166. stream.setsockopt(zmq.IDENTITY, identity)
  167. shell_streams = [stream]
  168. for addr in shell_addrs:
  169. connect(stream, addr)
  170. # control stream:
  171. control_addr = url('control')
  172. control_stream = zmqstream.ZMQStream(ctx.socket(zmq.ROUTER), loop)
  173. control_stream.setsockopt(zmq.IDENTITY, identity)
  174. connect(control_stream, control_addr)
  175. # create iopub stream:
  176. iopub_addr = url('iopub')
  177. iopub_socket = ctx.socket(zmq.PUB)
  178. iopub_socket.setsockopt(zmq.IDENTITY, identity)
  179. connect(iopub_socket, iopub_addr)
  180. # disable history:
  181. self.config.HistoryManager.hist_file = ':memory:'
  182. # Redirect input streams and set a display hook.
  183. if self.out_stream_factory:
  184. sys.stdout = self.out_stream_factory(self.session, iopub_socket, u'stdout')
  185. sys.stdout.topic = cast_bytes('engine.%i.stdout' % self.id)
  186. sys.stderr = self.out_stream_factory(self.session, iopub_socket, u'stderr')
  187. sys.stderr.topic = cast_bytes('engine.%i.stderr' % self.id)
  188. if self.display_hook_factory:
  189. sys.displayhook = self.display_hook_factory(self.session, iopub_socket)
  190. sys.displayhook.topic = cast_bytes('engine.%i.pyout' % self.id)
  191. self.kernel = Kernel(parent=self, int_id=self.id, ident=self.ident, session=self.session,
  192. control_stream=control_stream, shell_streams=shell_streams, iopub_socket=iopub_socket,
  193. loop=loop, user_ns=self.user_ns, log=self.log)
  194. self.kernel.shell.display_pub.topic = cast_bytes('engine.%i.displaypub' % self.id)
  195. # periodically check the heartbeat pings of the controller
  196. # Should be started here and not in "start()" so that the right period can be taken
  197. # from the hubs HeartBeatMonitor.period
  198. if self.max_heartbeat_misses > 0:
  199. # Use a slightly bigger check period than the hub signal period to not warn unnecessary
  200. self.hb_check_period = int(content['hb_period'])+10
  201. self.log.info("Starting to monitor the heartbeat signal from the hub every %i ms." , self.hb_check_period)
  202. self._hb_reporter = ioloop.PeriodicCallback(self._hb_monitor, self.hb_check_period, self.loop)
  203. self._hb_reporter.start()
  204. else:
  205. self.log.info("Monitoring of the heartbeat signal from the hub is not enabled.")
  206. # FIXME: This is a hack until IPKernelApp and IPEngineApp can be fully merged
  207. app = IPKernelApp(parent=self, shell=self.kernel.shell, kernel=self.kernel, log=self.log)
  208. app.init_profile_dir()
  209. app.init_code()
  210. self.kernel.start()
  211. else:
  212. self.log.fatal("Registration Failed: %s"%msg)
  213. raise Exception("Registration Failed: %s"%msg)
  214. self.log.info("Completed registration with id %i"%self.id)
  215. def abort(self):
  216. self.log.fatal("Registration timed out after %.1f seconds"%self.timeout)
  217. if self.url.startswith('127.'):
  218. self.log.fatal("""
  219. If the controller and engines are not on the same machine,
  220. you will have to instruct the controller to listen on an external IP (in ipcontroller_config.py):
  221. c.HubFactory.ip='*' # for all interfaces, internal and external
  222. c.HubFactory.ip='192.168.1.101' # or any interface that the engines can see
  223. or tunnel connections via ssh.
  224. """)
  225. self.session.send(self.registrar, "unregistration_request", content=dict(id=self.id))
  226. time.sleep(1)
  227. sys.exit(255)
  228. def _hb_monitor(self):
  229. """Callback to monitor the heartbeat from the controller"""
  230. self._hb_listener.flush()
  231. if self._hb_last_monitored > self._hb_last_pinged:
  232. self._hb_missed_beats += 1
  233. self.log.warn("No heartbeat in the last %s ms (%s time(s) in a row).", self.hb_check_period, self._hb_missed_beats)
  234. else:
  235. #self.log.debug("Heartbeat received (after missing %s beats).", self._hb_missed_beats)
  236. self._hb_missed_beats = 0
  237. if self._hb_missed_beats >= self.max_heartbeat_misses:
  238. self.log.fatal("Maximum number of heartbeats misses reached (%s times %s ms), shutting down.",
  239. self.max_heartbeat_misses, self.hb_check_period)
  240. self.session.send(self.registrar, "unregistration_request", content=dict(id=self.id))
  241. self.loop.stop()
  242. self._hb_last_monitored = time.time()
  243. def start(self):
  244. dc = ioloop.DelayedCallback(self.register, 0, self.loop)
  245. dc.start()
  246. self._abort_dc = ioloop.DelayedCallback(self.abort, self.timeout*1000, self.loop)
  247. self._abort_dc.start()