Source code for ubuntufinder.actions

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import csv

try:
    from StringIO import StringIO
except ImportError:
    from io import StringIO

import requests

from ubuntufinder.exceptions import ImageNotFound, LatestReleaseNotFound, ServiceUnavailable
from ubuntufinder.models import SearchImage, Image


CLOUD_IMAGES_SERVER = "https://cloud-images.ubuntu.com/query" # The server that serves the Cloud Images
CLOUD_IMAGES_LIST_FILE = "released.current.txt"
CLOUD_IMAGES_RELEASES_FILE = "released.latest.txt"
CLOUD_IMAGES_CSV_SEPARATOR = "\t"

LATEST = "latest"  # Code to search for the latest release


def _open_csv_from_url(url, _session=None):
    """
    :param url: The URL to open

    :returns: A CSV reader from the data at URL
    :rtype: :class:`csv.reader`
    """

    session = _session or requests.Session()
    try:
        res = session.get(url)
    except requests.RequestException as e:
        raise ServiceUnavailable(e)
    return csv.reader(StringIO(res.text), delimiter=CLOUD_IMAGES_CSV_SEPARATOR)


def _find_latest_release(_session):
    """
    :returns: The latest stable (non-devel) Ubuntu release
    :rtype: str
    """

    url = "/".join([CLOUD_IMAGES_SERVER, CLOUD_IMAGES_RELEASES_FILE])
    reader = _open_csv_from_url(url, _session)

    latest_release = None
    for release, platform, status, date in reader:
        if status == "release":
            latest_release = release

    if latest_release is None:
        raise LatestReleaseNotFound()

    return latest_release


def _list_images(release, _session=None):
    """
    :rtype: list of ubuntufinder.models.Image
    """

    url = "/".join([CLOUD_IMAGES_SERVER, release, "server", CLOUD_IMAGES_LIST_FILE])
    reader = _open_csv_from_url(url, _session)
    return [Image(*entry) for entry in reader]


def _find_image(region, release, architecture, instance_type, virtualization, _session=None):
    """
    :rtype: ubuntufinder.models.Image
    """

    search_image = SearchImage(release, "server", instance_type, architecture, region, virtualization)

    for image in _list_images(release, _session):
        if search_image.matches(image):
            return image

    raise ImageNotFound()


[docs]def find_image(region, release=LATEST, architecture="amd64", instance_type="ebs", virtualization="paravirtual", _session=None): """ Return a full image specification according to the query parameters :param region: The AWS region code to locate the Image in :type region: :class:`str` :param release: The codename of the Ubuntu Release to locate. Defaults to the latest release :type release: :class:`str` :param architecture: The CPU Architecture to find the image for. Defaults to amd64 :type architecture: :class:`str` :param instance_type: The Instance type to find the image for (ebs or instance-store). Defaults to ebs. :type instance_type: :class:`str` :param virtualization: The virtualization technology to find the image for (paravirtual or hvm). :type virtualization: :class:`str` :returns: An Image corresponding to your search :rtype: :class:`ubuntufinder.models.Image` :raises: :class:`ubuntufinder.exceptions.ImageNotFound` if no match is found. :raises: :class:`ubuntufinder.exceptions.ServiceUnavailable` if Cloud Images can't be accessed. """ if release == LATEST: release = _find_latest_release(_session) return _find_image(region, release, architecture, instance_type, virtualization, _session)