# -*- coding: utf-8 -*-
# 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

from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
from googleapiclient.http import HttpRequest
import httplib2
from oauth2client.client import GoogleCredentials

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


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."""

  # These constants are made public so that users can customize as they need.
  DEFAULT_TIMEOUT_SEC = 5 * 60
  INSTANCE_OPERATIONS_TIMEOUT_SEC = 10 * 60
  IMAGE_OPERATIONS_TIMEOUT_SEC = 10 * 60

  _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'

  # 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 zone_resource['region'].split('/')[-1]

  def CreateInstance(self, name, image, zone=None, network=None, subnet=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.
      subnet: The subnet to create the instance in.
      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.
    """
    logging.info('Creating instance "%s" with image "%s" ...', name, image)
    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)
    if subnet is not None:
      region = self.GetZoneRegion(zone)
      config['networkInterfaces'][0]['subnetwork'] = (
          'regions/%s/subnetworks/%s' % (region, subnet)
      )
    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.
    """
    logging.info('Deleting instance "%s" ...', name)
    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.
    """
    logging.info('Starting instance "%s" ...', name)
    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.
    """
    logging.info('Stopping instance "%s" ...', name)
    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.
    """
    logging.info('Creating image "%s" with "source" %s ...', name, source)
    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.
    """
    logging.info('Deleting image "%s" ...', name)
    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 GetInstanceInternalIP(self, instance, zone=None):
    """Gets the internal IP of an instance."""
    result = self.GetInstance(instance, zone)
    try:
      return result['networkInterfaces'][0]['networkIP']
    except (KeyError, IndexError):
      raise Error('Failed to get internal IP 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.

    Raises:
      Error when timeout happens or the operation fails.
    """
    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.

    Raises:
      Error when timeout happens or the operation fails.
    """
    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.

    Raises:
      Error when timeout happens or the operation fails.
    """
    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.

    Raises:
      Error when timeout happens or the operation fails.
    """
    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 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)
