def heron_pex(topology_pex, topology_class_name, args=None): Log.debug("Importing %s from %s", topology_class_name, topology_pex) if topology_class_name == '-': # loading topology by running its main method (if __name__ == "__main__") heron_env = os.environ.copy() heron_env['HERON_OPTIONS'] = opts.get_heron_config() cmd = [topology_pex] if args is not None: cmd.extend(args) Log.debug("Invoking class using command: ``%s''", ' '.join(cmd)) Log.debug('Heron options: {%s}', str(heron_env['HERON_OPTIONS'])) # invoke the command with subprocess and print error message, if any proc = subprocess.Popen(cmd, env=heron_env, stdout=subprocess.PIPE, stderr=subprocess.PIPE, bufsize=1) # todo(rli): improve python topology submission workflow return ProcessResult(proc) else: try: # loading topology from Topology's subclass (no main method) # to support specifying the name of topology Log.debug("args: %s", args) if args is not None and isinstance(args, (list, tuple)) and len(args) > 0: opts.set_config('cmdline.topology.name', args[0]) os.environ["HERON_OPTIONS"] = opts.get_heron_config() Log.debug("Heron options: {%s}", os.environ["HERON_OPTIONS"]) pex_loader.load_pex(topology_pex) topology_class = pex_loader.import_and_get_class(topology_pex, topology_class_name) topology_class.write() return SimpleResult(Status.Ok) except Exception as ex: Log.debug(traceback.format_exc()) err_context = "Topology %s failed to be loaded from the given pex: %s" %\ (topology_class_name, ex) return SimpleResult(Status.HeronError, err_context)
def run(command, parser, cl_args, unknown_args): ''' Submits the topology to the scheduler * Depending on the topology file name extension, we treat the file as a fatjar (if the ext is .jar) or a tar file (if the ext is .tar/.tar.gz). * We upload the topology file to the packer, update zookeeper and launch scheduler jobs representing that topology * You can see your topology in Heron UI :param command: :param parser: :param cl_args: :param unknown_args: :return: ''' # get the topology file name topology_file = cl_args['topology-file-name'] # check to see if the topology file exists if not os.path.isfile(topology_file): Log.error("Topology jar|tar|pex file %s does not exist" % topology_file) return False # check if it is a valid file type jar_type = topology_file.endswith(".jar") tar_type = topology_file.endswith(".tar") or topology_file.endswith(".tar.gz") pex_type = topology_file.endswith(".pex") if not jar_type and not tar_type and not pex_type: Log.error("Unknown file type. Please use .tar or .tar.gz or .jar or .pex file") return False # create a temporary directory for topology definition file tmp_dir = tempfile.mkdtemp() # if topology needs to be launched in deactivated state, do it so if cl_args['deploy_deactivated']: initial_state = topology_pb2.TopologyState.Name(topology_pb2.PAUSED) else: initial_state = topology_pb2.TopologyState.Name(topology_pb2.RUNNING) # set the tmp dir and deactivated state in global options opts.set_config('cmdline.topologydefn.tmpdirectory', tmp_dir) opts.set_config('cmdline.topology.initial.state', initial_state) # check the extension of the file name to see if it is tar/jar file. if jar_type: return submit_fatjar(cl_args, unknown_args, tmp_dir) elif tar_type: return submit_tar(cl_args, unknown_args, tmp_dir) elif pex_type: return submit_pex(cl_args, unknown_args, tmp_dir) return False
def test_many_opts(self): opts.clear_config() for k in range(1, 100): key = "key-%d" % (k) value = "value-%d" % (k) opts.set_config(key, value) for k in range(1, 100): key = "key-%d" % (k) value = "value-%d" % (k) self.assertEqual(value, opts.get_config(key))
def heron_pex(topology_pex, topology_class_name, args=None): Log.debug("Importing %s from %s" % (topology_class_name, topology_pex)) if topology_class_name == '-': # loading topology by running its main method (if __name__ == "__main__") heron_env = os.environ.copy() heron_env['HERON_OPTIONS'] = opts.get_heron_config() cmd = [topology_pex] if args is not None: cmd.extend(args) Log.debug('$> %s' % ' '.join(cmd)) Log.debug('Heron options: %s' % str(heron_env['HERON_OPTIONS'])) # invoke the command with subprocess and print error message, if any status = subprocess.call(cmd, env=heron_env) if status != 0: err_str = "Topology failed to be loaded from the given pex, with status: %d. Bailing out..." \ % status raise RuntimeError(err_str) else: try: # loading topology from Topology's subclass (no main method) # to support specifying the name of topology Log.debug("args: %s" % args) if args is not None and isinstance(args, (list, tuple)) and len(args) > 0: opts.set_config('cmdline.topology.name', args[0]) os.environ["HERON_OPTIONS"] = opts.get_heron_config() Log.debug("Heron options: %s" % os.environ["HERON_OPTIONS"]) pex_loader.load_pex(topology_pex) topology_class = pex_loader.import_and_get_class(topology_pex, topology_class_name) topology_class.write() except Exception: Log.debug(traceback.format_exc()) err_str = "Topology failed to be loaded from the given pex. Bailing out..." raise RuntimeError(err_str)
def test_clear_opts(self): opts.clear_config() opts.set_config('YY', 'yy') self.assertEqual('yy', opts.get_config('YY')) opts.clear_config() self.assertEqual(None, opts.get_config('YY'))
def test_non_exist_key(self): opts.clear_config() opts.set_config('XX', 'xx') self.assertEqual(None, opts.get_config('YY'))
def test_two_opts(self): opts.clear_config() opts.set_config('XX', 'xx') opts.set_config('YY', 'yy') self.assertEqual('xx', opts.get_config('XX')) self.assertEqual('yy', opts.get_config('YY'))
def test_one_opt(self): opts.clear_config() opts.set_config('XX', 'xx') self.assertEqual('xx', opts.get_config('XX'))
def run(command, parser, cl_args, unknown_args): ''' Submits the topology to the scheduler * Depending on the topology file name extension, we treat the file as a fatjar (if the ext is .jar) or a tar file (if the ext is .tar/.tar.gz). * We upload the topology file to the packer, update zookeeper and launch scheduler jobs representing that topology * You can see your topology in Heron UI :param command: :param parser: :param cl_args: :param unknown_args: :return: ''' # get the topology file name topology_file = cl_args['topology-file-name'] # check to see if the topology file exists if not os.path.isfile(topology_file): err_context = "Topology file '%s' does not exist" % topology_file return SimpleResult(Status.InvocationError, err_context) # check if it is a valid file type jar_type = topology_file.endswith(".jar") tar_type = topology_file.endswith(".tar") or topology_file.endswith(".tar.gz") pex_type = topology_file.endswith(".pex") if not jar_type and not tar_type and not pex_type: ext_name = os.path.splitext(topology_file) err_context = "Unknown file type '%s'. Please use .tar or .tar.gz or .jar or .pex file"\ % ext_name return SimpleResult(Status.InvocationError, err_context) # check if extra launch classpath is provided and if it is validate if cl_args['extra_launch_classpath']: valid_classpath = classpath.valid_java_classpath(cl_args['extra_launch_classpath']) if not valid_classpath: err_context = "One of jar or directory in extra launch classpath does not exist: %s" % \ cl_args['extra_launch_classpath'] return SimpleResult(Status.InvocationError, err_context) # create a temporary directory for topology definition file tmp_dir = tempfile.mkdtemp() opts.cleaned_up_files.append(tmp_dir) # if topology needs to be launched in deactivated state, do it so if cl_args['deploy_deactivated']: initial_state = topology_pb2.TopologyState.Name(topology_pb2.PAUSED) else: initial_state = topology_pb2.TopologyState.Name(topology_pb2.RUNNING) # set the tmp dir and deactivated state in global options opts.set_config('cmdline.topologydefn.tmpdirectory', tmp_dir) opts.set_config('cmdline.topology.initial.state', initial_state) # check the extension of the file name to see if it is tar/jar file. if jar_type: return submit_fatjar(cl_args, unknown_args, tmp_dir) elif tar_type: return submit_tar(cl_args, unknown_args, tmp_dir) else: return submit_pex(cl_args, unknown_args, tmp_dir)
def run(command, parser, cl_args, unknown_args): ''' Submits the topology to the scheduler * Depending on the topology file name extension, we treat the file as a fatjar (if the ext is .jar) or a tar file (if the ext is .tar/.tar.gz). * We upload the topology file to the packer, update zookeeper and launch scheduler jobs representing that topology * You can see your topology in Heron UI :param command: :param parser: :param cl_args: :param unknown_args: :return: ''' Log.debug("Submit Args %s", cl_args) # get the topology file name topology_file = cl_args['topology-file-name'] if urlparse.urlparse(topology_file).scheme: cl_args['topology-file-name'] = download(topology_file, cl_args['cluster']) topology_file = cl_args['topology-file-name'] Log.debug("download uri to local file: %s", topology_file) # check to see if the topology file exists if not os.path.isfile(topology_file): err_context = "Topology file '%s' does not exist" % topology_file return SimpleResult(Status.InvocationError, err_context) # check if it is a valid file type jar_type = topology_file.endswith(".jar") tar_type = topology_file.endswith(".tar") or topology_file.endswith(".tar.gz") pex_type = topology_file.endswith(".pex") cpp_type = topology_file.endswith(".dylib") or topology_file.endswith(".so") if not (jar_type or tar_type or pex_type or cpp_type): _, ext_name = os.path.splitext(topology_file) err_context = "Unknown file type '%s'. Please use .tar "\ "or .tar.gz or .jar or .pex or .dylib or .so file"\ % ext_name return SimpleResult(Status.InvocationError, err_context) # check if extra launch classpath is provided and if it is validate if cl_args['extra_launch_classpath']: valid_classpath = classpath.valid_java_classpath(cl_args['extra_launch_classpath']) if not valid_classpath: err_context = "One of jar or directory in extra launch classpath does not exist: %s" % \ cl_args['extra_launch_classpath'] return SimpleResult(Status.InvocationError, err_context) # create a temporary directory for topology definition file tmp_dir = tempfile.mkdtemp() opts.cleaned_up_files.append(tmp_dir) # if topology needs to be launched in deactivated state, do it so if cl_args['deploy_deactivated']: initial_state = topology_pb2.TopologyState.Name(topology_pb2.PAUSED) else: initial_state = topology_pb2.TopologyState.Name(topology_pb2.RUNNING) # set the tmp dir and deactivated state in global options opts.set_config('cmdline.topologydefn.tmpdirectory', tmp_dir) opts.set_config('cmdline.topology.initial.state', initial_state) opts.set_config('cmdline.topology.role', cl_args['role']) opts.set_config('cmdline.topology.environment', cl_args['environ']) # Use CLI release yaml file if the release_yaml_file config is empty if not cl_args['release_yaml_file']: cl_args['release_yaml_file'] = config.get_heron_release_file() # check the extension of the file name to see if it is tar/jar file. if jar_type: return submit_fatjar(cl_args, unknown_args, tmp_dir) elif tar_type: return submit_tar(cl_args, unknown_args, tmp_dir) elif cpp_type: return submit_cpp(cl_args, unknown_args, tmp_dir) else: return submit_pex(cl_args, unknown_args, tmp_dir)
def run(command, parser, cl_args, unknown_args): ''' Submits the topology to the scheduler * Depending on the topology file name extension, we treat the file as a fatjar (if the ext is .jar) or a tar file (if the ext is .tar/.tar.gz). * We upload the topology file to the packer, update zookeeper and launch scheduler jobs representing that topology * You can see your topology in Heron UI :param command: :param parser: :param cl_args: :param unknown_args: :return: ''' Log.debug("Submit Args %s", cl_args) # get the topology file name topology_file = cl_args['topology-file-name'] # check to see if the topology file exists if not os.path.isfile(topology_file): err_context = "Topology file '%s' does not exist" % topology_file return SimpleResult(Status.InvocationError, err_context) # check if it is a valid file type jar_type = topology_file.endswith(".jar") tar_type = topology_file.endswith(".tar") or topology_file.endswith( ".tar.gz") pex_type = topology_file.endswith(".pex") cpp_type = topology_file.endswith(".dylib") or topology_file.endswith( ".so") if not jar_type and not tar_type and not pex_type and not cpp_type: ext_name = os.path.splitext(topology_file) err_context = "Unknown file type '%s'. Please use .tar "\ "or .tar.gz or .jar or .pex or .dylib or .so file"\ % ext_name return SimpleResult(Status.InvocationError, err_context) # check if extra launch classpath is provided and if it is validate if cl_args['extra_launch_classpath']: valid_classpath = classpath.valid_java_classpath( cl_args['extra_launch_classpath']) if not valid_classpath: err_context = "One of jar or directory in extra launch classpath does not exist: %s" % \ cl_args['extra_launch_classpath'] return SimpleResult(Status.InvocationError, err_context) # create a temporary directory for topology definition file tmp_dir = tempfile.mkdtemp() opts.cleaned_up_files.append(tmp_dir) # if topology needs to be launched in deactivated state, do it so if cl_args['deploy_deactivated']: initial_state = topology_pb2.TopologyState.Name(topology_pb2.PAUSED) else: initial_state = topology_pb2.TopologyState.Name(topology_pb2.RUNNING) # set the tmp dir and deactivated state in global options opts.set_config('cmdline.topologydefn.tmpdirectory', tmp_dir) opts.set_config('cmdline.topology.initial.state', initial_state) opts.set_config('cmdline.topology.role', cl_args['role']) opts.set_config('cmdline.topology.environment', cl_args['environ']) # check the extension of the file name to see if it is tar/jar file. if jar_type: return submit_fatjar(cl_args, unknown_args, tmp_dir) elif tar_type: return submit_tar(cl_args, unknown_args, tmp_dir) elif cpp_type: return submit_cpp(cl_args, unknown_args, tmp_dir) else: return submit_pex(cl_args, unknown_args, tmp_dir)