# 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
import string

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)


def _GetMetdataValue(metadata, key):
  """Finds a value corresponding to a given metadata key.

  Args:
    metadata: metadata object, i.e. a dict containing containing 'items'
      - a list of key-value pairs.
    key: name of the key.

  Returns:
    Corresponding value or None if it was not found.
  """
  for item in metadata['items']:
    if item['key'] == key:
      return item['value']
  return None


def _UpdateMetadataValue(metadata, key, value):
  """Updates a single key-value pair in a metadata object.

  Args:
    metadata: metadata object, i.e. a dict containing containing 'items'
      - a list of key-value pairs.
    key: name of the key.
    value: new value for the key, or None if it should be removed.
  """
  items = metadata.setdefault('items', [])
  for item in items:
    if item['key'] == key:
      if value is None:
        items.remove(item)
      else:
        item['value'] = value
      return

  if value is not None:
    items.append({
        'key': key,
        'value': value,
    })


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

  # Project default service account and scopes.
  _DEFAULT_SERVICE_ACCOUNT_EMAIL = 'default'
  # The list is in line with what the gcloud cli uses.
  # https://cloud.google.com/sdk/gcloud/reference/compute/instances/create
  _DEFAULT_INSTANCE_SCOPES = [
      'https://www.googleapis.com/auth/cloud.useraccounts.readonly',
      'https://www.googleapis.com/auth/devstorage.read_only',
      'https://www.googleapis.com/auth/logging.write',
  ]

  # This is made public to allow easy customization of the retry behavior.
  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)

    self.region = self.GetZoneRegion(zone)

  @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 CreateAddress(self, name, region=None):
    """Reserves an external IP address.

    Args:
      name: The name to assign to the address.
      region: Region to reserved the address in.

    Returns:
      The reserved address as a string.
    """
    body = {
        'name': name,
    }
    operation = self.gce_client.addresses().insert(
        project=self.project,
        region=region or self.region,
        body=body).execute()
    self._WaitForRegionOperation(
        operation['name'], region,
        timeout_sec=self._INSTANCE_OPERATIONS_TIMEOUT_SEC)

    address = self.gce_client.addresses().get(
        project=self.project,
        region=region or self.region,
        address=name).execute()

    return address['address']

  def DeleteAddress(self, name, region=None):
    """Frees up an external IP address.

    Args:
      name: The name of the address.
      region: Region of the address.
    """
    operation = self.gce_client.addresses().delete(
        project=self.project,
        region=region or self.region,
        address=name).execute()
    self._WaitForRegionOperation(
        operation['name'], region=region or self.region,
        timeout_sec=self._INSTANCE_OPERATIONS_TIMEOUT_SEC)

  def GetZoneRegion(self, zone=None):
    """Resolves name of the region that a zone belongs to.

    Args:
      zone: The zone to resolve.

    Returns:
      Name of the region corresponding to the zone.
    """
    zone_resource = self.gce_client.zones().get(
        project=self.project,
        zone=zone or self.zone).execute()
    return string.split(zone_resource['region'], '/')[-1]

  def CreateInstance(self, name, image, zone=None, network=None,
                     machine_type=None, default_scopes=True,
                     static_address=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.
      default_scopes: If true, the default scopes are added to the instances.
      static_address: External IP address to assign to the instance as a string.
          If None an emphemeral address will be used.
      kwargs: Other possible Instance Resource properties.
          https://cloud.google.com/compute/docs/reference/latest/instances#resource
          Note that values from kwargs will overrule properties constructed from
          positinal arguments, i.e., name, image, zone, network and
          machine_type.

    Returns:
      URL to the created instance.
    """
    network = 'global/networks/%s' % network or self._DEFAULT_NETWORK
    machine_type = 'zones/%s/machineTypes/%s' % (
        zone or self.zone, machine_type or self._DEFAULT_MACHINE_TYPE)
    service_accounts = (
        {
            'email': self._DEFAULT_SERVICE_ACCOUNT_EMAIL,
            'scopes': self._DEFAULT_INSTANCE_SCOPES,
        },
    ) if default_scopes else ()

    config = {
        'name': name,
        'machineType': machine_type,
        'disks': (
            {
                'boot': True,
                'autoDelete': True,
                'initializeParams': {
                    'sourceImage': image,
                },
            },
        ),
        'networkInterfaces': (
            {
                'network': network,
                'accessConfigs': (
                    {
                        'type': 'ONE_TO_ONE_NAT',
                        'name': 'External NAT',
                    },
                ),
            },
        ),
        'serviceAccounts' : service_accounts,
    }
    config.update(**kwargs)
    if static_address is not None:
      config['networkInterfaces'][0]['accessConfigs'][0]['natIP'] = (
          static_address)
    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 StartInstance(self, name, zone=None):
    """Starts an instance with the name and waits until it's done.

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

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

    Args:
      name: Name of the instance to stop.
      zone: Zone where the instance is in. Default zone will be used if omitted.
    """
    operation = self.gce_client.instances().stop(
        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 GetCommonInstanceMetadata(self, key):
    """Looks up a single project metadata value.

    Args:
      key: Metadata key name.

    Returns:
      Metadata value corresponding to the key, or None if it was not found.
    """
    projects_data = self.gce_client.projects().get(
        project=self.project).execute()
    metadata = projects_data['commonInstanceMetadata']
    return _GetMetdataValue(metadata, key)

  def SetCommonInstanceMetadata(self, key, value):
    """Sets a single project metadata value.

    Args:
      key: Metadata key to be set.
      value: New value, or None if the given key should be removed.
    """
    projects_data = self.gce_client.projects().get(
        project=self.project).execute()
    metadata = projects_data['commonInstanceMetadata']
    _UpdateMetadataValue(metadata, key, value)
    operation = self.gce_client.projects().setCommonInstanceMetadata(
        project=self.project,
        body=metadata).execute()
    self._WaitForGlobalOperation(operation['name'])

  def GetInstanceMetadata(self, instance, key):
    """Looks up instance's metadata value.

    Args:
      instance: Name of the instance.
      key: Metadata key name.

    Returns:
      Metadata value corresponding to the key, or None if it was not found.
    """
    instance_data = self.GetInstance(instance)
    metadata = instance_data['metadata']
    return self._GetMetdataValue(metadata, key)

  def SetInstanceMetadata(self, instance, key, value):
    """Sets a single instance metadata value.

    Args:
      instance: Name of the instance.
      key: Metadata key to be set.
      value: New value, or None if the given key should be removed.
    """
    instance_data = self.GetInstance(instance)
    metadata = instance_data['metadata']
    _UpdateMetadataValue(metadata, key, value)
    operation = self.gce_client.instances().setMetadata(
        project=self.project,
        zone=self.zone,
        instance=instance,
        body=metadata).execute()
    self._WaitForZoneOperation(operation['name'])

  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 _WaitForRegionOperation(self, operation, region, timeout_sec=None,
                              timeout_handler=None):
    """Waits until a GCE RegionOperation is finished or timed out.

    Args:
      operation: The GCE operation to wait for.
      region: The region 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.regionOperations().get(
        project=self.project, region=region or self.region, 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)
