Ejemplo n.º 1
0
def get_verbose_status_of_marathon_app(marathon_client, app, service, instance,
                                       cluster, soa_dir):
    """Takes a given marathon app object and returns the verbose details
    about the tasks, times, hosts, etc"""
    output = []
    create_datetime = datetime_from_utc_to_local(
        isodate.parse_datetime(app.version))
    output.append("  Marathon app ID: %s" % PaastaColors.bold(app.id))
    output.append(
        "    App created: %s (%s)" %
        (str(create_datetime), humanize.naturaltime(create_datetime)))

    autoscaling_info = get_autoscaling_info(marathon_client, service, instance,
                                            cluster, soa_dir)
    if autoscaling_info:
        output.append("    Autoscaling Info:")
        headers = [
            field.replace("_", " ").capitalize()
            for field in ServiceAutoscalingInfo._fields
        ]
        table = [headers, autoscaling_info]
        output.append('\n'.join(
            ["      %s" % line for line in format_table(table)]))

    output.append("    Tasks:")
    rows = [("Mesos Task ID", "Host deployed to", "Deployed at what localtime",
             "Health")]
    for task in app.tasks:
        local_deployed_datetime = datetime_from_utc_to_local(task.staged_at)
        if task.host is not None:
            hostname = "%s:%s" % (task.host.split(".")[0], task.ports[0])
        else:
            hostname = "Unknown"
        if not task.health_check_results:
            health_check_status = PaastaColors.grey("N/A")
        elif marathon_tools.is_task_healthy(task):
            health_check_status = PaastaColors.green("Healthy")
        else:
            health_check_status = PaastaColors.red("Unhealthy")

        rows.append((
            get_short_task_id(task.id),
            hostname,
            '%s (%s)' % (
                local_deployed_datetime.strftime("%Y-%m-%dT%H:%M"),
                humanize.naturaltime(local_deployed_datetime),
            ),
            health_check_status,
        ))
    output.append('\n'.join(["      %s" % line
                             for line in format_table(rows)]))
    if len(app.tasks) == 0:
        output.append("      No tasks associated with this marathon app")
    return app.tasks, "\n".join(output)
Ejemplo n.º 2
0
def status_marathon_job_verbose(
    service: str,
    instance: str,
    clients: marathon_tools.MarathonClients,
    cluster: str,
    soa_dir: str,
    job_config: marathon_tools.MarathonServiceConfig,
    dashboards: Dict[marathon_tools.MarathonClient, str],
) -> Tuple[List[MarathonTask], str]:
    """Returns detailed information about a marathon apps for a service
    and instance. Does not make assumptions about what the *exact*
    appid is, but instead does a fuzzy match on any marathon apps
    that match the given service.instance"""
    all_tasks: List[MarathonTask] = []
    all_output: List[str] = []
    # For verbose mode, we want to see *any* matching app. As it may
    # not be the one that we think should be deployed. For example
    # during a bounce we want to see the old and new ones.
    marathon_apps_with_clients = marathon_tools.get_marathon_apps_with_clients(
        clients=clients.get_all_clients_for_service(job_config),
        embed_tasks=True,
    )

    autoscaling_info = get_autoscaling_info(clients, job_config)
    if autoscaling_info:
        all_output.append("  Autoscaling Info:")
        headers = [
            field.replace("_", " ").capitalize()
            for field in ServiceAutoscalingInfo._fields
        ]
        table = [headers, autoscaling_info]
        all_output.append('\n'.join(
            ["    %s" % line for line in format_table(table)]))

    for app, client in marathon_tools.get_matching_apps_with_clients(
            service, instance, marathon_apps_with_clients):
        tasks, output = get_verbose_status_of_marathon_app(
            marathon_client=client,
            app=app,
            service=service,
            instance=instance,
            cluster=cluster,
            soa_dir=soa_dir,
            dashboards=dashboards,
        )
        all_tasks.extend(tasks)
        all_output.append(output)
    return all_tasks, "\n".join(all_output)
Ejemplo n.º 3
0
def status_marathon_job(
    service: str,
    instance: str,
    cluster: str,
    soa_dir: str,
    dashboards: Dict[marathon_tools.MarathonClient, str],
    normal_instance_count: int,
    clients: marathon_tools.MarathonClients,
    job_config: marathon_tools.MarathonServiceConfig,
    desired_app_id: str,
    verbose: int,
) -> Tuple[List[MarathonTask], str]:
    marathon_apps_with_clients = marathon_tools.get_marathon_apps_with_clients(
        clients=clients.get_all_clients_for_service(job_config),
        embed_tasks=True,
        service_name=service,
    )
    all_tasks = []
    all_output = [
        ""
    ]  # One entry that will be replaced with status_marathon_job_human output later.

    running_instances = 0

    if verbose > 0:
        autoscaling_info = get_autoscaling_info(marathon_apps_with_clients, job_config)
        if autoscaling_info:
            all_output.append("  Autoscaling Info:")
            headers = [
                field.replace("_", " ").capitalize()
                for field in ServiceAutoscalingInfo._fields
            ]
            table = [headers, humanize_autoscaling_info(autoscaling_info)]
            all_output.append(
                "\n".join(["    %s" % line for line in format_table(table)])
            )

    deploy_status_for_desired_app = "Waiting for bounce"
    matching_apps_with_clients = marathon_tools.get_matching_apps_with_clients(
        service, instance, marathon_apps_with_clients
    )
    for app, client in matching_apps_with_clients:
        all_tasks.extend(app.tasks)
        (
            deploy_status_for_current_app,
            running_instances_for_current_app,
            out,
        ) = status_marathon_app(
            marathon_client=client,
            app=app,
            service=service,
            instance=instance,
            cluster=cluster,
            soa_dir=soa_dir,
            dashboards=dashboards,
            verbose=verbose,
        )
        if app.id.lstrip("/") == desired_app_id.lstrip("/"):
            deploy_status_for_desired_app = marathon_tools.MarathonDeployStatus.tostring(
                deploy_status_for_current_app
            )

        running_instances += running_instances_for_current_app
        all_output.append(out)

    all_output[0] = status_marathon_job_human(
        service=service,
        instance=instance,
        deploy_status=deploy_status_for_desired_app,
        desired_app_id=desired_app_id,
        app_count=len(matching_apps_with_clients),
        running_instances=running_instances,
        normal_instance_count=normal_instance_count,
    )

    return all_tasks, "\n".join(all_output)
Ejemplo n.º 4
0
def marathon_job_status(
    service: str,
    instance: str,
    job_config: marathon_tools.MarathonServiceConfig,
    marathon_apps_with_clients: List[Tuple[MarathonApp, MarathonClient]],
    verbose: int,
) -> MutableMapping[str, Any]:
    job_status_fields: MutableMapping[str, Any] = {
        "app_statuses": [],
        "app_count":
        len(marathon_apps_with_clients),
        "desired_state":
        job_config.get_desired_state(),
        "bounce_method":
        job_config.get_bounce_method(),
        "expected_instance_count":
        job_config.get_instances(),
        "active_shas":
        list(get_active_shas_for_marathon_apps(marathon_apps_with_clients)),
    }

    try:
        desired_app_id = job_config.format_marathon_app_dict()["id"]
    except NoDockerImageError:
        error_msg = "Docker image is not in deployments.json."
        job_status_fields["error_message"] = error_msg
        return job_status_fields

    job_status_fields["desired_app_id"] = desired_app_id

    deploy_status_for_desired_app = None
    dashboard_links = get_marathon_dashboard_links(
        settings.marathon_clients, settings.system_paasta_config)
    tasks_running = 0
    for app, marathon_client in marathon_apps_with_clients:
        deploy_status = marathon_tools.get_marathon_app_deploy_status(
            marathon_client, app)

        app_status = marathon_app_status(
            app,
            marathon_client,
            dashboard_links.get(marathon_client) if dashboard_links else None,
            deploy_status,
            list_tasks=verbose > 0,
        )
        job_status_fields["app_statuses"].append(app_status)

        if app.id.lstrip("/") == desired_app_id.lstrip("/"):
            deploy_status_for_desired_app = marathon_tools.MarathonDeployStatus.tostring(
                deploy_status)
        tasks_running += app.tasks_running

    job_status_fields["deploy_status"] = (deploy_status_for_desired_app
                                          or "Waiting for bounce")
    job_status_fields["running_instance_count"] = tasks_running

    if verbose > 0:
        autoscaling_info = get_autoscaling_info(marathon_apps_with_clients,
                                                job_config)
        if autoscaling_info is not None:
            autoscaling_info_dict = autoscaling_info._asdict()

            for field in ("current_utilization", "target_instances"):
                if autoscaling_info_dict[field] is None:
                    del autoscaling_info_dict[field]

            job_status_fields["autoscaling_info"] = autoscaling_info_dict

    return job_status_fields