From 0b3438bfbed5db128d7ac0345e121171d29bfc83 Mon Sep 17 00:00:00 2001 From: Marcus Sorensen Date: Mon, 16 Oct 2023 01:02:47 -0600 Subject: [PATCH 1/4] Update pom.xml reflections version (#8019) Addresses bug described in reflections 0.9.12 https://github.com/ronmamo/reflections/issues/273 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index b53dfad1b0ce..d50f9d8c936e 100644 --- a/pom.xml +++ b/pom.xml @@ -170,7 +170,7 @@ 2.6.6 0.6.0 0.3.0 - 0.9.12 + 0.10.2 3.4.4_1 4.0.1 1.7.0 From ba24a18f27da7e727af384d914e758c887209153 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Mon, 16 Oct 2023 18:22:05 +0530 Subject: [PATCH 2/4] kvm: fix direct download template size (#8093) Signed-off-by: Abhishek Kumar --- .../HttpsDirectTemplateDownloader.java | 52 ++++++++++--------- .../main/java/com/cloud/utils/UriUtils.java | 8 ++- .../com/cloud/utils/storage/QCOW2Utils.java | 3 +- .../utils/imagestore/ImageStoreUtil.java | 2 +- .../java/com/cloud/utils/UriUtilsTest.java | 14 +++-- 5 files changed, 47 insertions(+), 32 deletions(-) diff --git a/core/src/main/java/org/apache/cloudstack/direct/download/HttpsDirectTemplateDownloader.java b/core/src/main/java/org/apache/cloudstack/direct/download/HttpsDirectTemplateDownloader.java index 1bee45c477d2..70a3eb29bc7a 100644 --- a/core/src/main/java/org/apache/cloudstack/direct/download/HttpsDirectTemplateDownloader.java +++ b/core/src/main/java/org/apache/cloudstack/direct/download/HttpsDirectTemplateDownloader.java @@ -19,29 +19,6 @@ package org.apache.cloudstack.direct.download; -import com.cloud.utils.Pair; -import com.cloud.utils.exception.CloudRuntimeException; -import com.cloud.utils.script.Script; -import com.cloud.utils.storage.QCOW2Utils; -import org.apache.cloudstack.utils.security.SSLUtils; -import org.apache.commons.httpclient.HttpStatus; -import org.apache.commons.io.IOUtils; -import org.apache.http.Header; -import org.apache.http.HttpEntity; -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.commons.collections.MapUtils; -import org.apache.http.client.config.RequestConfig; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpHead; -import org.apache.http.client.methods.HttpUriRequest; -import org.apache.http.conn.ssl.SSLConnectionSocketFactory; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClients; -import org.apache.http.util.EntityUtils; - -import javax.net.ssl.HttpsURLConnection; -import javax.net.ssl.SSLContext; -import javax.net.ssl.TrustManager; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; @@ -60,6 +37,32 @@ import java.util.List; import java.util.Map; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; + +import org.apache.cloudstack.utils.security.SSLUtils; +import org.apache.commons.collections.MapUtils; +import org.apache.commons.httpclient.HttpStatus; +import org.apache.commons.io.IOUtils; +import org.apache.http.Header; +import org.apache.http.HttpEntity; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpHead; +import org.apache.http.client.methods.HttpUriRequest; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.util.EntityUtils; + +import com.cloud.utils.Pair; +import com.cloud.utils.UriUtils; +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.script.Script; +import com.cloud.utils.storage.QCOW2Utils; + public class HttpsDirectTemplateDownloader extends DirectTemplateDownloaderImpl { protected CloseableHttpClient httpsClient; @@ -183,8 +186,7 @@ public Long getRemoteFileSize(String url, String format) { SSLContext context = getSSLContext(); urlConnection.setSSLSocketFactory(context.getSocketFactory()); urlConnection.connect(); - boolean isCompressed = !url.endsWith("qcow2"); - return QCOW2Utils.getVirtualSize(urlObj.openStream(), isCompressed); + return QCOW2Utils.getVirtualSize(urlObj.openStream(), UriUtils.isUrlForCompressedFile(url)); } catch (IOException e) { throw new CloudRuntimeException(String.format("Cannot obtain qcow2 virtual size due to: %s", e.getMessage()), e); } diff --git a/utils/src/main/java/com/cloud/utils/UriUtils.java b/utils/src/main/java/com/cloud/utils/UriUtils.java index dffc0106e8a8..a2bfa9eaa6fa 100644 --- a/utils/src/main/java/com/cloud/utils/UriUtils.java +++ b/utils/src/main/java/com/cloud/utils/UriUtils.java @@ -408,14 +408,14 @@ public static List getMetalinkUrls(String metalinkUrl) { return urls; } - public static final Set COMMPRESSION_FORMATS = ImmutableSet.of("zip", "bz2", "gz"); + public static final Set COMPRESSION_FORMATS = ImmutableSet.of("zip", "bz2", "gz"); public static final Set buildExtensionSet(boolean metalink, String... baseExtensions) { final ImmutableSet.Builder builder = ImmutableSet.builder(); for (String baseExtension : baseExtensions) { builder.add("." + baseExtension); - for (String format : COMMPRESSION_FORMATS) { + for (String format : COMPRESSION_FORMATS) { builder.add("." + baseExtension + "." + format); } } @@ -647,4 +647,8 @@ private static UriInfo getRbdUrlInfo(String url) { throw new CloudRuntimeException(url + " is not a valid uri for RBD"); } } + + public static boolean isUrlForCompressedFile(String url) { + return UriUtils.COMPRESSION_FORMATS.stream().anyMatch(f -> url.toLowerCase().endsWith(f)); + } } diff --git a/utils/src/main/java/com/cloud/utils/storage/QCOW2Utils.java b/utils/src/main/java/com/cloud/utils/storage/QCOW2Utils.java index 32a54722aaeb..4daf138bb8c8 100644 --- a/utils/src/main/java/com/cloud/utils/storage/QCOW2Utils.java +++ b/utils/src/main/java/com/cloud/utils/storage/QCOW2Utils.java @@ -32,6 +32,7 @@ import org.apache.log4j.Logger; import com.cloud.utils.NumbersUtil; +import com.cloud.utils.UriUtils; public final class QCOW2Utils { public static final Logger LOGGER = Logger.getLogger(QCOW2Utils.class.getName()); @@ -114,7 +115,7 @@ private static long getVirtualSizeFromInputStream(InputStream inputStream) throw public static long getVirtualSize(String urlStr) { try { URL url = new URL(urlStr); - return getVirtualSizeFromInputStream(url.openStream()); + return getVirtualSize(url.openStream(), UriUtils.isUrlForCompressedFile(urlStr)); } catch (MalformedURLException e) { LOGGER.warn("Failed to validate for qcow2, malformed URL: " + urlStr + ", error: " + e.getMessage()); throw new IllegalArgumentException("Invalid URL: " + urlStr); diff --git a/utils/src/main/java/org/apache/cloudstack/utils/imagestore/ImageStoreUtil.java b/utils/src/main/java/org/apache/cloudstack/utils/imagestore/ImageStoreUtil.java index 02878cf29606..2b37ce5fb72f 100644 --- a/utils/src/main/java/org/apache/cloudstack/utils/imagestore/ImageStoreUtil.java +++ b/utils/src/main/java/org/apache/cloudstack/utils/imagestore/ImageStoreUtil.java @@ -101,7 +101,7 @@ public static boolean isCorrectExtension(String path, String format) { public static boolean isCompressedExtension(String path) { final String lowerCasePath = path.toLowerCase(); - return UriUtils.COMMPRESSION_FORMATS + return UriUtils.COMPRESSION_FORMATS .stream() .map(extension -> "." + extension) .anyMatch(lowerCasePath::endsWith); diff --git a/utils/src/test/java/com/cloud/utils/UriUtilsTest.java b/utils/src/test/java/com/cloud/utils/UriUtilsTest.java index 1a3ae17f584e..4ec1f9a9bd92 100644 --- a/utils/src/test/java/com/cloud/utils/UriUtilsTest.java +++ b/utils/src/test/java/com/cloud/utils/UriUtilsTest.java @@ -19,13 +19,13 @@ package com.cloud.utils; -import org.junit.Assert; -import org.junit.Test; - import java.util.Arrays; import java.util.Collections; import java.util.List; +import org.junit.Assert; +import org.junit.Test; + public class UriUtilsTest { @Test public void encodeURIComponent() { @@ -265,4 +265,12 @@ public void testGetUriInfoIpv6() { testGetUriInfoInternal(url11, host); testGetUriInfoInternal(url12, host); } + + @Test + public void testIsUrlForCompressedFile() { + Assert.assertTrue(UriUtils.isUrlForCompressedFile("https://abc.com/xyz.bz2")); + Assert.assertTrue(UriUtils.isUrlForCompressedFile("http://abc.com/xyz.zip")); + Assert.assertTrue(UriUtils.isUrlForCompressedFile("https://abc.com/xyz.gz")); + Assert.assertFalse(UriUtils.isUrlForCompressedFile("http://abc.com/xyz.qcow2")); + } } From e437d1016f6f44344e0ece563c6e42c71964fd80 Mon Sep 17 00:00:00 2001 From: sato03 Date: Mon, 16 Oct 2023 11:20:09 -0300 Subject: [PATCH 3/4] Snapshot removal and storage cleanup logs (#8031) --- .../storage/snapshot/SnapshotServiceImpl.java | 14 ++-- .../com/cloud/storage/StorageManagerImpl.java | 77 ++++++++++++++----- 2 files changed, 63 insertions(+), 28 deletions(-) diff --git a/engine/storage/snapshot/src/main/java/org/apache/cloudstack/storage/snapshot/SnapshotServiceImpl.java b/engine/storage/snapshot/src/main/java/org/apache/cloudstack/storage/snapshot/SnapshotServiceImpl.java index 4d106f5c4f6a..0c65eb045336 100644 --- a/engine/storage/snapshot/src/main/java/org/apache/cloudstack/storage/snapshot/SnapshotServiceImpl.java +++ b/engine/storage/snapshot/src/main/java/org/apache/cloudstack/storage/snapshot/SnapshotServiceImpl.java @@ -364,7 +364,7 @@ protected Void deleteSnapshotCallback(AsyncCallbackDispatcher unusedTemplatesInPool = _tmpltMgr.getUnusedTemplatesInPool(pool); - s_logger.debug("Storage pool garbage collector found " + unusedTemplatesInPool.size() + " templates to clean up in storage pool: " + pool.getName()); + s_logger.debug(String.format("Storage pool garbage collector found [%s] templates to be cleaned up in storage pool [%s].", unusedTemplatesInPool.size(), pool.getName())); for (VMTemplateStoragePoolVO templatePoolVO : unusedTemplatesInPool) { if (templatePoolVO.getDownloadState() != VMTemplateStorageResourceAssoc.Status.DOWNLOADED) { - s_logger.debug("Storage pool garbage collector is skipping template with ID: " + templatePoolVO.getTemplateId() + " on pool " + templatePoolVO.getPoolId() - + " because it is not completely downloaded."); + s_logger.debug(String.format("Storage pool garbage collector is skipping template [%s] clean up on pool [%s] " + + "because it is not completely downloaded.", templatePoolVO.getTemplateId(), templatePoolVO.getPoolId())); continue; } if (!templatePoolVO.getMarkedForGC()) { templatePoolVO.setMarkedForGC(true); _vmTemplatePoolDao.update(templatePoolVO.getId(), templatePoolVO); - s_logger.debug("Storage pool garbage collector has marked template with ID: " + templatePoolVO.getTemplateId() + " on pool " + templatePoolVO.getPoolId() - + " for garbage collection."); + s_logger.debug(String.format("Storage pool garbage collector has marked template [%s] on pool [%s] " + + "for garbage collection.", templatePoolVO.getTemplateId(), templatePoolVO.getPoolId())); continue; } _tmpltMgr.evictTemplateFromStoragePool(templatePoolVO); } } catch (Exception e) { - s_logger.warn("Problem cleaning up primary storage pool " + pool, e); + s_logger.error(String.format("Failed to clean up primary storage pool [%s] due to: [%s].", pool, e.getMessage())); + s_logger.debug(String.format("Failed to clean up primary storage pool [%s].", pool), e); } } } @@ -1316,10 +1317,39 @@ public void cleanupStorage(boolean recurring) { //destroy snapshots in destroying state in snapshot_store_ref List ssSnapshots = _snapshotStoreDao.listByState(ObjectInDataStoreStateMachine.State.Destroying); for (SnapshotDataStoreVO ssSnapshotVO : ssSnapshots) { + String snapshotUuid = null; + SnapshotVO snapshot = null; + + if (s_logger.isDebugEnabled()) { + snapshot = _snapshotDao.findById(ssSnapshotVO.getSnapshotId()); + if (snapshot == null) { + s_logger.warn(String.format("Did not find snapshot [%s] in destroying state; therefore, it cannot be destroyed.", ssSnapshotVO.getSnapshotId())); + continue; + } + + snapshotUuid = snapshot.getUuid(); + } + try { - _snapshotService.deleteSnapshot(snapshotFactory.getSnapshot(ssSnapshotVO.getSnapshotId(), DataStoreRole.Image)); + if (s_logger.isDebugEnabled()) { + s_logger.debug(String.format("Verifying if snapshot [%s] is in destroying state in any image data store.", snapshotUuid)); + } + + SnapshotInfo snapshotInfo = snapshotFactory.getSnapshot(ssSnapshotVO.getSnapshotId(), DataStoreRole.Image); + + if (snapshotInfo != null) { + if (s_logger.isDebugEnabled()) { + s_logger.debug(String.format("Snapshot [%s] in destroying state found in image data store [%s]; therefore, it will be destroyed.", snapshotUuid, snapshotInfo.getDataStore().getUuid())); + } + _snapshotService.deleteSnapshot(snapshotInfo); + } else if (s_logger.isDebugEnabled()) { + s_logger.debug(String.format("Did not find snapshot [%s] in destroying state in any image data store.", snapshotUuid)); + } } catch (Exception e) { - s_logger.debug("Failed to delete snapshot: " + ssSnapshotVO.getId() + " from storage"); + s_logger.error(String.format("Failed to delete snapshot [%s] from storage due to: [%s].", ssSnapshotVO.getSnapshotId(), e.getMessage())); + if (s_logger.isDebugEnabled()) { + s_logger.debug(String.format("Failed to delete snapshot [%s] from storage.", snapshotUuid), e); + } } } cleanupSecondaryStorage(recurring); @@ -1343,7 +1373,8 @@ public void cleanupStorage(boolean recurring) { // system, but not necessary. handleManagedStorage(vol); } catch (Exception e) { - s_logger.warn("Unable to destroy host-side clustered file system " + vol.getUuid(), e); + s_logger.error(String.format("Unable to destroy host-side clustered file system [%s] due to: [%s].", vol.getUuid(), e.getMessage())); + s_logger.debug(String.format("Unable to destroy host-side clustered file system [%s].", vol.getUuid()), e); } try { @@ -1352,10 +1383,11 @@ public void cleanupStorage(boolean recurring) { volService.ensureVolumeIsExpungeReady(vol.getId()); volService.expungeVolumeAsync(volumeInfo); } else { - s_logger.debug("Volume " + vol.getUuid() + " is already destroyed"); + s_logger.debug(String.format("Volume [%s] is already destroyed.", vol.getUuid())); } } catch (Exception e) { - s_logger.warn("Unable to destroy volume " + vol.getUuid(), e); + s_logger.error(String.format("Unable to destroy volume [%s] due to: [%s].", vol.getUuid(), e.getMessage())); + s_logger.debug(String.format("Unable to destroy volume [%s].", vol.getUuid()), e); } } @@ -1369,7 +1401,8 @@ public void cleanupStorage(boolean recurring) { } _snapshotDao.expunge(snapshotVO.getId()); } catch (Exception e) { - s_logger.warn("Unable to destroy snapshot " + snapshotVO.getUuid(), e); + s_logger.error(String.format("Unable to destroy snapshot [%s] due to: [%s].", snapshotVO.getUuid(), e.getMessage())); + s_logger.debug(String.format("Unable to destroy snapshot [%s].", snapshotVO.getUuid()), e); } } @@ -1378,14 +1411,14 @@ public void cleanupStorage(boolean recurring) { for (VolumeDataStoreVO volumeDataStore : volumeDataStores) { VolumeVO volume = volumeDao.findById(volumeDataStore.getVolumeId()); if (volume == null) { - s_logger.warn("Uploaded volume with id " + volumeDataStore.getVolumeId() + " not found, so cannot be destroyed"); + s_logger.warn(String.format("Uploaded volume [%s] not found, so cannot be destroyed.", volumeDataStore.getVolumeId())); continue; } try { DataStore dataStore = _dataStoreMgr.getDataStore(volumeDataStore.getDataStoreId(), DataStoreRole.Image); EndPoint ep = _epSelector.select(dataStore, volumeDataStore.getExtractUrl()); if (ep == null) { - s_logger.warn("There is no secondary storage VM for image store " + dataStore.getName() + ", cannot destroy uploaded volume " + volume.getUuid()); + s_logger.warn(String.format("There is no secondary storage VM for image store [%s], cannot destroy uploaded volume [%s].", dataStore.getName(), volume.getUuid())); continue; } Host host = _hostDao.findById(ep.getId()); @@ -1397,17 +1430,18 @@ public void cleanupStorage(boolean recurring) { // expunge volume from secondary if volume is on image store VolumeInfo volOnSecondary = volFactory.getVolume(volume.getId(), DataStoreRole.Image); if (volOnSecondary != null) { - s_logger.info("Expunging volume " + volume.getUuid() + " uploaded using HTTP POST from secondary data store"); + s_logger.info(String.format("Expunging volume [%s] uploaded using HTTP POST from secondary data store.", volume.getUuid())); AsyncCallFuture future = volService.expungeVolumeAsync(volOnSecondary); VolumeApiResult result = future.get(); if (!result.isSuccess()) { - s_logger.warn("Failed to expunge volume " + volume.getUuid() + " from the image store " + dataStore.getName() + " due to: " + result.getResult()); + s_logger.warn(String.format("Failed to expunge volume [%s] from the image store [%s] due to: [%s].", volume.getUuid(), dataStore.getName(), result.getResult())); } } } } } catch (Throwable th) { - s_logger.warn("Unable to destroy uploaded volume " + volume.getUuid() + ". Error details: " + th.getMessage()); + s_logger.error(String.format("Unable to destroy uploaded volume [%s] due to: [%s].", volume.getUuid(), th.getMessage())); + s_logger.debug(String.format("Unable to destroy uploaded volume [%s].", volume.getUuid()), th); } } @@ -1416,14 +1450,14 @@ public void cleanupStorage(boolean recurring) { for (TemplateDataStoreVO templateDataStore : templateDataStores) { VMTemplateVO template = _templateDao.findById(templateDataStore.getTemplateId()); if (template == null) { - s_logger.warn("Uploaded template with id " + templateDataStore.getTemplateId() + " not found, so cannot be destroyed"); + s_logger.warn(String.format("Uploaded template [%s] not found, so cannot be destroyed.", templateDataStore.getTemplateId())); continue; } try { DataStore dataStore = _dataStoreMgr.getDataStore(templateDataStore.getDataStoreId(), DataStoreRole.Image); EndPoint ep = _epSelector.select(dataStore, templateDataStore.getExtractUrl()); if (ep == null) { - s_logger.warn("There is no secondary storage VM for image store " + dataStore.getName() + ", cannot destroy uploaded template " + template.getUuid()); + s_logger.warn(String.format("Cannot destroy uploaded template [%s] as there is no secondary storage VM for image store [%s].", template.getUuid(), dataStore.getName())); continue; } Host host = _hostDao.findById(ep.getId()); @@ -1432,7 +1466,7 @@ public void cleanupStorage(boolean recurring) { AsyncCallFuture future = _imageSrv.deleteTemplateAsync(tmplFactory.getTemplate(template.getId(), dataStore)); TemplateApiResult result = future.get(); if (!result.isSuccess()) { - s_logger.warn("Failed to delete template " + template.getUuid() + " from the image store " + dataStore.getName() + " due to: " + result.getResult()); + s_logger.warn(String.format("Failed to delete template [%s] from image store [%s] due to: [%s]", template.getUuid(), dataStore.getName(), result.getResult())); continue; } // remove from template_zone_ref @@ -1456,7 +1490,8 @@ public void cleanupStorage(boolean recurring) { } } } catch (Throwable th) { - s_logger.warn("Unable to destroy uploaded template " + template.getUuid() + ". Error details: " + th.getMessage()); + s_logger.error(String.format("Unable to destroy uploaded template [%s] due to: [%s].", template.getUuid(), th.getMessage())); + s_logger.debug(String.format("Unable to destroy uploaded template [%s].", template.getUuid()), th); } } cleanupInactiveTemplates(); From 065abe2a3b64b3edae2da956869ccd0a7a37f70b Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Mon, 16 Oct 2023 19:54:59 +0530 Subject: [PATCH 4/4] test,refactor: fix test_project_resources cleanup (#8097) Signed-off-by: Abhishek Kumar --- .../component/test_project_resources.py | 80 ++++++++----------- 1 file changed, 34 insertions(+), 46 deletions(-) diff --git a/test/integration/component/test_project_resources.py b/test/integration/component/test_project_resources.py index f767af1788b9..16d21dfd7cba 100644 --- a/test/integration/component/test_project_resources.py +++ b/test/integration/component/test_project_resources.py @@ -551,66 +551,59 @@ def setUpClass(cls): cls.hypervisor = cls.testClient.getHypervisorInfo() if cls.hypervisor.lower() in ['lxc']: raise unittest.SkipTest("create template from volume is not supported on %s" % cls.hypervisor.lower()) + cls._cleanup = [] cls.template = get_template( - cls.api_client, - cls.zone.id, - cls.services["ostype"] - ) + cls.api_client, + cls.zone.id, + cls.services["ostype"] + ) cls.services["server"]["zoneid"] = cls.zone.id # Create Domains, Account etc cls.domain = Domain.create( - cls.api_client, - cls.services["domain"] - ) + cls.api_client, + cls.services["domain"] + ) + cls._cleanup.append(cls.domain) cls.account = Account.create( - cls.api_client, - cls.services["account"], - domainid=cls.domain.id - ) + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + cls._cleanup.append(cls.account) cls.user = Account.create( - cls.api_client, - cls.services["account"], - domainid=cls.domain.id - ) + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + cls._cleanup.append(cls.user) # Create project as a domain admin cls.project = Project.create( - cls.api_client, - cls.services["project"], - account=cls.account.name, - domainid=cls.account.domainid - ) + cls.api_client, + cls.services["project"], + account=cls.account.name, + domainid=cls.account.domainid + ) + cls._cleanup.append(cls.project) cls.services["account"] = cls.account.name # Create Service offering and disk offerings etc cls.service_offering = ServiceOffering.create( - cls.api_client, - cls.services["service_offering"] - ) + cls.api_client, + cls.services["service_offering"] + ) + cls._cleanup.append(cls.service_offering) cls.userapiclient = cls.testClient.getUserApiClient( - UserName=cls.account.name, - DomainName=cls.domain.name - ) - - cls._cleanup = [ - cls.project, - cls.service_offering, - cls.account, - cls.user, - cls.domain - ] + UserName=cls.account.name, + DomainName=cls.domain.name + ) return @classmethod def tearDownClass(cls): - try: - #Cleanup resources used - cleanup_resources(cls.api_client, cls._cleanup) - except Exception as e: - raise Exception("Warning: Exception during cleanup : %s" % e) - return + super(TestTemplates, cls).tearDownClass() def setUp(self): self.apiclient = self.testClient.getApiClient() @@ -619,12 +612,7 @@ def setUp(self): return def tearDown(self): - try: - #Clean up, terminate the created instance, volumes and snapshots - cleanup_resources(self.apiclient, self.cleanup) - except Exception as e: - raise Exception("Warning: Exception during cleanup : %s" % e) - return + super(TestTemplates, self).tearDown() @attr(tags=["advanced", "basic", "sg", "eip", "advancedns"], required_hardware="false") def test_04_public_private_template_use_in_project(self):