134 lines
5.3 KiB
Python
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
|