def _runImpl(self): self._server = NimbleServer(router=self._router) self._SERVER_THREAD = self self._ACTIVATING = False NimbleEnvironment.log(NimbleServerThread._ACTIVE_MESSAGE) asyncore.loop()
def open(self): if self._active: nowTime = TimeUtils.getNowSeconds() if nowTime - self._activatedTime > NimbleEnvironment.CONNECTION_LIFETIME: self.close() else: return False self._activatedTime = TimeUtils.getNowSeconds() try: target = (NimbleEnvironment.getConnectionHost(), NimbleEnvironment.getConnectionPort()) self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Sets socket option to prevent connection being refused by TCP reconnecting # to the same socket after a recent closure. self._socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self._socket.setblocking(1) self._socket.connect(target) except Exception as err: NimbleEnvironment.logError( '[ERROR | NIMBLE COMMUNICATION] Failed to open Nimble connection', err) return False if self not in NimbleConnection._CONNECTION_POOL: NimbleConnection._CONNECTION_POOL.append(self) self._active = True return True
def startServer(logLevel=0, router=None, inMaya=None): """ Starts the NimbleServer properly given the current environmental conditions. The server runs in a separate thread and remains active until the stopServer() method. @@@param logLevel:int The integer logLevel to use when starting the server. The allowed values are: [#list] [#item]0 (default): Only log critical actions.[/#item] [#item]1: Additionally log warnings as well as succinct activity.[/#item] [#item]2: Full verbose logging of all activity.[/#item] [/#list] @@@param router:NimbleRouter The router to use for the server. The default value of None will use the default router for the given environment. The router is responsible for handling the communication traffic received by the server and correctly responding as a result. @@@param inMaya:boolean Whether or not the server is being run in Maya. By default this is determined automatically by the Nimble environment settings. However, in some cases the determination can be incorrect if your external or Maya Python interpreters have been modified to fool the environment test. In such cases this may need to be explicitly set. """ NimbleEnvironment.inMaya(override=inMaya) NimbleEnvironment.setServerLogLevel(logLevel) NimbleServerThread(router=router).start()
def startServer(logLevel =0, router =None, inMaya =None): """ Starts the NimbleServer properly given the current environmental conditions. The server runs in a separate thread and remains active until the stopServer() method. @@@param logLevel:int The integer logLevel to use when starting the server. The allowed values are: [#list] [#item]0 (default): Only log critical actions.[/#item] [#item]1: Additionally log warnings as well as succinct activity.[/#item] [#item]2: Full verbose logging of all activity.[/#item] [/#list] @@@param router:NimbleRouter The router to use for the server. The default value of None will use the default router for the given environment. The router is responsible for handling the communication traffic received by the server and correctly responding as a result. @@@param inMaya:boolean Whether or not the server is being run in Maya. By default this is determined automatically by the Nimble environment settings. However, in some cases the determination can be incorrect if your external or Maya Python interpreters have been modified to fool the environment test. In such cases this may need to be explicitly set. """ NimbleEnvironment.inMaya(override=inMaya) NimbleEnvironment.setServerLogLevel(logLevel) NimbleServerThread(router=router).start()
def open(self): if self._active: nowTime = TimeUtils.getNowSeconds() if nowTime - self._activatedTime > NimbleEnvironment.CONNECTION_LIFETIME: self.close() else: return False self._activatedTime = TimeUtils.getNowSeconds() try: target = ( NimbleEnvironment.getConnectionHost(), NimbleEnvironment.getConnectionPort() ) self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Sets socket option to prevent connection being refused by TCP reconnecting # to the same socket after a recent closure. self._socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self._socket.setblocking(1) self._socket.connect(target) except Exception as err: NimbleEnvironment.logError( '[ERROR | NIMBLE COMMUNICATION] Failed to open Nimble connection', err) return False if self not in NimbleConnection._CONNECTION_POOL: NimbleConnection._CONNECTION_POOL.append(self) self._active = True return True
def __call__(self, *args, **kwargs): """Doc...""" if self.response is None: self.response = RemoteScriptResponse() if self.kwargs is None: self.kwargs = kwargs try: self.run() except Exception as err: message = "Nimble remote script run failure" NimbleEnvironment.logError(message, err) logMessage = Logger.createErrorMessage(message, err) self.putErrorResult(Logger.logMessageToString(logMessage=logMessage, includePrefix=False)) result = self.response.result return result if result else dict()
def handle_request(self): message = self._message if not message: return logLevel = NimbleEnvironment.getServerLogLevel() try: data = self._parseData(message, logLevel) except Exception as err: self._sendResponse( NimbleResponseData(kind=DataKindEnum.GENERAL, error=DataErrorEnum.PARSE_FAILURE, response=NimbleResponseData.FAILED_RESPONSE, payload={'error': str(err)}), logLevel) return if data.kind == DataKindEnum.PING: reply = NimbleResponseData( kind=DataKindEnum.PING, response=NimbleResponseData.SUCCESS_RESPONSE) else: reply = self._routeMessage(data) if not reply: reply = NimbleResponseData( kind=DataKindEnum.GENERAL, error=DataErrorEnum.UNRECOGNIZED_REQUEST, response=NimbleResponseData.FAILED_RESPONSE) self._sendResponse(reply, logLevel)
def handle_request(self): message = self._message if not message: return logLevel = NimbleEnvironment.getServerLogLevel() try: data = self._parseData(message, logLevel) except Exception as err: self._sendResponse( NimbleResponseData( kind=DataKindEnum.GENERAL, error=DataErrorEnum.PARSE_FAILURE, response=NimbleResponseData.FAILED_RESPONSE, payload={'error':str(err)} ), logLevel ) return if data.kind == DataKindEnum.PING: reply = NimbleResponseData( kind=DataKindEnum.PING, response=NimbleResponseData.SUCCESS_RESPONSE) else: reply = self._routeMessage(data) if not reply: reply = NimbleResponseData( kind=DataKindEnum.GENERAL, error=DataErrorEnum.UNRECOGNIZED_REQUEST, response=NimbleResponseData.FAILED_RESPONSE ) self._sendResponse(reply, logLevel)
def __init__(self, connection): self._connection = connection self._commands = None if NimbleEnvironment.inMaya(): import maya.cmds as mc self._commands = mc
def _send(self, nimbleData): """Doc...""" if NimbleEnvironment.inMaya(): return MayaRouter.processRequest(nimbleData) result = self._sendRemote(nimbleData) time.sleep(0.0001) return result
def __call__(self, *args, **kwargs): """Doc...""" if self.response is None: self.response = RemoteScriptResponse() if self.kwargs is None: self.kwargs = kwargs try: self.run() except Exception as err: message = u'Nimble remote script run failure' NimbleEnvironment.logError(message, err) logMessage = Logger.createErrorMessage(message, err) self.putErrorResult( Logger.logMessageToString(logMessage=logMessage, includePrefix=False)) result = self.response.result return result if result else dict()
def __init__(self, router =None): asyncore.dispatcher.__init__(self) try: self.create_socket(socket.AF_INET, socket.SOCK_STREAM) self.set_reuse_addr() self.bind(('localhost', NimbleEnvironment.getServerPort())) self.listen(5) except Exception, err: print 'FAILED: Nimble server connection' print err raise
def __init__(self, **kwargs): """ Creates a new instance of NimbleConnection and opens the communication socket to the corresponding NimbleServer instance. NimbleEnvironment is used to determine whether the connection should be to a Maya or external application NimbleServer instance. """ self._active = False self._socket = None if not NimbleEnvironment.inMaya(): self.open() self._mayaCommandLink = None
def __init__(self, router =None): asyncore.dispatcher.__init__(self) try: self.create_socket(socket.AF_INET, socket.SOCK_STREAM) self.set_reuse_addr() self.bind(('localhost', NimbleEnvironment.getServerPort())) self.listen(5) except Exception as err: NimbleEnvironment.logError( '[ERROR | NIMBLE SERVER] Failed to establish server connection', err) raise if router is None: if NimbleEnvironment.inMaya(): from nimble.connection.router.MayaRouter import MayaRouter self._router = MayaRouter else: self._router = NimbleRouter else: self._router = router
def getConnection(inMaya=None, forceCreate=False): """ Retrieves a communication connection object from the connection pool, which is used for sending commands to the remote nimble server. :param inMaya | boolean Whether or not the server is being run in Maya. By default this is determined automatically by the Nimble environment settings. However, in some cases the determination can be incorrect if your external or Maya Python interpreters have been modified to fool the environment test. In such cases this may need to be explicitly set. :param forceCreate | boolean If True a new connection will be created even if one already exists and is available. This should rarely be used but can be useful in multi-threaded situations where sharing a single connection could be harmful. :return NimbleConnection A NimbleConnection instance opened and ready for issuing commands to the remote server. """ NimbleEnvironment.inMaya(override=inMaya) return NimbleConnection.getConnection(forceCreate=forceCreate)
def getConnection(inMaya =None, forceCreate =False): """ Retrieves a communication connection object from the connection pool, which is used for sending commands to the remote nimble server. :param inMaya | boolean Whether or not the server is being run in Maya. By default this is determined automatically by the Nimble environment settings. However, in some cases the determination can be incorrect if your external or Maya Python interpreters have been modified to fool the environment test. In such cases this may need to be explicitly set. :param forceCreate | boolean If True a new connection will be created even if one already exists and is available. This should rarely be used but can be useful in multi-threaded situations where sharing a single connection could be harmful. :return NimbleConnection A NimbleConnection instance opened and ready for issuing commands to the remote server. """ NimbleEnvironment.inMaya(override=inMaya) return NimbleConnection.getConnection(forceCreate=forceCreate)
def __init__(self, router=None): asyncore.dispatcher.__init__(self) try: self.create_socket(socket.AF_INET, socket.SOCK_STREAM) self.set_reuse_addr() self.bind((NimbleEnvironment.getServerHost(), NimbleEnvironment.getServerPort())) self.listen(5) except Exception as err: NimbleEnvironment.logError( '[ERROR | NIMBLE SERVER] Failed to establish server connection', err) raise if router is None: if NimbleEnvironment.inMaya(): from nimble.connection.router.MayaRouter import MayaRouter self._router = MayaRouter else: self._router = NimbleRouter else: self._router = router
def changeServerLogLevel(logLevel=0): """ Changes the active servers logging level, or, if no server is active, changes the environment so that when a server is started it will run at the specified level. This is useful if, for example, you want to dynamically change the log level at a given point to debug. @@@param logLevel:int The integer logLevel to use when starting the server. The allowed values are: [#list] [#item]0 (default): Only log critical actions.[/#item] [#item]1: Additionally log warnings as well as succinct activity.[/#item] [#item]2: Full verbose logging of all activity.[/#item] [/#list] """ return NimbleEnvironment.setServerLogLevel(logLevel)
def changeServerLogLevel(logLevel =0): """ Changes the active servers logging level, or, if no server is active, changes the environment so that when a server is started it will run at the specified level. This is useful if, for example, you want to dynamically change the log level at a given point to debug. @@@param logLevel:int The integer logLevel to use when starting the server. The allowed values are: [#list] [#item]0 (default): Only log critical actions.[/#item] [#item]1: Additionally log warnings as well as succinct activity.[/#item] [#item]2: Full verbose logging of all activity.[/#item] [/#list] """ return NimbleEnvironment.setServerLogLevel(logLevel)
def open(self): if self._active: return False try: target = ('localhost', NimbleEnvironment.getConnectionPort()) self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Sets socket option to prevent connection being refused by TCP reconnecting # to the same socket after a recent closure. self._socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self._socket.connect(target) except Exception, err: print 'Failed to open Nimble connection.' print err return False
def runPythonImport(self, modulePackage, methodName=None, className=None, runInMaya=None, **kwargs): """ Executes the specified import through Nimble in the specified run mode. modulePackage: (String) An absolute (dot-syntax) formatted import to the module you wish to be executed. This module will be imported by Maya and must be on its sys.path. [methodName]: (String) An optional function name to be executed within the module. If a class name is specified this method will be called on an instance of the specified class. If no class name is specified the method will be called directly on the module. [className]: (String) An optional class name of a class to import within the specified module. The class will be imported from the module and instantiated. [runInMaya]: If True the import will be executed within Maya. If False the import will be executed outside of Maya on the remote end of the Nimble connection. The default value of None will use the current global setting, which can be set by the nimble.enablePythonTestMode() top-level function and defaults to runInMaya = True, i.e. test mode is disabled. Returns a NimbleResponseData object with the results of the script execution. """ payload = { 'module': modulePackage, 'method': methodName, 'class': className, 'kwargs': kwargs } if NimbleEnvironment.inMaya(): return MayaRouter.runPythonImport(payload) if (not NimbleEnvironment.TEST_REMOTE_MODE ) if runInMaya is None else runInMaya: return self._send( NimbleData(kind=DataKindEnum.PYTHON_IMPORT, payload=payload)) else: return MayaRouter.runPythonImport(payload)
def echo(self, verbose =False, pretty =False): msg = self._createMessage() header = 'RESPONSE' if hasattr(self, 'response') else 'REQUEST' if verbose: if pretty: s = '\n' + 100*'-' + '\n' + header + ':\n' + (len(header) + 1)*'-' + '\n' for n,v in msg.iteritems(): s += ' ' + str(n).upper() + ': ' + str(v) + '\n' NimbleEnvironment.log(s) else: NimbleEnvironment.log(header + ': ' + str(msg)) else: NimbleEnvironment.log('<NIMBLE %s | %s>' % (header, self.kind))
def handle_request(self): message = self._message if not message: return logLevel = NimbleEnvironment.getServerLogLevel() try: data = self._parseData(message, logLevel) except Exception, err: self._sendResponse( NimbleResponseData( kind=DataKindEnum.GENERAL, error=DataErrorEnum.PARSE_FAILURE, response=NimbleResponseData.FAILED_RESPONSE, payload={"error": str(err)}, ), logLevel, ) return
def runPythonImport(self, modulePackage, methodName =None, className=None, runInMaya =None, **kwargs): """ Executes the specified import through Nimble in the specified run mode. modulePackage: (String) An absolute (dot-syntax) formatted import to the module you wish to be executed. This module will be imported by Maya and must be on its sys.path. [methodName]: (String) An optional function name to be executed within the module. If a class name is specified this method will be called on an instance of the specified class. If no class name is specified the method will be called directly on the module. [className]: (String) An optional class name of a class to import within the specified module. The class will be imported from the module and instantiated. [runInMaya]: If True the import will be executed within Maya. If False the import will be executed outside of Maya on the remote end of the Nimble connection. The default value of None will use the current global setting, which can be set by the nimble.enablePythonTestMode() top-level function and defaults to runInMaya = True, i.e. test mode is disabled. Returns a NimbleResponseData object with the results of the script execution. """ payload = { 'module':modulePackage, 'method':methodName, 'class':className, 'kwargs':kwargs} if NimbleEnvironment.inMaya(): return MayaRouter.runPythonImport(payload) if (not NimbleEnvironment.TEST_REMOTE_MODE) if runInMaya is None else runInMaya: return self._send(NimbleData(kind=DataKindEnum.PYTHON_IMPORT, payload=payload)) else: return MayaRouter.runPythonImport(payload)
def getNimbleConnection(cls, inMaya =None, forceCreate =None): NimbleEnvironment.inMaya(override=inMaya) try: return NimbleConnection.getConnection(forceCreate=forceCreate) except Exception: raise
def run(self): """Doc...""" self.saveSelection() count = self.fetch('count', 1000) self._size = self.fetch('size', 0.1) self._padding = self.fetch('padding', 0.0) transforms = cmds.ls(selection=True, type='transform') if not transforms: self._cleanup() self.putErrorResult(u'ERROR: No transforms selected') return shapes = [] totalVolume = 0.0 shapeCount = 0 for transform in transforms: shapeNames = cmds.listRelatives(transforms, shapes=True) if not shapeNames: continue for shape in shapeNames: try: box = TransformUtils.getBoundingBox(shape) cmds.select(shape, replace=True) shapeVolume = nimble.executeMelCommand('computePolysetVolume') totalVolume += shapeVolume shapes.append(dict( transform=transform, name=shape, box=box, weight=float(shapeVolume)) ) shapeCount += 1 except Exception as err: self._cleanup() NimbleEnvironment.logError(u'ERROR: Shape processing', err) self.putErrorResult( u'ERROR: Unable to process selection item %s -> %s' % (transform, shape) ) return if shapeCount == 0: self._cleanup() self.putErrorResult(u'ERROR: No polygon transforms found in selection') return try: for shape in shapes: if not self._createMeshPointNode(shape): self._cleanup() print(u'ERROR: Creation failure') self.putErrorResult(u'ERROR: Unable to create point test node') shape['weight'] /= totalVolume shapeCount = int(round(float(count)*shape['weight'])) for i in range(shapeCount): self._create(shape) self._removeMeshPointNode() except Exception as err: self._cleanup() print(Logger.createErrorMessage(u'ERROR: Creation failure', err)) self.putErrorResult(u'ERROR: Unable to create random box') return self._cleanup()
# test_externalServer.py # (C)2012 http://www.ThreeAddOne.com # Scott Ernst from __future__ import print_function, absolute_import, unicode_literals, division import time import nimble nimble.startServer() nimble.echoServerStatus() from nimble.NimbleEnvironment import NimbleEnvironment print('IN MAYA:', NimbleEnvironment.inMaya()) time.sleep(5) nimble.stopServer() print('Test complete')
def getIsRunningInMaya(): return NimbleEnvironment.inMaya()
def _sendRemote(self, nimbleData): responseFlags = 0 message = u'' retry = NimbleEnvironment.REMOTE_RETRY_COUNT while retry > 0: try: self.open() except Exception as err: failure = [ '[ERROR | NIMBLE COMMUNICATION] Unable to open connection', err ] retry -= 1 if retry == 0: if not nimble.quietFailure: NimbleEnvironment.logError(failure[0], failure[1]) return None continue try: serialData = nimbleData.serialize() except Exception as err: failure = [ '[ERROR | NIMBLE COMMUNICATION] Unable to serialize data for transmission', err ] if not nimble.quietFailure: NimbleEnvironment.logError(failure[0], failure[1]) return None try: self._chunk.clear() self._chunk.writeUint32(NimbleEnvironment.CONNECTION_FLAGS) self._chunk.writeString( serialData + NimbleEnvironment.TERMINATION_IDENTIFIER) self._socket.sendall(self._chunk.byteArray) except Exception as err: failure = [ '[ERROR | NIMBLE COMMUNICATION] Unable to send data', err ] self.close() retry -= 1 if retry == 0: if not nimble.quietFailure: NimbleEnvironment.logError(failure[0], failure[1]) return None continue try: self._chunk.clear() b = SocketUtils.receiveInChunks( self._socket, chunkSize=NimbleEnvironment.SOCKET_RESPONSE_CHUNK_SIZE) self._chunk.writeString(b) self._chunk.position = 0 responseFlags = self._chunk.readUint32() message = StringUtils.strToUnicode(self._chunk.read(-1)) # Break while loop on successful reading of the result if message is not None: break except Exception as err: if not nimble.quietFailure: NimbleEnvironment.logError( '[ERROR | NIMBLE COMMUNICATION] Unable to read response', err) self.close() return None try: if not (responseFlags & ConnectionFlags.KEEP_ALIVE): self.close() except Exception as err: if not nimble.quietFailure: NimbleEnvironment.logError( '[ERROR | NIMBLE COMMUNICATION] Unable to close connection', err) try: return NimbleData.fromMessage(message) except Exception as err: if not nimble.quietFailure: NimbleEnvironment.logError( '[ERROR | NIMBLE COMMUNICATION] Response data parsing failure', err) return None
def runPythonImport(cls, payload): try: kwargs = payload.get('kwargs', {}) targetModule = StringUtils.toStr2(payload.get('module')) targetMethod = StringUtils.toStr2(payload.get('method')) targetClass = StringUtils.toStr2(payload.get('class')) target = targetClass if targetClass is not None else targetMethod if target is None: parts = targetModule.rsplit('.', 1) targetModule = parts[0] target = parts[1] except Exception as err: NimbleEnvironment.logError([ 'ERROR: Failed to parse python import payload', 'PAYLOAD: ' + DictUtils.prettyPrint(payload)], err) return NimbleResponseData( kind=DataKindEnum.PYTHON_IMPORT, error=cls._getDetailedError('\n'.join([ 'ERROR: Failed to parse python import payload', 'PAYLOAD: ' + DictUtils.prettyPrint(payload)]), err), response=NimbleResponseData.FAILED_RESPONSE) # Dynamically import the specified module and reload it to make sure any changes have # been updated try: module = __import__( StringUtils.toStr2(targetModule), globals(), locals(), [StringUtils.toStr2(target)] if target else []) reload(module) target = getattr(module, target) except Exception as err: NimbleEnvironment.logError([ 'ERROR: Failed to import python target', 'MODULE: %s' % targetModule, 'TARGET: %s' % target, 'PAYLOAD: ' + DictUtils.prettyPrint(payload)], err) return NimbleResponseData( kind=DataKindEnum.PYTHON_IMPORT, error=cls._getDetailedError( 'Failed to import python module', err), response=NimbleResponseData.FAILED_RESPONSE) try: result = dict() if targetClass is not None: tc = target() result = getattr(tc, targetMethod)(**kwargs) \ if targetMethod else \ tc(**kwargs) elif targetMethod is not None: result = target(**kwargs) else: # Find a NimbleScriptBase derived class definition and if it exists, run it to # populate the results for name,value in DictUtils.iter(Reflection.getReflectionDict(target)): if not inspect.isclass(value): continue if NimbleScriptBase in value.__bases__: result = getattr(target, name)()(**kwargs) found = True # If a result dictionary contains an error key format the response as a failure errorMessage = None try: errorMessage = ArgsUtils.extract( NimbleEnvironment.REMOTE_RESULT_ERROR_KEY, None, result) except Exception as err: pass return cls.createReply(DataKindEnum.PYTHON_IMPORT, result, errorMessage=errorMessage) except Exception as err: msg = 'ERROR: Failed to execute remote script' NimbleEnvironment.logError([ msg, 'PAYLOAD: ' + DictUtils.prettyPrint(payload), 'TARGET: ' + str(target)], err) return NimbleResponseData( kind=DataKindEnum.PYTHON_IMPORT, error=cls._getDetailedError(msg, err), response=NimbleResponseData.FAILED_RESPONSE)
def runPythonImport(cls, payload): try: kwargs = payload.get('kwargs', {}) targetModule = StringUtils.toStr2(payload.get('module')) targetMethod = StringUtils.toStr2(payload.get('method')) targetClass = StringUtils.toStr2(payload.get('class')) target = targetClass if targetClass is not None else targetMethod if target is None: parts = targetModule.rsplit('.', 1) targetModule = parts[0] target = parts[1] except Exception as err: NimbleEnvironment.logError([ 'ERROR: Failed to parse python import payload', 'PAYLOAD: ' + DictUtils.prettyPrint(payload) ], err) return NimbleResponseData( kind=DataKindEnum.PYTHON_IMPORT, error=cls._getDetailedError( '\n'.join([ 'ERROR: Failed to parse python import payload', 'PAYLOAD: ' + DictUtils.prettyPrint(payload) ]), err), response=NimbleResponseData.FAILED_RESPONSE) # Dynamically import the specified module and reload it to make sure any changes have # been updated try: module = __import__(StringUtils.toStr2(targetModule), globals(), locals(), [StringUtils.toStr2(target)] if target else []) reload(module) target = getattr(module, target) except Exception as err: NimbleEnvironment.logError([ 'ERROR: Failed to import python target', 'MODULE: %s' % targetModule, 'TARGET: %s' % target, 'PAYLOAD: ' + DictUtils.prettyPrint(payload) ], err) return NimbleResponseData( kind=DataKindEnum.PYTHON_IMPORT, error=cls._getDetailedError('Failed to import python module', err), response=NimbleResponseData.FAILED_RESPONSE) try: result = dict() if targetClass is not None: tc = target() result = getattr(tc, targetMethod)(**kwargs) \ if targetMethod else \ tc(**kwargs) elif targetMethod is not None: result = target(**kwargs) else: # Find a NimbleScriptBase derived class definition and if it exists, run it to # populate the results for name, value in DictUtils.iter( Reflection.getReflectionDict(target)): if not inspect.isclass(value): continue if NimbleScriptBase in value.__bases__: result = getattr(target, name)()(**kwargs) found = True # If a result dictionary contains an error key format the response as a failure errorMessage = None try: errorMessage = ArgsUtils.extract( NimbleEnvironment.REMOTE_RESULT_ERROR_KEY, None, result) except Exception as err: pass return cls.createReply(DataKindEnum.PYTHON_IMPORT, result, errorMessage=errorMessage) except Exception as err: msg = 'ERROR: Failed to execute remote script' NimbleEnvironment.logError([ msg, 'PAYLOAD: ' + DictUtils.prettyPrint(payload), 'TARGET: ' + str(target) ], err) return NimbleResponseData( kind=DataKindEnum.PYTHON_IMPORT, error=cls._getDetailedError(msg, err), response=NimbleResponseData.FAILED_RESPONSE)
def _sendRemote(self, nimbleData): responseFlags = 0 message = u'' retry = NimbleEnvironment.REMOTE_RETRY_COUNT while retry > 0: try: self.open() except Exception as err: failure = [ '[ERROR | NIMBLE COMMUNICATION] Unable to open connection', err ] retry -= 1 if retry == 0: if not nimble.quietFailure: NimbleEnvironment.logError(failure[0], failure[1]) return None continue try: serialData = nimbleData.serialize() except Exception as err: failure = [ '[ERROR | NIMBLE COMMUNICATION] Unable to serialize data for transmission', err ] if not nimble.quietFailure: NimbleEnvironment.logError(failure[0], failure[1]) return None try: self._chunk.clear() self._chunk.writeUint32(NimbleEnvironment.CONNECTION_FLAGS) self._chunk.writeString(serialData + NimbleEnvironment.TERMINATION_IDENTIFIER) self._socket.sendall(self._chunk.byteArray) except Exception as err: failure = [ '[ERROR | NIMBLE COMMUNICATION] Unable to send data', err ] self.close() retry -= 1 if retry == 0: if not nimble.quietFailure: NimbleEnvironment.logError(failure[0], failure[1]) return None continue try: self._chunk.clear() b = SocketUtils.receiveInChunks( self._socket, chunkSize=NimbleEnvironment.SOCKET_RESPONSE_CHUNK_SIZE) self._chunk.writeString(b) self._chunk.position = 0 responseFlags = self._chunk.readUint32() message = StringUtils.strToUnicode(self._chunk.read(-1)) # Break while loop on successful reading of the result if message is not None: break except Exception as err: if not nimble.quietFailure: NimbleEnvironment.logError( '[ERROR | NIMBLE COMMUNICATION] Unable to read response', err) self.close() return None try: if not (responseFlags & ConnectionFlags.KEEP_ALIVE): self.close() except Exception as err: if not nimble.quietFailure: NimbleEnvironment.logError( '[ERROR | NIMBLE COMMUNICATION] Unable to close connection', err) try: return NimbleData.fromMessage(message) except Exception as err: if not nimble.quietFailure: NimbleEnvironment.logError( '[ERROR | NIMBLE COMMUNICATION] Response data parsing failure', err) return None