Ejemplo n.º 1
0
def _get_container_labels(container, parent_pod):
    """Returns key/value pairs identifying all metrics of this container.

  Args:
    container: the container object to annotate.
    parent_pod: the parent pod of 'container'.

  Returns:
  A dictionary of key/value pairs.
  If any error was detected, returns None.
  """
    if not utilities.is_wrapped_object(container, "Container"):
        return None
    if not utilities.is_wrapped_object(parent_pod, "Pod"):
        return None

    pod_id = utilities.get_attribute(parent_pod, ["properties", "metadata", "uid"])
    if not utilities.valid_string(pod_id):
        return None

    hostname = utilities.get_attribute(parent_pod, ["properties", "spec", "host"])
    if not utilities.valid_string(hostname):
        return None

    short_container_name = utilities.get_short_container_name(container, parent_pod)

    if not utilities.valid_string(short_container_name):
        return None

    return {"pod_id": pod_id, "hostname": hostname, "container_name": short_container_name}
Ejemplo n.º 2
0
 def test_get_short_container_name(self):
   """Tests get_short_container_name()."""
   container = {
       'annotations': {
           'label': 'php-redis/c6bf48e9b60c',
       },
       'id': 'k8s_php-redis.526c9b3e_guestbook-controller-14zj2_default',
       'properties': {
           'Id': 'deadbeef',
           'Image': '01234567',
           'Name': '/k8s_php-redis.526c9b3e_guestbook-controller-14zj2_default'
       },
       'timestamp': '2015-05-29T18:42:52.217499',
       'type': 'Container'
   }
   parent_pod = {
       'annotations': {
           'label': 'guestbook-controller-14zj2'
       },
       'id': 'guestbook-controller-14zj2',
       'properties': {
           'status': {
               'containerStatuses': [
                   {
                       'containerID': 'docker://deadbeef',
                       'image': 'brendanburns/php-redis',
                       'name': 'php-redis'
                   }
               ],
               'hostIP': '104.154.34.132',
               'phase': 'Running',
               'podIP': '10.64.0.5'
           }
       },
       'timestamp': '2015-05-29T18:37:04.852412',
       'type': 'Pod'
   }
   self.assertEqual(
       'php-redis',
       utilities.get_short_container_name(container, parent_pod))
Ejemplo n.º 3
0
def _get_container_labels(container, parent_pod):
  """Returns key/value pairs identifying all metrics of this container.

  Args:
    container: the container object to annotate.
    parent_pod: the parent pod of 'container'.

  Returns:
  A dictionary of key/value pairs.
  If any error was detected, returns None.
  """
  if not utilities.is_wrapped_object(container, 'Container'):
    return None
  if not utilities.is_wrapped_object(parent_pod, 'Pod'):
    return None

  pod_id = utilities.get_attribute(
      parent_pod, ['properties', 'metadata', 'uid'])
  if not utilities.valid_string(pod_id):
    return None

  hostname = utilities.get_attribute(
      parent_pod, ['properties', 'spec', 'host'])
  if not utilities.valid_string(hostname):
    return None

  short_container_name = utilities.get_short_container_name(
      container, parent_pod)

  if not utilities.valid_string(short_container_name):
    return None

  return {
      'pod_id': pod_id,
      'hostname': hostname,
      'container_name': short_container_name
  }
Ejemplo n.º 4
0
def _get_container_labels(container, parent_pod):
    """Returns key/value pairs identifying all metrics of this container.

  Args:
    container: the container object to annotate.
    parent_pod: the parent pod of 'container'.

  Returns:
  A dictionary of key/value pairs.
  If any error was detected, returns None.
  """
    if not utilities.is_wrapped_object(container, 'Container'):
        return None
    if not utilities.is_wrapped_object(parent_pod, 'Pod'):
        return None

    pod_id = utilities.get_attribute(parent_pod,
                                     ['properties', 'metadata', 'uid'])
    if not utilities.valid_string(pod_id):
        return None

    hostname = utilities.get_attribute(parent_pod,
                                       ['properties', 'spec', 'host'])
    if not utilities.valid_string(hostname):
        return None

    short_container_name = utilities.get_short_container_name(
        container, parent_pod)

    if not utilities.valid_string(short_container_name):
        return None

    return {
        'pod_id': pod_id,
        'hostname': hostname,
        'container_name': short_container_name
    }
Ejemplo n.º 5
0
def get_containers(gs, docker_host):
  """Gets the list of all containers in 'docker_host'.

  Args:
    gs: global state.
    docker_host: the Docker host running the containers.

  Returns:
    list of wrapped container objects.
    Each element in the list is the result of
    utilities.wrap_object(container, 'Container', ...)

  Raises:
    CollectorError: in case of failure to fetch data from Docker.
    Other exceptions may be raised due to exectution errors.
  """
  containers, timestamp = gs.get_containers_cache().lookup(docker_host)
  if timestamp is not None:
    gs.logger_info(
        'get_containers(docker_host=%s) cache hit returns '
        '%d containers', docker_host, len(containers))
    return containers

  url = 'http://{docker_host}:{port}/containers/json'.format(
      docker_host=docker_host, port=gs.get_docker_port())
  # A typical value of 'docker_host' is:
  # k8s-guestbook-node-3.c.rising-apricot-840.internal
  # Use only the first period-seperated element for the test file name.
  fname = '{host}-containers'.format(host=docker_host.split('.')[0])
  try:
    containers_list = fetch_data(gs, url, fname)
  except collector_error.CollectorError:
    raise
  except:
    msg = ('fetching %s or %s failed with exception %s' %
           (url, fname, sys.exc_info()[0]))
    gs.logger_exception(msg)
    raise collector_error.CollectorError(msg)

  if not isinstance(containers_list, types.ListType):
    msg = 'invalid response from fetching %s' % url
    gs.logger_exception(msg)
    raise collector_error.CollectorError(msg)

  containers = []
  timestamps = []
  for container_info in containers_list:
    # NOTE: container 'Name' is stable across container re-starts whereas
    # container 'Id' is not.
    # This may be because Kubernertes assigns the Name while Docker assigns
    # the Id (?)
    # The container Name is the only element of the array 'Names' -
    # why is Names an array here?
    # skip the leading / in the Name
    if not (isinstance(container_info.get('Names'), types.ListType) and
            container_info['Names'] and
            utilities.valid_string(container_info['Names'][0]) and
            container_info['Names'][0][0] == '/'):
      msg = 'invalid containers data format. docker_host=%s' % docker_host
      gs.logger_error(msg)
      raise collector_error.CollectorError(msg)

    container_id = container_info['Names'][0][1:]
    container, ts = _inspect_container(gs, docker_host, container_id)
    if container is None:
      continue

    if not utilities.valid_string(container.get('Name')):
      msg = ('missing or invalid Name attribute in container %s' %
             container_id)
      gs.logger_error(msg)
      raise collector_error.CollectorError(msg)

    if container['Name'] != ('/' + container_id):
      msg = ('container %s\'s Name attribute is "%s"; expecting "%s"' %
             (container_id, container['Name'], '/' + container_id))
      gs.logger_error(msg)
      raise collector_error.CollectorError(msg)

    short_hex_id = utilities.object_to_hex_id(container)
    if short_hex_id is None:
      msg = 'Could not compute short hex ID of container %s' % container_id
      gs.logger_error(msg)
      raise collector_error.CollectorError(msg)

    wrapped_container = utilities.wrap_object(
        container, 'Container', container_id, ts, label=short_hex_id)
    containers.append(wrapped_container)
    timestamps.append(ts)

    # Modify the container's label after the wrapped container was added
    # to the containers list.
    # Compute the container's short name to create a better container label:
    # short_container_name/short_hex_id.
    # For example: "cassandra/d85b599c17d8".
    parent_pod_id = utilities.get_parent_pod_id(wrapped_container)
    if parent_pod_id is None:
      continue
    parent_pod = kubernetes.get_one_pod(gs, docker_host, parent_pod_id)
    if parent_pod is None:
      continue
    short_container_name = utilities.get_short_container_name(
        wrapped_container, parent_pod)
    if not utilities.valid_string(short_container_name):
      continue
    wrapped_container['annotations']['label'] = (short_container_name + '/' +
                                                 short_hex_id)

  ret_value = gs.get_containers_cache().update(
      docker_host, containers,
      min(timestamps) if timestamps else time.time())
  gs.logger_info(
      'get_containers(docker_host=%s) returns %d containers',
      docker_host, len(containers))
  return ret_value
Ejemplo n.º 6
0
 def test_get_short_container_name(self):
   """Tests get_short_container_name()."""
   self.assertEqual(
       'php-redis',
       utilities.get_short_container_name(CONTAINER, PARENT_POD))
Ejemplo n.º 7
0
def get_containers(gs, docker_host):
    """Gets the list of all containers in 'docker_host'.

  Args:
    gs: global state.
    docker_host: the Docker host running the containers.

  Returns:
    list of wrapped container objects.
    Each element in the list is the result of
    utilities.wrap_object(container, 'Container', ...)

  Raises:
    CollectorError: in case of failure to fetch data from Docker.
    Other exceptions may be raised due to exectution errors.
  """
    containers, timestamp = gs.get_containers_cache().lookup(docker_host)
    if timestamp is not None:
        gs.logger_info(
            'get_containers(docker_host=%s) cache hit returns '
            '%d containers', docker_host, len(containers))
        return containers

    url = 'http://{docker_host}:{port}/containers/json'.format(
        docker_host=docker_host, port=gs.get_docker_port())
    # A typical value of 'docker_host' is:
    # k8s-guestbook-node-3.c.rising-apricot-840.internal
    # Use only the first period-seperated element for the test file name.
    fname = '{host}-containers'.format(host=docker_host.split('.')[0])
    try:
        containers_list = fetch_data(gs, url, fname)
    except collector_error.CollectorError:
        raise
    except:
        msg = ('fetching %s or %s failed with exception %s' %
               (url, fname, sys.exc_info()[0]))
        gs.logger_exception(msg)
        raise collector_error.CollectorError(msg)

    if not isinstance(containers_list, types.ListType):
        msg = 'invalid response from fetching %s' % url
        gs.logger_exception(msg)
        raise collector_error.CollectorError(msg)

    containers = []
    timestamps = []
    for container_info in containers_list:
        # NOTE: container 'Name' is stable across container re-starts whereas
        # container 'Id' is not.
        # This may be because Kubernertes assigns the Name while Docker assigns
        # the Id (?)
        # The container Name is the only element of the array 'Names' -
        # why is Names an array here?
        # skip the leading / in the Name
        if not (isinstance(container_info.get('Names'), types.ListType)
                and container_info['Names']
                and utilities.valid_string(container_info['Names'][0])
                and container_info['Names'][0][0] == '/'):
            msg = 'invalid containers data format. docker_host=%s' % docker_host
            gs.logger_error(msg)
            raise collector_error.CollectorError(msg)

        container_id = container_info['Names'][0][1:]
        container, ts = _inspect_container(gs, docker_host, container_id)
        if container is None:
            continue

        if not utilities.valid_string(container.get('Name')):
            msg = ('missing or invalid Name attribute in container %s' %
                   container_id)
            gs.logger_error(msg)
            raise collector_error.CollectorError(msg)

        if container['Name'] != ('/' + container_id):
            msg = ('container %s\'s Name attribute is "%s"; expecting "%s"' %
                   (container_id, container['Name'], '/' + container_id))
            gs.logger_error(msg)
            raise collector_error.CollectorError(msg)

        short_hex_id = utilities.object_to_hex_id(container)
        if short_hex_id is None:
            msg = 'Could not compute short hex ID of container %s' % container_id
            gs.logger_error(msg)
            raise collector_error.CollectorError(msg)

        wrapped_container = utilities.wrap_object(container,
                                                  'Container',
                                                  container_id,
                                                  ts,
                                                  label=short_hex_id)
        containers.append(wrapped_container)
        timestamps.append(ts)

        # Modify the container's label after the wrapped container was added
        # to the containers list.
        # Compute the container's short name to create a better container label:
        # short_container_name/short_hex_id.
        # For example: "cassandra/d85b599c17d8".
        parent_pod_id = utilities.get_parent_pod_id(wrapped_container)
        if parent_pod_id is None:
            continue
        parent_pod = kubernetes.get_one_pod(gs, docker_host, parent_pod_id)
        if parent_pod is None:
            continue
        short_container_name = utilities.get_short_container_name(
            wrapped_container, parent_pod)
        if not utilities.valid_string(short_container_name):
            continue
        wrapped_container['annotations']['label'] = (short_container_name +
                                                     '/' + short_hex_id)

    ret_value = gs.get_containers_cache().update(
        docker_host, containers,
        min(timestamps) if timestamps else time.time())
    gs.logger_info('get_containers(docker_host=%s) returns %d containers',
                   docker_host, len(containers))
    return ret_value