# 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 print_function

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)


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