async def async_request(self, command, args=None, timeout=None): """Send asynchronous request via SSH. """ timeout = timeout if timeout is not None else self.timeout try: async with ascyncto(timeout): cmd, ssh_cmd, login_sh, cylc_path, msg = self.prepare_command( command, args, timeout) proc = _remote_cylc_cmd(cmd, host=self.host, stdin_str=msg, ssh_cmd=ssh_cmd, remote_cylc_path=cylc_path, ssh_login_shell=login_sh, capture_process=True) while True: if proc.poll() is not None: break await asyncio.sleep(self.SLEEP_INTERVAL) out, err = (f.decode() for f in proc.communicate()) return_code = proc.wait() if return_code: raise ClientError(err, f"return-code={return_code}") return json.loads(out) except asyncio.TimeoutError: raise ClientTimeout(f"Command exceeded the timeout {timeout}. " f"This could be due to network problems. " "Check the workflow log.")
async def async_request(self, command, args=None, timeout=None, req_meta=None): """Send an asynchronous request using asyncio. Has the same arguments and return values as ``serial_request``. """ timeout = (float(timeout) * 1000 if timeout else None) or self.timeout if not args: args = {} # Note: we are using CurveZMQ to secure the messages (see # self.curve_auth, self.socket.curve_...key etc.). We have set up # public-key cryptography on the ZMQ messaging and sockets, so # there is no need to encrypt messages ourselves before sending. # send message msg = {'command': command, 'args': args} msg.update(self.header) # add the request metadata if req_meta: msg['meta'].update(req_meta) LOG.debug('zmq:send %s', msg) message = encode_(msg) self.socket.send_string(message) # receive response if self.poller.poll(timeout): res = await self.socket.recv() else: if callable(self.timeout_handler): self.timeout_handler() raise ClientTimeout( 'Timeout waiting for server response.' ' This could be due to network or server issues.' ' Check the workflow log.') if msg['command'] in PB_METHOD_MAP: response = {'data': res} else: response = decode_(res.decode()) LOG.debug('zmq:recv %s', response) try: return response['data'] except KeyError: error = response['error'] raise ClientError(error['message'], error.get('traceback'))
async def async_request(self, command, args=None, timeout=None): """Send an asynchronous request using asyncio. Has the same arguments and return values as ``serial_request``. """ if timeout: timeout = float(timeout) timeout = (timeout * 1000 if timeout else None) or self.timeout if not args: args = {} # get secret for this request # assumes secret won't change during the request try: secret = self.secret() except cylc.flow.suite_srv_files_mgr.SuiteServiceFileError: raise ClientError('could not read suite passphrase') # send message msg = {'command': command, 'args': args} msg.update(self.header) LOG.debug('zmq:send %s' % msg) message = encrypt(msg, secret) self.socket.send_string(message) # receive response if self.poller.poll(timeout): res = await self.socket.recv() else: if self.timeout_handler: self.timeout_handler() raise ClientTimeout('Timeout waiting for server response.') if msg['command'] in PB_METHOD_MAP: response = {'data': res} else: try: response = decrypt(res.decode(), secret) except jose.exceptions.JWTError: raise ClientError( 'Could not decrypt response. Has the passphrase changed?') LOG.debug('zmq:recv %s' % response) try: return response['data'] except KeyError: error = response['error'] raise ClientError(error['message'], error.get('traceback'))