|
|
|
@ -13,14 +13,18 @@
|
|
|
|
|
# License for the specific language governing permissions and limitations |
|
|
|
|
# under the License. |
|
|
|
|
|
|
|
|
|
from functools import wraps |
|
|
|
|
import os |
|
|
|
|
import shutil |
|
|
|
|
import subprocess |
|
|
|
|
import time |
|
|
|
|
|
|
|
|
|
from functools import wraps |
|
|
|
|
|
|
|
|
|
from six.moves import urllib |
|
|
|
|
from tempest.lib import exceptions |
|
|
|
|
from tenacity import RetryError |
|
|
|
|
from tenacity import Retrying |
|
|
|
|
from tenacity import stop_after_attempt |
|
|
|
|
|
|
|
|
|
from config_tempest import constants as C |
|
|
|
|
from config_tempest.services.base import VersionedService |
|
|
|
@ -78,7 +82,7 @@ class ImageService(VersionedService):
|
|
|
|
|
def set_versions(self): |
|
|
|
|
super(ImageService, self).set_versions(top_level=False) |
|
|
|
|
|
|
|
|
|
def create_tempest_images(self, conf): |
|
|
|
|
def create_tempest_images(self, conf, retry_alt=False): |
|
|
|
|
"""Uploads an image to the glance. |
|
|
|
|
|
|
|
|
|
The method creates images specified in conf, if they're not created |
|
|
|
@ -113,20 +117,22 @@ class ImageService(VersionedService):
|
|
|
|
|
image_id = conf.get('compute', 'image_ref') |
|
|
|
|
image_id = self.find_or_upload_image(image_id, name, |
|
|
|
|
image_source=image_path, |
|
|
|
|
image_dest=img_path) |
|
|
|
|
image_dest=img_path, |
|
|
|
|
retry_alt=retry_alt) |
|
|
|
|
alt_image_id = None |
|
|
|
|
if conf.has_option('compute', 'image_ref_alt'): |
|
|
|
|
alt_image_id = conf.get('compute', 'image_ref_alt') |
|
|
|
|
alt_image_id = self.find_or_upload_image(alt_image_id, alt_name, |
|
|
|
|
image_source=image_path, |
|
|
|
|
image_dest=img_path) |
|
|
|
|
image_dest=img_path, |
|
|
|
|
retry_alt=retry_alt) |
|
|
|
|
# get name of the image_id |
|
|
|
|
conf.set('scenario', 'img_file', img_path) |
|
|
|
|
conf.set('compute', 'image_ref', image_id) |
|
|
|
|
conf.set('compute', 'image_ref_alt', alt_image_id) |
|
|
|
|
|
|
|
|
|
def find_or_upload_image(self, image_id, image_name, image_source='', |
|
|
|
|
image_dest=''): |
|
|
|
|
image_dest='', retry_alt=False): |
|
|
|
|
"""If the image is not found, uploads it. |
|
|
|
|
|
|
|
|
|
:type image_id: string |
|
|
|
@ -145,11 +151,17 @@ class ImageService(VersionedService):
|
|
|
|
|
C.LOG.info("Creating image '%s'", image_name) |
|
|
|
|
if image_source.startswith("http:") or \ |
|
|
|
|
image_source.startswith("https:"): |
|
|
|
|
self._download_file(image_source, image_dest) |
|
|
|
|
try: |
|
|
|
|
self._download_file(image_source, image_dest) |
|
|
|
|
# We only download alternative image if the default image |
|
|
|
|
# fails |
|
|
|
|
except Exception: |
|
|
|
|
if retry_alt: |
|
|
|
|
self._download_with_retry(image_dest) |
|
|
|
|
else: |
|
|
|
|
try: |
|
|
|
|
shutil.copyfile(image_source, image_dest) |
|
|
|
|
except IOError: |
|
|
|
|
except Exception: |
|
|
|
|
# let's try if this is the case when a user uses already |
|
|
|
|
# existing image in glance which is not uploaded as *_alt |
|
|
|
|
if image_name[-4:] == "_alt": |
|
|
|
@ -159,10 +171,25 @@ class ImageService(VersionedService):
|
|
|
|
|
if not os.path.isfile(path): |
|
|
|
|
self._download_image(image['id'], path) |
|
|
|
|
else: |
|
|
|
|
raise IOError |
|
|
|
|
if retry_alt: |
|
|
|
|
self._download_with_retry(image_dest) |
|
|
|
|
else: |
|
|
|
|
raise IOError |
|
|
|
|
image = self._upload_image(image_name, image_dest) |
|
|
|
|
return image['id'] |
|
|
|
|
|
|
|
|
|
def _download_with_retry(self, destination): |
|
|
|
|
retry_attempt = -1 |
|
|
|
|
attempts = len(C.DEFAULT_IMAGES) |
|
|
|
|
try: |
|
|
|
|
for attempt in Retrying(stop=stop_after_attempt(attempts)): |
|
|
|
|
retry_attempt += 1 |
|
|
|
|
with attempt: |
|
|
|
|
self._download_file(C.DEFAULT_IMAGES[retry_attempt], |
|
|
|
|
destination) |
|
|
|
|
except RetryError: |
|
|
|
|
pass |
|
|
|
|
|
|
|
|
|
def _find_image(self, image_id, image_name): |
|
|
|
|
"""Find image by ID or name (the image client doesn't have this). |
|
|
|
|
|
|
|
|
|