Exemple #1
0
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.')

    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('No matching tasks. Exiting.')

    log.log_files(mesos_files, follow, lines)

    return 0
Exemple #2
0
def test_task_exact_match():
    """Test a task gets returned if it is an exact match, even if
    it is a substring of another task.
    """
    with patch('dcos.mesos.Master.slaves',
               return_value=[{"id": "foo"}, {"id": "foobar"}]):
        master = mesos.Master(None)
        assert master.slave("foo") == {"id": "foo"}
Exemple #3
0
def get_tasks(task_id='', completed=True):
    """ Get a list of tasks, optionally filtered by task name.

        :param task_id: task ID
        :type task_id: str
        :param completed: include completed tasks?
        :type completed: bool

        :return: a tuple of tasks
        :rtype: tuple
    """

    client = mesos.DCOSClient()
    master = mesos.Master(client.get_master_state())
    tasks = master.tasks(completed=completed, fltr=task_id)

    return tasks
Exemple #4
0
def get_tasks(task_id='', completed=True):
    """ Get a list of tasks, optionally filtered by task id.
        The task_id can be the abbrevated.  Example: If a task named 'sleep' is
        scaled to 3 in marathon, there will be be 3 tasks starting with 'sleep.'

        :param task_id: task ID
        :type task_id: str
        :param completed: include completed tasks?
        :type completed: bool

        :return: a list of tasks
        :rtype: []
    """

    client = mesos.DCOSClient()
    master = mesos.Master(client.get_master_state())
    mesos_tasks = master.tasks(completed=completed, fltr=task_id)
    return [task.__dict__['_task'] for task in mesos_tasks]
Exemple #5
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
Exemple #6
0
def uninstall_app(app_name, remove_all, app_id, init_client, dcos_client):
    """Uninstalls an app.

    :param app_name: The app to uninstall
    :type app_name: str
    :param remove_all: Whether to remove all instances of the named app
    :type remove_all: boolean
    :param app_id: App ID of the app instance to uninstall
    :type app_id: str
    :param init_client: The program to use to run the app
    :type init_client: object
    :param dcos_client: the DCOS client
    :type dcos_client: dcos.mesos.DCOSClient
    :returns: number of apps uninstalled
    :rtype: int
    """

    apps = init_client.get_apps()

    def is_match(app):
        encoding = 'utf-8'  # We normalize encoding for byte-wise comparison
        name_label = app.get('labels', {}).get(PACKAGE_NAME_KEY, u'')
        name_label_enc = name_label.encode(encoding)
        app_name_enc = app_name.encode(encoding)
        name_matches = name_label_enc == app_name_enc

        if app_id is not None:
            pkg_app_id = app.get('id', '')
            normalized_app_id = init_client.normalize_app_id(app_id)
            return name_matches and pkg_app_id == normalized_app_id
        else:
            return name_matches

    matching_apps = [a for a in apps if is_match(a)]

    if not remove_all and len(matching_apps) > 1:
        app_ids = [a.get('id') for a in matching_apps]
        raise DCOSException(
            ("Multiple apps named [{}] are installed: [{}].\n" +
             "Please use --app-id to specify the ID of the app to uninstall," +
             " or use --all to uninstall all apps.").format(
                 app_name,
                 ', '.join(app_ids)))

    for app in matching_apps:
        package_json = _decode_and_add_context(
            app['id'],
            app.get('labels', {}))
        # First, remove the app from Marathon
        init_client.remove_app(app['id'], force=True)

        # Second, shutdown the framework with Mesos
        framework_name = app.get('labels', {}).get(PACKAGE_FRAMEWORK_NAME_KEY)
        if framework_name is not None:
            logger.info(
                'Trying to shutdown framework {}'.format(framework_name))
            frameworks = mesos.Master(dcos_client.get_master_state()) \
                              .frameworks(inactive=True)

            # Look up all the framework names
            framework_ids = [
                framework['id']
                for framework in frameworks
                if framework['name'] == framework_name
            ]

            logger.info(
                'Found the following frameworks: {}'.format(framework_ids))

            # Emit post uninstall notes
            emitter.publish(
                DefaultError(
                    'Uninstalled package [{}] version [{}]'.format(
                        package_json['name'],
                        package_json['version'])))

            if 'postUninstallNotes' in package_json:
                emitter.publish(
                    DefaultError(package_json['postUninstallNotes']))

            if len(framework_ids) == 1:
                dcos_client.shutdown_framework(framework_ids[0])
            elif len(framework_ids) > 1:
                raise DCOSException(
                    "Unable to shutdown the framework for [{}] because there "
                    "are multiple frameworks with the same name: [{}]. "
                    "Manually shut them down using 'dcos service "
                    "shutdown'.".format(
                        framework_name,
                        ', '.join(framework_ids)))

    return len(matching_apps)