From 32cfb2d597929e13b1dff5b914cd4b869cd7f76d Mon Sep 17 00:00:00 2001 From: Madhukar Mishra Date: Thu, 26 Oct 2023 03:41:41 +0530 Subject: [PATCH 01/10] add vlan, isolationMethod to TrafficTypeResponse --- .../api/response/TrafficTypeResponse.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/api/src/main/java/org/apache/cloudstack/api/response/TrafficTypeResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/TrafficTypeResponse.java index 9a79b0724658..fb67ef3ad845 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/TrafficTypeResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/TrafficTypeResponse.java @@ -56,6 +56,15 @@ public class TrafficTypeResponse extends BaseResponse { @Param(description = "The network name label of the physical device dedicated to this traffic on a HyperV host") private String hypervNetworkLabel; + // why not VLAN_ID + @SerializedName(ApiConstants.VLAN) + @Param(description = "The VLAN id to be used for Management traffic by VMware host") + private String vlan; + + @SerializedName(ApiConstants.ISOLATION_METHOD) + @Param(description = "The isolation method for the traffic") + private String isolationMethod; + @SerializedName(ApiConstants.OVM3_NETWORK_LABEL) @Param(description = "The network name of the physical device dedicated to this traffic on an OVM3 host") private String ovm3NetworkLabel; @@ -128,4 +137,20 @@ public String getOvm3Label() { public void setOvm3Label(String ovm3Label) { this.ovm3NetworkLabel = ovm3Label; } + + public String getIsolationMethod() { + return isolationMethod; + } + + public void setIsolationMethod(String isolationMethod) { + this.isolationMethod = isolationMethod; + } + + public String getVlan() { + return vlan; + } + + public void setVlan(String vlan) { + this.vlan = vlan; + } } From d4460e734fe6cb116e923f00fc29c1b186763a3c Mon Sep 17 00:00:00 2001 From: Madhukar Mishra Date: Thu, 26 Oct 2023 07:18:14 +0530 Subject: [PATCH 02/10] set vlan, isolationMethods in createTrafficTypeResponse() --- .../network/PhysicalNetworkTrafficType.java | 2 ++ .../api/response/TrafficTypeResponse.java | 18 +++++++++--------- .../java/com/cloud/api/ApiResponseHelper.java | 2 ++ 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/api/src/main/java/com/cloud/network/PhysicalNetworkTrafficType.java b/api/src/main/java/com/cloud/network/PhysicalNetworkTrafficType.java index 9676badb4e90..d3804cd29daf 100644 --- a/api/src/main/java/com/cloud/network/PhysicalNetworkTrafficType.java +++ b/api/src/main/java/com/cloud/network/PhysicalNetworkTrafficType.java @@ -41,4 +41,6 @@ public interface PhysicalNetworkTrafficType extends InternalIdentity, Identity { String getHypervNetworkLabel(); String getOvm3NetworkLabel(); + + String getVlan(); } diff --git a/api/src/main/java/org/apache/cloudstack/api/response/TrafficTypeResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/TrafficTypeResponse.java index fb67ef3ad845..cd873180dee4 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/TrafficTypeResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/TrafficTypeResponse.java @@ -25,6 +25,8 @@ import com.cloud.network.PhysicalNetworkTrafficType; import com.cloud.serializer.Param; +import java.util.List; + @EntityReference(value = PhysicalNetworkTrafficType.class) public class TrafficTypeResponse extends BaseResponse { @@ -56,14 +58,13 @@ public class TrafficTypeResponse extends BaseResponse { @Param(description = "The network name label of the physical device dedicated to this traffic on a HyperV host") private String hypervNetworkLabel; - // why not VLAN_ID @SerializedName(ApiConstants.VLAN) @Param(description = "The VLAN id to be used for Management traffic by VMware host") private String vlan; - @SerializedName(ApiConstants.ISOLATION_METHOD) - @Param(description = "The isolation method for the traffic") - private String isolationMethod; + @SerializedName(ApiConstants.ISOLATION_METHODS) + @Param(description = "isolation methods for the physical network traffic") + private List isolationMethods; @SerializedName(ApiConstants.OVM3_NETWORK_LABEL) @Param(description = "The network name of the physical device dedicated to this traffic on an OVM3 host") @@ -138,14 +139,13 @@ public void setOvm3Label(String ovm3Label) { this.ovm3NetworkLabel = ovm3Label; } - public String getIsolationMethod() { - return isolationMethod; + public List getIsolationMethods() { + return isolationMethods; } - public void setIsolationMethod(String isolationMethod) { - this.isolationMethod = isolationMethod; + public void setIsolationMethods(List isolationMethods) { + this.isolationMethods = isolationMethods; } - public String getVlan() { return vlan; } diff --git a/server/src/main/java/com/cloud/api/ApiResponseHelper.java b/server/src/main/java/com/cloud/api/ApiResponseHelper.java index 3649197a2188..41fc2253061e 100644 --- a/server/src/main/java/com/cloud/api/ApiResponseHelper.java +++ b/server/src/main/java/com/cloud/api/ApiResponseHelper.java @@ -3084,6 +3084,7 @@ public TrafficTypeResponse createTrafficTypeResponse(PhysicalNetworkTrafficType PhysicalNetwork pnet = ApiDBUtils.findPhysicalNetworkById(result.getPhysicalNetworkId()); if (pnet != null) { response.setPhysicalNetworkId(pnet.getUuid()); + response.setIsolationMethods(pnet.getIsolationMethods()); } if (result.getTrafficType() != null) { response.setTrafficType(result.getTrafficType().toString()); @@ -3094,6 +3095,7 @@ public TrafficTypeResponse createTrafficTypeResponse(PhysicalNetworkTrafficType response.setVmwareLabel(result.getVmwareNetworkLabel()); response.setHypervLabel(result.getHypervNetworkLabel()); response.setOvm3Label(result.getOvm3NetworkLabel()); + response.setVlan(result.getVlan()); response.setObjectName("traffictype"); return response; From 8c412f60bd4f617deef00647f9631bc6f6269bec Mon Sep 17 00:00:00 2001 From: Madhukar Mishra Date: Fri, 27 Oct 2023 22:06:16 +0530 Subject: [PATCH 03/10] change PhysicalNetworkTrafficType.isolationMethods -> string --- .../cloudstack/api/response/PhysicalNetworkResponse.java | 4 ++++ .../cloudstack/api/response/TrafficTypeResponse.java | 9 ++++----- .../src/main/java/com/cloud/api/ApiResponseHelper.java | 5 ++++- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/api/src/main/java/org/apache/cloudstack/api/response/PhysicalNetworkResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/PhysicalNetworkResponse.java index f5116829305a..3e28df7f4973 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/PhysicalNetworkResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/PhysicalNetworkResponse.java @@ -139,6 +139,10 @@ public void setIsolationMethods(List isolationMethods) { this.isolationMethods = buf.delete(buf.length() - 1, buf.length()).toString(); } + public String getIsolationMethods() { + return isolationMethods; + } + public void setName(String name) { this.name = name; } diff --git a/api/src/main/java/org/apache/cloudstack/api/response/TrafficTypeResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/TrafficTypeResponse.java index cd873180dee4..281ed6736ee6 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/TrafficTypeResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/TrafficTypeResponse.java @@ -25,8 +25,6 @@ import com.cloud.network.PhysicalNetworkTrafficType; import com.cloud.serializer.Param; -import java.util.List; - @EntityReference(value = PhysicalNetworkTrafficType.class) public class TrafficTypeResponse extends BaseResponse { @@ -64,7 +62,7 @@ public class TrafficTypeResponse extends BaseResponse { @SerializedName(ApiConstants.ISOLATION_METHODS) @Param(description = "isolation methods for the physical network traffic") - private List isolationMethods; + private String isolationMethods; @SerializedName(ApiConstants.OVM3_NETWORK_LABEL) @Param(description = "The network name of the physical device dedicated to this traffic on an OVM3 host") @@ -139,13 +137,14 @@ public void setOvm3Label(String ovm3Label) { this.ovm3NetworkLabel = ovm3Label; } - public List getIsolationMethods() { + public String getIsolationMethods() { return isolationMethods; } - public void setIsolationMethods(List isolationMethods) { + public void setIsolationMethods(String isolationMethods) { this.isolationMethods = isolationMethods; } + public String getVlan() { return vlan; } diff --git a/server/src/main/java/com/cloud/api/ApiResponseHelper.java b/server/src/main/java/com/cloud/api/ApiResponseHelper.java index 41fc2253061e..16600068860b 100644 --- a/server/src/main/java/com/cloud/api/ApiResponseHelper.java +++ b/server/src/main/java/com/cloud/api/ApiResponseHelper.java @@ -3084,7 +3084,10 @@ public TrafficTypeResponse createTrafficTypeResponse(PhysicalNetworkTrafficType PhysicalNetwork pnet = ApiDBUtils.findPhysicalNetworkById(result.getPhysicalNetworkId()); if (pnet != null) { response.setPhysicalNetworkId(pnet.getUuid()); - response.setIsolationMethods(pnet.getIsolationMethods()); + // using PhysicalNetworkResponse only to convert isolation methods to string + PhysicalNetworkResponse pnetResponse = new PhysicalNetworkResponse(); + pnetResponse.setIsolationMethods(pnet.getIsolationMethods()); + response.setIsolationMethods(pnetResponse.getIsolationMethods()); } if (result.getTrafficType() != null) { response.setTrafficType(result.getTrafficType().toString()); From d8cc5cc826e08d06f2ad0227bc8f542446ad4e34 Mon Sep 17 00:00:00 2001 From: Madhukar Mishra Date: Fri, 27 Oct 2023 23:29:33 +0530 Subject: [PATCH 04/10] Add unit test for createTrafficTypeResponse --- .../com/cloud/api/ApiResponseHelperTest.java | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/server/src/test/java/com/cloud/api/ApiResponseHelperTest.java b/server/src/test/java/com/cloud/api/ApiResponseHelperTest.java index 8b5879a0723a..0e80a72f44ee 100644 --- a/server/src/test/java/com/cloud/api/ApiResponseHelperTest.java +++ b/server/src/test/java/com/cloud/api/ApiResponseHelperTest.java @@ -17,6 +17,8 @@ package com.cloud.api; import com.cloud.domain.DomainVO; +import com.cloud.network.Networks; +import com.cloud.network.PhysicalNetworkTrafficType; import com.cloud.network.as.AutoScaleVmGroup; import com.cloud.network.as.AutoScaleVmGroupVO; import com.cloud.network.as.AutoScaleVmProfileVO; @@ -25,6 +27,9 @@ import com.cloud.network.dao.LoadBalancerVO; import com.cloud.network.dao.NetworkServiceMapDao; import com.cloud.network.dao.NetworkVO; +import com.cloud.network.dao.PhysicalNetworkVO; +import com.cloud.network.dao.PhysicalNetworkTrafficTypeVO; + import com.cloud.storage.VMTemplateVO; import com.cloud.usage.UsageVO; import com.cloud.user.Account; @@ -43,6 +48,8 @@ import org.apache.cloudstack.api.response.DirectDownloadCertificateResponse; import org.apache.cloudstack.api.response.NicSecondaryIpResponse; import org.apache.cloudstack.api.response.UsageRecordResponse; +import org.apache.cloudstack.api.response.TrafficTypeResponse; + import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.usage.UsageService; import org.junit.After; @@ -66,6 +73,8 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertFalse; + import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.Mockito.when; @@ -367,4 +376,36 @@ public void testAutoScaleVmProfileResponseWithoutUserData() { assertNull(response.getUserDataDetails()); } } + + @Test + public void testCreateTrafficTypeResponse() { + PhysicalNetworkVO pnet = new PhysicalNetworkVO(); + pnet.addIsolationMethod("VXLAN"); + pnet.addIsolationMethod("STT"); + + try (MockedStatic ignored = Mockito.mockStatic(ApiDBUtils.class)) { + when(ApiDBUtils.findPhysicalNetworkById(anyLong())).thenReturn(pnet); + String xenLabel = "xen"; + String kvmLabel = "kvm"; + String vmwareLabel = "vmware"; + String simulatorLabel = "simulator"; + String hypervLabel = "hyperv"; + String ovmLabel = "ovm"; + String vlan = "vlan"; + String trafficType = "Public"; + PhysicalNetworkTrafficType pnetTrafficType = new PhysicalNetworkTrafficTypeVO(pnet.getId(), Networks.TrafficType.getTrafficType(trafficType), xenLabel, kvmLabel, vmwareLabel, simulatorLabel, vlan, hypervLabel, ovmLabel); + + TrafficTypeResponse response = apiResponseHelper.createTrafficTypeResponse(pnetTrafficType); + assertFalse(UUID.fromString(response.getId()).toString().isEmpty()); + assertEquals(response.getphysicalNetworkId(), pnet.getUuid()); + assertEquals(response.getTrafficType(), trafficType); + assertEquals(response.getXenLabel(), xenLabel); + assertEquals(response.getKvmLabel(), kvmLabel); + assertEquals(response.getVmwareLabel(), vmwareLabel); + assertEquals(response.getHypervLabel(), hypervLabel); + assertEquals(response.getOvm3Label(), ovmLabel); + assertEquals(response.getVlan(), vlan); + assertEquals(response.getIsolationMethods(), "VXLAN,STT"); + } + } } From 0777b38a92f431c9def7ea90f62768eb5c277c9d Mon Sep 17 00:00:00 2001 From: Madhukar Mishra Date: Sat, 28 Oct 2023 22:25:52 +0530 Subject: [PATCH 05/10] Fix responseObject on ListTrafficTypesCmd --- .../api/command/admin/usage/ListTrafficTypesCmd.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/usage/ListTrafficTypesCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/usage/ListTrafficTypesCmd.java index 6e36ca3bd8d1..821eef52439f 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/usage/ListTrafficTypesCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/usage/ListTrafficTypesCmd.java @@ -27,14 +27,13 @@ import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.api.response.PhysicalNetworkResponse; -import org.apache.cloudstack.api.response.ProviderResponse; import org.apache.cloudstack.api.response.TrafficTypeResponse; import com.cloud.network.PhysicalNetworkTrafficType; import com.cloud.user.Account; import com.cloud.utils.Pair; -@APICommand(name = "listTrafficTypes", description = "Lists traffic types of a given physical network.", responseObject = ProviderResponse.class, since = "3.0.0", +@APICommand(name = "listTrafficTypes", description = "Lists traffic types of a given physical network.", responseObject = TrafficTypeResponse.class, since = "3.0.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListTrafficTypesCmd extends BaseListCmd { public static final Logger s_logger = Logger.getLogger(ListTrafficTypesCmd.class.getName()); From 7c308b22cd33663f2e8461627fd88da0e06a5def Mon Sep 17 00:00:00 2001 From: Madhukar Mishra Date: Thu, 2 Nov 2023 22:20:52 +0530 Subject: [PATCH 06/10] don't depend on PhysicalNetworkResponse for PhysicalNetworkTrafficType.isolationMethods --- .../cloudstack/api/response/PhysicalNetworkResponse.java | 4 ---- server/src/main/java/com/cloud/api/ApiResponseHelper.java | 7 +++---- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/api/src/main/java/org/apache/cloudstack/api/response/PhysicalNetworkResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/PhysicalNetworkResponse.java index 3e28df7f4973..f5116829305a 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/PhysicalNetworkResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/PhysicalNetworkResponse.java @@ -139,10 +139,6 @@ public void setIsolationMethods(List isolationMethods) { this.isolationMethods = buf.delete(buf.length() - 1, buf.length()).toString(); } - public String getIsolationMethods() { - return isolationMethods; - } - public void setName(String name) { this.name = name; } diff --git a/server/src/main/java/com/cloud/api/ApiResponseHelper.java b/server/src/main/java/com/cloud/api/ApiResponseHelper.java index 16600068860b..6ad36ddb816c 100644 --- a/server/src/main/java/com/cloud/api/ApiResponseHelper.java +++ b/server/src/main/java/com/cloud/api/ApiResponseHelper.java @@ -3084,10 +3084,9 @@ public TrafficTypeResponse createTrafficTypeResponse(PhysicalNetworkTrafficType PhysicalNetwork pnet = ApiDBUtils.findPhysicalNetworkById(result.getPhysicalNetworkId()); if (pnet != null) { response.setPhysicalNetworkId(pnet.getUuid()); - // using PhysicalNetworkResponse only to convert isolation methods to string - PhysicalNetworkResponse pnetResponse = new PhysicalNetworkResponse(); - pnetResponse.setIsolationMethods(pnet.getIsolationMethods()); - response.setIsolationMethods(pnetResponse.getIsolationMethods()); + if (!pnet.getIsolationMethods().isEmpty()) { + response.setIsolationMethods(String.join(",", pnet.getIsolationMethods())); + } } if (result.getTrafficType() != null) { response.setTrafficType(result.getTrafficType().toString()); From 4c8dfb6c94e305c30328b18e7f225edeaa69c684 Mon Sep 17 00:00:00 2001 From: Madhukar Mishra Date: Sat, 4 Nov 2023 03:01:32 +0530 Subject: [PATCH 07/10] Add marvin test for TrafficTypeResponse --- .../smoke/test_network_traffic_type_api.py | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 test/integration/smoke/test_network_traffic_type_api.py diff --git a/test/integration/smoke/test_network_traffic_type_api.py b/test/integration/smoke/test_network_traffic_type_api.py new file mode 100644 index 000000000000..bb1de5f5d0ff --- /dev/null +++ b/test/integration/smoke/test_network_traffic_type_api.py @@ -0,0 +1,50 @@ +from marvin.cloudstackTestCase import cloudstackTestCase +from marvin.lib.base import ( + TrafficType, + PhysicalNetwork, + Zone, +) +from nose.plugins.attrib import attr + + +class TestTrafficTypeApi(cloudstackTestCase): + @classmethod + def setUpClass(cls): + cls.test_client = super(TestTrafficTypeApi, cls).getClsTestClient() + cls.api_client = cls.testClient.getApiClient() + cls.services = cls.testClient.getParsedTestDataConfig() + cls._cleanup = [] + cls.services["advanced_sg"]["zone"]["name"] = "TestTrafficTypeApi-zone" + cls.zone = Zone.create(cls.api_client, cls.services["advanced_sg"]["zone"]) + cls._cleanup.append(cls.zone) + + cls.physical_network = PhysicalNetwork.create( + cls.api_client, + cls.services["l2-network"], + isolationmethods="VLAN", + zoneid=cls.zone.id, + ) + cls._cleanup.append(cls.physical_network) + + @attr(tags=["advanced"], required_hardware="false") + def test_list_api_fields(self): + traffic_type = TrafficType.add( + self.api_client, + physicalnetworkid=self.physical_network.id, + kvmnetworklabel="kvm", + traffictype="Public", + vlan="100", + ).traffictype + + traffic_types = TrafficType.list( + self.api_client, + physicalnetworkid=self.physical_network.id + ) + + assert len(traffic_types) == 1 + response = traffic_types[0] + self.assertEqual(response.id, traffic_type.id) + self.assertEqual(response.kvmnetworklabel, "kvm") + self.assertEqual(response.traffictype, "Public") + self.assertEqual(response.vlan, "100") + self.assertEqual(response.isolationmethods, "VLAN") From bb476dc3d3b62ccb2d0103ba79c8780d2c4872b1 Mon Sep 17 00:00:00 2001 From: Madhukar Mishra Date: Tue, 7 Nov 2023 19:35:30 +0530 Subject: [PATCH 08/10] add license Co-authored-by: dahn --- .../smoke/test_network_traffic_type_api.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/test/integration/smoke/test_network_traffic_type_api.py b/test/integration/smoke/test_network_traffic_type_api.py index bb1de5f5d0ff..c578d507ae1c 100644 --- a/test/integration/smoke/test_network_traffic_type_api.py +++ b/test/integration/smoke/test_network_traffic_type_api.py @@ -1,3 +1,21 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +# Import Local Modules from marvin.cloudstackTestCase import cloudstackTestCase from marvin.lib.base import ( TrafficType, From 1df0bb1a28ae8c73167e4f3e98b19f4132c52801 Mon Sep 17 00:00:00 2001 From: Madhukar Mishra Date: Tue, 7 Nov 2023 19:37:45 +0530 Subject: [PATCH 09/10] add teardown for TestTrafficTypeApi Co-authored-by: dahn --- test/integration/smoke/test_network_traffic_type_api.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/integration/smoke/test_network_traffic_type_api.py b/test/integration/smoke/test_network_traffic_type_api.py index c578d507ae1c..c1490a89e683 100644 --- a/test/integration/smoke/test_network_traffic_type_api.py +++ b/test/integration/smoke/test_network_traffic_type_api.py @@ -44,6 +44,11 @@ def setUpClass(cls): ) cls._cleanup.append(cls.physical_network) + @classmethod + def tearDownClass(cls): + super(TestTrafficTypeApi, cls).tearDownClass() + + @attr(tags=["advanced"], required_hardware="false") def test_list_api_fields(self): traffic_type = TrafficType.add( From cc72ada3c17d332400e98f99b505229e0ea42e76 Mon Sep 17 00:00:00 2001 From: Madhukar Mishra Date: Tue, 7 Nov 2023 20:38:13 +0530 Subject: [PATCH 10/10] fix style Co-authored-by: dahn --- test/integration/smoke/test_network_traffic_type_api.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/integration/smoke/test_network_traffic_type_api.py b/test/integration/smoke/test_network_traffic_type_api.py index c1490a89e683..10e9df470988 100644 --- a/test/integration/smoke/test_network_traffic_type_api.py +++ b/test/integration/smoke/test_network_traffic_type_api.py @@ -44,10 +44,10 @@ def setUpClass(cls): ) cls._cleanup.append(cls.physical_network) - @classmethod - def tearDownClass(cls): - super(TestTrafficTypeApi, cls).tearDownClass() - + @classmethod + def tearDownClass(cls): + super(TestTrafficTypeApi, cls).tearDownClass() + @attr(tags=["advanced"], required_hardware="false") def test_list_api_fields(self):