# Copyright 2016 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Prod host metrics"""

from __future__ import absolute_import
from __future__ import print_function
from __future__ import unicode_literals

import collections
import json
import subprocess

from chromite.lib import cros_logging as logging
from chromite.lib import metrics

_METRIC_ROOT_PATH = 'prod_hosts/'
_ATEST_PROGRAM = '/usr/local/autotest/cli/atest'

logger = logging.getLogger(__name__)


class _ProdHostReporter(object):
  """Prod host metrics reporter.

  ProdHostReporter takes source and sinks arguments.  Sources have a
  get_servers() method that returns prod host information as an iterable
  of Server instances.  Sinks have a write_servers() method for
  reporting the server information.
  """

  def __init__(self, source, sinks=()):
    """Initialize instance.

    Args:
      source: Source for getting prod host information.
      sinks: Sinks for writing prod host information.
    """
    self._source = source
    self._sinks = sinks

  def __call__(self):
    """Report prod hosts."""
    servers = list(self._source.get_servers())
    for sink in self._sinks:
      sink.write_servers(servers)


class _AtestSource(object):
  """Source for prod host information, using atest."""

  def __init__(self, atest_program):
    """Initialize instance.

    Args:
      atest_program: atest program as full path or name on the search path.
      parser: Parser to use for atest output.
    """
    self._atest_program = atest_program

  def _query_atest_for_servers(self):
    """Run atest to get host information.

    Returns:
      atest output as a string (specifically, a bytestring)
    """
    return subprocess.check_output(
        [self._atest_program, 'server', 'list', '--json'])

  def get_servers(self):
    """Get server information from this source.

    Returns:
      Iterable of Server instances.
    """
    server_dicts = json.loads(self._query_atest_for_servers())
    for server in server_dicts:
      yield Server(
          hostname=server['hostname'],
          status=server['status'],
          roles=tuple(server['roles']),
          created=server['date_created'],
          modified=server['date_modified'],
          note=server['note'])


Server = collections.namedtuple(
    'Server', 'hostname,status,roles,created,modified,note')


class _TsMonSink(object):
  """Sink using ts_mon to report Monarch metrics."""

  def __init__(self, metric_root_path):
    """Initialize instance.

    Args:
      metric_root_path: Path for ts_mon metrics.  Should end in a slash.
    """
    if not metric_root_path.endswith('/'):
      raise ValueError('metric_root_path should end with slash',
                       metric_root_path)
    self._metric_root_path = metric_root_path

  def write_servers(self, servers):
    """Write server information.

    Args:
      servers: Iterable of Server instances.
    """
    for server in servers:
      fields = {
          'target_hostname': server.hostname,
      }
      self._presence_metric.set(True, fields)
      self._roles_metric.set(self._format_roles(server.roles), fields)

  @property
  def _presence_metric(self):
    return metrics.Boolean(self._metric_root_path + 'presence')

  @property
  def _roles_metric(self):
    return metrics.String(self._metric_root_path + 'roles')

  def _format_roles(self, roles):
    return ','.join(sorted(roles))


class _LoggingSink(object):
  """Sink using Python's logging facilities."""

  def write_servers(self, servers):
    """Write server information.

    Args:
      servers: Iterable of Server instances.
    """
    for server in servers:
      logger.debug('Server: %r', server)


collect_prod_hosts = _ProdHostReporter(
    source=_AtestSource(_ATEST_PROGRAM),
    sinks=(_TsMonSink(_METRIC_ROOT_PATH), _LoggingSink()))
