charm-nova-lxd/tests/lxd_amulet_utils.py

134 lines
5.3 KiB
Python

# Copyright 2016 Canonical Ltd
#
# 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.
# Temporary Local Helpers - Extends OpenStackAmuletUtils
# ============================================================================
# NOTE:
# Move to charmhelpers/contrib/openstack/amulet/utils.py once
# validated and settled.
#
# These helpers are and should be written in a way that they
# are not LXD-specific. They should default to KVM/x86_64
# with enough parameters plumbed to allow LXD.
#
import amulet
import logging
import os
import urllib
from charmhelpers.contrib.openstack.amulet.utils import (
OpenStackAmuletUtils
)
DEBUG = logging.DEBUG
ERROR = logging.ERROR
# LXD_IMAGE_URL = 'http://cloud-images.ubuntu.com/trusty/current/trusty-server-cloudimg-amd64-root.tar.xz' # noqa
class LXDAmuletUtils(OpenStackAmuletUtils):
"""LXD amulet utilities.
This class inherits from AmuletUtils and has additional support
that is specifically for use by OpenStack charm tests.
"""
def __init__(self, log_level=ERROR):
"""Initialize the deployment environment."""
super(LXDAmuletUtils, self).__init__(log_level)
# NOTE(beisner): to eventually replace the existing amulet openstack
# glance image creation helper method. Plopped here to fine-tune and
# make more flexible.
def glance_create_image(self, glance, image_name, image_url,
download_dir='tests',
hypervisor_type='qemu',
disk_format='qcow2',
architecture='x86_64',
container_format='bare'):
"""Download an image and upload it to glance, validate its status
and return an image object pointer. KVM defaults, can override for
LXD.
:param glance: pointer to authenticated glance api connection
:param image_name: display name for new image
:param image_url: url to retrieve
:param download_dir: directory to store downloaded image file
:param hypervisor_type: glance image hypervisor property
:param disk_format: glance image disk format
:param architecture: glance image architecture property
:param container_format: glance image container format
:returns: glance image pointer
"""
self.log.debug('Creating glance image ({}) from '
'{}...'.format(image_name, image_url))
# Download image
http_proxy = os.getenv('AMULET_HTTP_PROXY')
self.log.debug('AMULET_HTTP_PROXY: {}'.format(http_proxy))
if http_proxy:
proxies = {'http': http_proxy}
opener = urllib.FancyURLopener(proxies)
else:
opener = urllib.FancyURLopener()
abs_file_name = os.path.join(download_dir, image_name)
if not os.path.exists(abs_file_name):
opener.retrieve(image_url, abs_file_name)
# Create glance image
glance_properties = {
'architecture': architecture,
'hypervisor_type': hypervisor_type
}
with open(abs_file_name) as f:
image = glance.images.create(name=image_name,
is_public=True,
disk_format=disk_format,
container_format=container_format,
properties=glance_properties,
data=f)
# Wait for image to reach active status
img_id = image.id
ret = self.resource_reaches_status(glance.images, img_id,
expected_stat='active',
msg='Image status wait')
if not ret:
msg = 'Glance image failed to reach expected state.'
amulet.raise_status(amulet.FAIL, msg=msg)
# Re-validate new image
self.log.debug('Validating image attributes...')
val_img_name = glance.images.get(img_id).name
val_img_stat = glance.images.get(img_id).status
val_img_pub = glance.images.get(img_id).is_public
val_img_cfmt = glance.images.get(img_id).container_format
val_img_dfmt = glance.images.get(img_id).disk_format
msg_attr = ('Image attributes - name:{} public:{} id:{} stat:{} '
'container fmt:{} disk fmt:{}'.format(
val_img_name, val_img_pub, img_id,
val_img_stat, val_img_cfmt, val_img_dfmt))
if val_img_name == image_name and val_img_stat == 'active' \
and val_img_pub is True and val_img_cfmt == container_format \
and val_img_dfmt == disk_format:
self.log.debug(msg_attr)
else:
msg = ('Image validation failed, {}'.format(msg_attr))
amulet.raise_status(amulet.FAIL, msg=msg)
return image