def _log_service(follow, lines, service, file_): """Prints the contents of the logs for a given service. Used for non-marathon services. :param follow: same as unix tail's -f :type follow: bool :param lines: number of lines to print :type lines: int :param service: service name :type service: str :param file_: file path to read :type file_: str :returns: process return code :rtype: int """ if file_ is None: file_ = 'stdout' task = _get_service_task(service) # if journald logging is disabled, read from files API. if log.dcos_log_enabled() or log.dcos_log_enabled(version=2): if 'id' not in task: raise DCOSException('Missing `id` in task. {}'.format(task)) task_id = task['id'] task_main._log(True, follow, False, lines, task_id, file_) return 0 # else use the files API directly. return _log_task(task['id'], follow, lines, file_)
def _log_service(follow, lines, service, file_): """Prints the contents of the logs for a given service. Used for non-marathon services. :param follow: same as unix tail's -f :type follow: bool :param lines: number of lines to print :type lines: int :param service: service name :type service: str :param file_: file path to read :type file_: str :returns: process return code :rtype: int """ if file_ is None: file_ = 'stdout' task = _get_service_task(service) # if journald logging is disabled, read from files API. if not log.dcos_log_enabled(): return _log_task(task['id'], follow, lines, file_) if 'id' not in task: raise DCOSException('Missing `id` in task. {}'.format(task)) task_id = task['id'] task_main._log(follow, False, lines, task_id, file_) return 0
def _dcos_log(follow, lines, leader, slave, component, filters): """ Print logs from dcos-log backend. :param follow: same as unix tail's -f :type follow: bool :param lines: number of lines to print :type lines: int :param leader: whether to print the leading master's log :type leader: bool :param slave: the slave ID to print :type slave: str | None :param component: DC/OS component name :type component: string :param filters: a list of filters ["key:value", ...] :type filters: list """ if not log.dcos_log_enabled(): raise DCOSException('dcos-log is not supported') filter_query = '' if component: filters.append('_SYSTEMD_UNIT:{}'.format(_get_unit_type(component))) for f in filters: key_value = f.split(':') if len(key_value) != 2: raise SystemExit('Invalid filter parameter {}. ' 'Must be --filter=key:value'.format(f)) filter_query += '&filter={}'.format(f) endpoint = '/system/v1' if leader: endpoint += '/logs/v1/' if slave: endpoint += '/agent/{}/logs/v1/'.format(slave) endpoint_type = 'range' if follow: endpoint_type = 'stream' dcos_url = config.get_config_val('core.dcos_url').rstrip("/") if not dcos_url: raise config.missing_config_exception(['core.dcos_url']) url = (dcos_url + endpoint + endpoint_type + '/?skip_prev={}'.format(lines) + filter_query) if follow: return log.follow_logs(url) return log.print_logs_range(url)
def _log(follow, lines, leader, slave, component, filters): """ Prints the contents of leader and slave logs. :param follow: same as unix tail's -f :type follow: bool :param lines: number of lines to print :type lines: int :param leader: whether to print the leading master's log :type leader: bool :param slave: the slave ID to print :type slave: str | None :param component: DC/OS component name :type component: string :param filters: a list of filters ["key:value", ...] :type filters: list :returns: process return code :rtype: int """ if not (leader or slave): raise DCOSException('You must choose one of --leader or --mesos-id.') if lines is None: lines = 10 lines = util.parse_int(lines) if log.dcos_log_enabled(version=2): _dcos_log_v2(follow, lines, leader, slave, component, filters) return 0 if not log.has_journald_capability(): if component or filters: raise DCOSException('--component or --filter is not ' 'supported by files API') # fall back to mesos files API. mesos_files = _mesos_files(leader, slave) log.log_files(mesos_files, follow, lines) return 0 # dcos-log does not support logs from leader and agent. if leader and slave: raise DCOSException( 'You must choose one of --leader or --mesos-id.') # if journald logging enabled. _dcos_log(follow, lines, leader, slave, component, filters) return 0
def _log(all_, follow, completed, lines, task, file_): """ Tail a file in the task's sandbox. :param all_: If True, include all tasks :type all_: bool :param follow: same as unix tail's -f :type follow: bool :param completed: whether to include completed tasks :type completed: bool :param lines: number of lines to print :type lines: int :param task: task pattern to match :type task: str :param file_: file path to read :type file_: str :returns: process return code :rtype: int """ fltr = task if file_ is None: file_ = 'stdout' if lines is None: lines = 10 lines = util.parse_int(lines) # get tasks client = mesos.DCOSClient() master = mesos.Master(client.get_master_state()) tasks = master.tasks(fltr=fltr, completed=completed, all_=all_) if not tasks: if not fltr: raise DCOSException("No tasks found. Exiting.") elif not completed: completed_tasks = master.tasks(completed=True, fltr=fltr) if completed_tasks: msg = 'No running tasks match ID [{}]; however, there '.format( fltr) if len(completed_tasks) > 1: msg += 'are {} matching completed tasks. '.format( len(completed_tasks)) else: msg += 'is 1 matching completed task. ' msg += 'Run with --completed to see these logs.' raise DCOSException(msg) raise DCOSException('No matching tasks. Exiting.') # if journald logging is disabled, read files API and exit. if not log.dcos_log_enabled(): mesos_files = _mesos_files(tasks, file_, client) if not mesos_files: if fltr is None: msg = "No tasks found. Exiting." else: msg = "No matching tasks. Exiting." raise DCOSException(msg) log.log_files(mesos_files, follow, lines) return 0 # otherwise if file_ in ('stdout', 'stderr'): _dcos_log(follow, tasks, lines, file_, completed) return 0 raise DCOSException('Invalid file {}. dcos-log only ' 'supports stdout/stderr'.format(file_)) return 1
def _log(follow, completed, lines, task, file_): """ Tail a file in the task's sandbox. :param follow: same as unix tail's -f :type follow: bool :param completed: whether to include completed tasks :type completed: bool :param lines: number of lines to print :type lines: int :param task: task pattern to match :type task: str :param file_: file path to read :type file_: str :returns: process return code :rtype: int """ fltr = task if file_ is None: file_ = 'stdout' if lines is None: lines = 10 lines = util.parse_int(lines) # get tasks client = mesos.DCOSClient() master = mesos.Master(client.get_master_state()) tasks = master.tasks(completed=completed, fltr=fltr) if not tasks: if not fltr: raise DCOSException("No tasks found. Exiting.") elif not completed: completed_tasks = master.tasks(completed=True, fltr=fltr) if completed_tasks: msg = 'No running tasks match ID [{}]; however, there '.format( fltr) if len(completed_tasks) > 1: msg += 'are {} matching completed tasks. '.format( len(completed_tasks)) else: msg += 'is 1 matching completed task. ' msg += 'Run with --completed to see these logs.' raise DCOSException(msg) raise DCOSException('No matching tasks. Exiting.') if file_ in ('stdout', 'stderr') and log.dcos_log_enabled(): try: _dcos_log(follow, tasks, lines, file_, completed) return 0 except (DCOSAuthenticationException, DCOSAuthorizationException): raise except DCOSException as e: emitter.publish(DefaultError(e)) emitter.publish(DefaultError('Falling back to files API...')) mesos_files = _mesos_files(tasks, file_, client) if not mesos_files: if fltr is None: msg = "No tasks found. Exiting." else: msg = "No matching tasks. Exiting." raise DCOSException(msg) log.log_files(mesos_files, follow, lines) return 0