# vim: tabstop=4 shiftwidth=4 softtabstop=4

# Copyright 2010 OpenStack LLC.
# All Rights Reserved.
#
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
#    not use this file except in compliance with the License. You may obtain
#    a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
#    License for the specific language governing permissions and limitations
#    under the License.
"""Implementation of an image service that uses Glance as the backend"""

from __future__ import absolute_import

import datetime as dt

from glance.common import exception as glance_exception

from nova import exception
from nova import flags
from nova import log as logging
from nova import utils
from nova.image import service


LOG = logging.getLogger('nova.image.glance')

FLAGS = flags.FLAGS

GlanceClient = utils.import_class('glance.client.Client')


class GlanceImageService(service.BaseImageService):
    """Provides storage and retrieval of disk image objects within Glance."""

    def __init__(self, client=None):
        if client is None:
            self.client = GlanceClient(FLAGS.glance_host, FLAGS.glance_port)
        self.client = client

    def index(self, context):
        """
        Calls out to Glance for a list of images available
        """
        return self.client.get_images()

    def detail(self, context):
        """
        Calls out to Glance for a list of detailed image information
        """
        return self.client.get_images_detailed()

    def show(self, context, image_id):
        """
        Returns a dict containing image data for the given opaque image id.
        """
        try:
            image = self.client.get_image_meta(image_id)
            if 'created_at' in image:
                image['created_at'] = \
                        dt.datetime.strptime(image['created_at'],
                                             "%Y-%m-%dT%H:%M:%S.%f")
            if 'updated_at' in image:
                image['updated_at'] = \
                        dt.datetime.strptime(image['updated_at'],
                                             "%Y-%m-%dT%H:%M:%S.%f")
            if 'deleted_at' in image and image['deleted_at'] is not None:
                image['deleted_at'] = \
                        dt.datetime.strptime(image['deleted_at'],
                                             "%Y-%m-%dT%H:%M:%S.%f")
        except glance_exception.NotFound:
            raise exception.NotFound
        return image

    def show_by_name(self, context, name):
        """
        Returns a dict containing image data for the given name.
        """
        # TODO(vish): replace this with more efficient call when glance
        #             supports it.
        images = self.detail(context)
        image = None
        for cantidate in images:
            if name == cantidate.get('name'):
                image = cantidate
                break
        if image is None:
            raise exception.NotFound
        return image

    def get(self, context, image_id, data):
        """
        Calls out to Glance for metadata and data and writes data.
        """
        try:
            metadata, image_chunks = self.client.get_image(image_id)
        except glance_exception.NotFound:
            raise exception.NotFound
        for chunk in image_chunks:
            data.write(chunk)
        return metadata

    def create(self, context, metadata, data=None):
        """
        Store the image data and return the new image id.

        :raises AlreadyExists if the image already exist.

        """
        return self.client.add_image(metadata, data)

    def update(self, context, image_id, metadata, data=None):
        """Replace the contents of the given image with the new data.

        :raises NotFound if the image does not exist.

        """
        try:
            result = self.client.update_image(image_id, metadata, data)
        except glance_exception.NotFound:
            raise exception.NotFound
        return result

    def delete(self, context, image_id):
        """
        Delete the given image.

        :raises NotFound if the image does not exist.

        """
        try:
            result = self.client.delete_image(image_id)
        except glance_exception.NotFound:
            raise exception.NotFound
        return result

    def delete_all(self):
        """
        Clears out all images
        """
        pass

@@ -1977,249 +1977,193 @@
     
-    if 'created_at' in image:%0A                image%5B'created_at'%5D = %5C%0A                        dt.date
+except glance_exception.NotFound:%0A            raise exception.NotFound%0A        return self._convert_
 time
-.
 st
-rp
+amps_to_date
 time
+s
 (image
-%5B'created_at'%5D,%0A                                             %22%25Y-%25m-%25dT%25H:%25M:%25S.%25f%22)%0A            if 'updated_at' in
+)%0A%0A    def _convert_timestamps_to_datetimes(self,
  image
+)
 :%0A  
@@ -2164,32 +2164,36 @@
 e):%0A        
+%22%22%22%0A
         
 image%5B'updat
@@ -2184,31 +2184,79 @@
     
-image%5B'updated_at'%5D = %5C
+Returns image with known timestamp fields converted to datetime objects
 %0A   
@@ -2256,32 +2256,36 @@
 cts%0A        
+%22%22%22%0A
         
         dt.d
@@ -2276,126 +2276,63 @@
     
-        dt.datetime.strptime(image%5B'updated_at'%5D,%0A                                             %22%25Y-%25m-%25dT%25H:%25M:%25S.%25f%22)
+for attr in %5B'created_at', 'updated_at', 'deleted_at'%5D:
 %0A   
@@ -2343,28 +2343,20 @@
      if 
-'deleted_at'
+attr
  in imag
@@ -2367,28 +2367,20 @@
 d image%5B
-'deleted_at'
+attr
 %5D is not
@@ -2412,91 +2412,145 @@
 age%5B
-'deleted_at'%5D = %5C%0A                        dt.date
+attr%5D = self._parse_glance_iso8601_timestamp(image%5Battr%5D)%0A        return image%0A%0A    def _parse_glance_iso8601_
 time
-.
 st
-rptime(image%5B'deleted_at'%5D,
+amp(self, timestamp):
 %0A   
@@ -2550,35 +2550,36 @@
 p):%0A        
-   
+%22%22%22%0A
         
             
@@ -2566,32 +2566,83 @@
         
-        
+Parse a subset of iso8601 timestamps into datetime objects%0A
         
         
@@ -2633,24 +2633,28 @@
         
+%22%22%22%0A
         
   %22%25Y-%25m
@@ -2649,133 +2649,70 @@
     
-  %22%25Y-%25m-%25dT%25H:%25M:%25S.%25f%22)%0A        except glance_exception.NotFound:%0A            raise exception.NotFound%0A        return image
+return dt.datetime.strptime(timestamp, %22%25Y-%25m-%25dT%25H:%25M:%25S.%25f%22)
 %0A%0A  

refactor to simpler implementation