# Copyright 2015 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.

"""A convinient wrapper of the GCE python API.

Public methods in class GceContext raise HttpError when the underlining call to
Google API fails, or gce.Error on other failures.
"""

from __future__ import print_function

import httplib2

from chromite.lib import cros_logging as logging
from chromite.lib import timeout_util
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
from googleapiclient.http import HttpRequest
from oauth2client.client import GoogleCredentials


class Error(Exception):
  """Base exception for this module."""


class ResourceNotFoundError(Error):
  """Exceptions raised when requested GCE resource was not found."""


class RetryOnServerErrorHttpRequest(HttpRequest):
  """A HttpRequest that will be retried on server errors automatically."""

  def __init__(self, num_retries, *args, **kwargs):
    """Constructor for RetryOnServerErrorHttpRequest."""
    self.num_retries = num_retries
    super(RetryOnServerErrorHttpRequest, self).__init__(*args, **kwargs)

  def execute(self, http=None, num_retries=None):
    """Excutes a RetryOnServerErrorHttpRequest.

    HttpRequest.execute() has the option of automatically retrying on server
    errors, i.e., 500 status codes. Call it with a non-zero value of
    |num_retries| will cause failed requests to be retried.

    Args:
      http: The httplib2.http to send this request through.
      num_retries: Number of retries. Class default value will be used if
          omitted.

    Returns:
      A deserialized object model of the response body as determined
          by the postproc. See HttpRequest.execute().
    """
    return super(RetryOnServerErrorHttpRequest, self).execute(
        http=http, num_retries=num_retries or self.num_retries)


class GceContext(object):
  """A convinient wrapper around the GCE Python API."""

  _GCE_SCOPES = (
      'https://www.googleapis.com/auth/compute',  # CreateInstance, CreateImage
      'https://www.googleapis.com/auth/devstorage.full_control', # CreateImage
  )
  _DEFAULT_NETWORK = 'default'
  _DEFAULT_MACHINE_TYPE = 'n1-standard-8'
  _DEFAULT_TIMEOUT_SEC = 5 * 60
  _INSTANCE_OPERATIONS_TIMEOUT_SEC = 5 * 60
  _IMAGE_OPERATIONS_TIMEOUT_SEC = 2* 60
  RETRIES = 2

  def __init__(self, project, zone, credentials, thread_safe=False):
    """Initializes GceContext.

    Args:
      project: The GCP project to create instances in.
      zone: The default zone to create instances in.
      credentials: The credentials used to call the GCE API.
      thread_safe: Whether the client is expected to be thread safe.
    """
    self.project = project
    self.zone = zone

    def _BuildRequest(http, *args, **kwargs):
      """Custom request builder."""
      return self._BuildRetriableRequest(self.RETRIES, http, thread_safe,
                                         credentials, *args, **kwargs)

    self.gce_client = build('compute', 'v1', credentials=credentials,
                            requestBuilder=_BuildRequest)

  @classmethod
  def ForServiceAccount(cls, project, zone, json_key_file):
    """Creates a GceContext using service account credentials.

    About service account:
    https://developers.google.com/api-client-library/python/auth/service-accounts

    Args:
      project: The GCP project to create images and instances in.
      zone: The default zone to create instances in.
      json_key_file: Path to the service account JSON key.

    Returns:
      GceContext.
    """
    credentials = GoogleCredentials.from_stream(json_key_file).create_scoped(
        cls._GCE_SCOPES)
    return GceContext(project, zone, credentials)

  @classmethod
  def ForServiceAccountThreadSafe(cls, project, zone, json_key_file):
    """Creates a thread-safe GceContext using service account credentials.

    About service account:
    https://developers.google.com/api-client-library/python/auth/service-accounts

    Args:
      project: The GCP project to create images and instances in.
      zone: The default zone to create instances in.
      json_key_file: Path to the service account JSON key.

    Returns:
      GceContext.
    """
    credentials = GoogleCredentials.from_stream(json_key_file).create_scoped(
        cls._GCE_SCOPES)
    return GceContext(project, zone, credentials, thread_safe=True)

  def CreateInstance(self, name, image, zone=None, network=None,
                     machine_type=None, **kwargs):
    """Creates an instance with the given image and waits until it's ready.

    Args:
      name: Instance name.
      image: Fully spelled URL of the image, e.g., for private images,
          'global/images/my-private-image', or for images from a
          publicly-available project,
          'projects/debian-cloud/global/images/debian-7-wheezy-vYYYYMMDD'.
          Details:
          https://cloud.google.com/compute/docs/reference/latest/instances/insert
      zone: The zone to create the instance in. Default zone will be used if
          omitted.
      network: An existing network to create the instance in. Default network
          will be used if omitted.
      machine_type: The machine type to use. Default machine type will be used
          if omitted.
      kwargs: Other possible Instance Resource properties.
          https://cloud.google.com/compute/docs/reference/latest/instances#resource

    Returns:
      URL to the created instance.
    """
    machine_type = 'zones/%s/machineTypes/%s' % (
        zone or self.zone, machine_type or self._DEFAULT_MACHINE_TYPE)
    # Allow machineType overriding.
    if 'machineType' in kwargs:
      machine_type = kwargs['machineType']

    config = {
        'name': name,
        'machineType': machine_type,
        'disks': (
            {
                'boot': True,
                'autoDelete': True,
                'initializeParams': {
                    'sourceImage': image,
                },
            },
        ),
        'networkInterfaces': (
            {
                'network': ('global/networks/%s' % network or
                            self._DEFAULT_NETWORK),
                'accessConfigs': (
                    {
                        'type': 'ONE_TO_ONE_NAT',
                        'name': 'External NAT',
                    },
                ),
            },
        ),
    }
    config.update(**kwargs)
    operation = self.gce_client.instances().insert(
        project=self.project,
        zone=zone or self.zone,
        body=config).execute()
    self._WaitForZoneOperation(
        operation['name'],
        timeout_sec=self._INSTANCE_OPERATIONS_TIMEOUT_SEC,
        timeout_handler=lambda: self.DeleteInstance(name))
    return operation['targetLink']

  def DeleteInstance(self, name, zone=None):
    """Deletes an instance with the name and waits until it's done.

    Args:
      name: Name of the instance to delete.
      zone: Zone where the instance is in. Default zone will be used if omitted.
    """
    operation = self.gce_client.instances().delete(
        project=self.project,
        zone=zone or self.zone,
        instance=name).execute()
    self._WaitForZoneOperation(
        operation['name'], timeout_sec=self._INSTANCE_OPERATIONS_TIMEOUT_SEC)

  def CreateImage(self, name, source):
    """Creates an image with the given |source|.

    Args:
      name: Name of the image to be created.
      source:
        Google Cloud Storage object of the source disk, e.g.,
        'https://storage.googleapis.com/my-gcs-bucket/test_image.tar.gz'.

    Returns:
      URL to the created image.
    """
    config = {
        'name': name,
        'rawDisk': {
            'source': source,
        },
    }
    operation = self.gce_client.images().insert(
        project=self.project,
        body=config).execute()
    self._WaitForGlobalOperation(operation['name'],
                                 timeout_sec=self._IMAGE_OPERATIONS_TIMEOUT_SEC,
                                 timeout_handler=lambda: self.DeleteImage(name))
    return operation['targetLink']

  def DeleteImage(self, name):
    """Deletes an image and waits until it's deleted.

    Args:
      name: Name of the image to delete.
    """
    operation = self.gce_client.images().delete(
        project=self.project,
        image=name).execute()
    self._WaitForGlobalOperation(operation['name'],
                                 timeout_sec=self._IMAGE_OPERATIONS_TIMEOUT_SEC)

  def ListInstances(self, zone=None):
    """Lists all instances.

    Args:
      zone: Zone where the instances are in. Default zone will be used if
            omitted.

    Returns:
      A list of Instance Resources if found, or an empty list otherwise.
    """
    result = self.gce_client.instances().list(project=self.project,
                                              zone=zone or self.zone).execute()
    return result.get('items', [])

  def ListImages(self):
    """Lists all images.

    Returns:
      A list of Image Resources if found, or an empty list otherwise.
    """
    result = self.gce_client.images().list(project=self.project).execute()
    return result.get('items', [])

  def GetInstance(self, instance, zone=None):
    """Gets an Instance Resource by name and zone.

    Args:
      instance: Name of the instance.
      zone: Zone where the instance is in. Default zone will be used if omitted.

    Returns:
      An Instance Resource.

    Raises:
      ResourceNotFoundError if instance was not found, or HttpError on other
      HTTP failures.
    """
    try:
      return self.gce_client.instances().get(project=self.project,
                                             zone=zone or self.zone,
                                             instance=instance).execute()
    except HttpError as e:
      if e.resp.status == 404:
        raise ResourceNotFoundError(
            'Instance "%s" for project "%s" in zone "%s" was not found.' %
            (instance, self.project, zone or self.zone))
      else:
        raise

  def GetInstanceIP(self, instance, zone=None):
    """Gets the external IP of an instance.

    Args:
      instance: Name of the instance to get IP for.
      zone: Zone where the instance is in. Default zone will be used if omitted.

    Returns:
      External IP address of the instance.

    Raises:
      Error: Something went wrong when trying to get IP for the instance.
    """
    result = self.GetInstance(instance, zone)
    try:
      return result['networkInterfaces'][0]['accessConfigs'][0]['natIP']
    except (KeyError, IndexError):
      raise Error('Failed to get IP address for instance %s' % instance)

  def GetImage(self, image):
    """Gets an Image Resource by name.

    Args:
      image: Name of the image to look for.

    Returns:
      An Image Resource.

    Raises:
      ResourceNotFoundError: The requested image was not found.
    """
    try:
      return self.gce_client.images().get(project=self.project,
                                          image=image).execute()
    except HttpError as e:
      if e.resp.status == 404:
        raise ResourceNotFoundError('Image "%s" for project "%s" was not found.'
                                    % (image, self.project))
      else:
        raise

  def InstanceExists(self, instance, zone=None):
    """Checks if an instance exists in the current project.

    Args:
      instance: Name of the instance to check existence of.
      zone: Zone where the instance is in. Default zone will be used if omitted.

    Returns:
      True if the instance exists or False otherwise.
    """
    try:
      return self.GetInstance(instance, zone) is not None
    except ResourceNotFoundError:
      return False

  def ImageExists(self, image):
    """Checks if an image exists in the current project.

    Args:
      image: Name of the image to check existence of.

    Returns:
      True if the instance exists or False otherwise.
    """
    try:
      return self.GetImage(image) is not None
    except ResourceNotFoundError:
      return False

  def _WaitForZoneOperation(self, operation, zone=None, timeout_sec=None,
                            timeout_handler=None):
    """Waits until a GCE ZoneOperation is finished or timed out.

    Args:
      operation: The GCE operation to wait for.
      zone: The zone that |operation| belongs to.
      timeout_sec: The maximum number of seconds to wait for.
      timeout_handler: A callable to be executed when timeout happens.
    """
    get_request = self.gce_client.zoneOperations().get(
        project=self.project, zone=zone or self.zone, operation=operation)
    self._WaitForOperation(operation, get_request, timeout_sec,
                           timeout_handler=timeout_handler)

  def _WaitForGlobalOperation(self, operation, timeout_sec=None,
                              timeout_handler=None):
    """Waits until a GCE GlobalOperation is finished or timed out.

    Args:
      operation: The GCE operation to wait for.
      timeout_sec: The maximum number of seconds to wait for.
      timeout_handler: A callable to be executed when timeout happens.
    """
    get_request = self.gce_client.globalOperations().get(project=self.project,
                                                         operation=operation)
    self._WaitForOperation(operation, get_request, timeout_sec=timeout_sec,
                           timeout_handler=timeout_handler)

  def _WaitForOperation(self, operation, get_operation_request,
                        timeout_sec=None, timeout_handler=None):
    """Waits until timeout or the request gets a response with a 'DONE' status.

    Args:
      operation: The GCE operation to wait for.
      get_operation_request:
        The HTTP request to get the operation's status.
        This request will be executed periodically until it returns a status
        'DONE'.
      timeout_sec: The maximum number of seconds to wait for.
      timeout_handler: A callable to be executed when times out.
    """
    def _IsDone():
      result = get_operation_request.execute()
      if result['status'] == 'DONE':
        if 'error' in result:
          raise Error(result['error'])
        return True
      return False

    try:
      timeout = timeout_sec or self._DEFAULT_TIMEOUT_SEC
      logging.info('Waiting up to %d seconds for operation [%s] to complete...',
                   timeout, operation)
      timeout_util.WaitForReturnTrue(_IsDone, timeout, period=1)
    except timeout_util.TimeoutError:
      if not timeout_handler:
        timeout_handler()
      raise Error('Timeout wating for operation [%s] to complete' % operation)

  def _BuildRetriableRequest(self, num_retries, http, thread_safe=False,
                             credentials=None, *args, **kwargs):
    """Builds a request that will be automatically retried on server errors.

    Args:
      num_retries: The maximum number of times to retry until give up.
      http: An httplib2.Http object that this request will be executed through.
      thread_safe: Whether or not the request needs to be thread-safe.
      credentials: Credentials to apply to the request.
      *args: Optional positional arguments.
      **kwargs: Optional keyword arguments.

    Returns:
      RetryOnServerErrorHttpRequest: A request that will automatically retried
          on server errors.
    """
    if thread_safe:
      # Create a new http object for every request.
      http = credentials.authorize(httplib2.Http())
    return RetryOnServerErrorHttpRequest(num_retries, http, *args, **kwargs)
