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/command/admin/usage/ListTrafficTypesCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/usage/ListTrafficTypesCmd.java index d106a736fcab..c204c67d465e 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 @@ -26,14 +26,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 { 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..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 @@ -56,6 +56,14 @@ 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; + @SerializedName(ApiConstants.VLAN) + @Param(description = "The VLAN id to be used for Management traffic by VMware host") + private String vlan; + + @SerializedName(ApiConstants.ISOLATION_METHODS) + @Param(description = "isolation methods for the physical network traffic") + 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") private String ovm3NetworkLabel; @@ -128,4 +136,20 @@ public String getOvm3Label() { public void setOvm3Label(String ovm3Label) { this.ovm3NetworkLabel = ovm3Label; } + + public String getIsolationMethods() { + return isolationMethods; + } + + public void setIsolationMethods(String isolationMethods) { + this.isolationMethods = isolationMethods; + } + + public String getVlan() { + return vlan; + } + + public void setVlan(String vlan) { + this.vlan = vlan; + } } diff --git a/server/src/main/java/com/cloud/api/ApiResponseHelper.java b/server/src/main/java/com/cloud/api/ApiResponseHelper.java index 404cefb68fe9..1ebbd4f35b5c 100644 --- a/server/src/main/java/com/cloud/api/ApiResponseHelper.java +++ b/server/src/main/java/com/cloud/api/ApiResponseHelper.java @@ -3256,6 +3256,9 @@ public TrafficTypeResponse createTrafficTypeResponse(PhysicalNetworkTrafficType PhysicalNetwork pnet = ApiDBUtils.findPhysicalNetworkById(result.getPhysicalNetworkId()); if (pnet != null) { response.setPhysicalNetworkId(pnet.getUuid()); + if (!pnet.getIsolationMethods().isEmpty()) { + response.setIsolationMethods(String.join(",", pnet.getIsolationMethods())); + } } if (result.getTrafficType() != null) { response.setTrafficType(result.getTrafficType().toString()); @@ -3266,6 +3269,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; diff --git a/server/src/test/java/com/cloud/api/ApiResponseHelperTest.java b/server/src/test/java/com/cloud/api/ApiResponseHelperTest.java index 223b0740cf27..d4f477383efd 100644 --- a/server/src/test/java/com/cloud/api/ApiResponseHelperTest.java +++ b/server/src/test/java/com/cloud/api/ApiResponseHelperTest.java @@ -16,14 +16,6 @@ // under the License. package com.cloud.api; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - import java.lang.reflect.Field; import java.text.ParseException; import java.text.SimpleDateFormat; @@ -37,9 +29,24 @@ import java.util.TimeZone; import java.util.UUID; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.mockito.Spy; +import org.mockito.junit.MockitoJUnitRunner; +import org.springframework.test.util.ReflectionTestUtils; + import org.apache.cloudstack.annotation.dao.AnnotationDao; +import org.apache.cloudstack.api.ResponseObject; import org.apache.cloudstack.api.response.AutoScaleVmGroupResponse; import org.apache.cloudstack.api.response.AutoScaleVmProfileResponse; +import org.apache.cloudstack.api.response.ConsoleSessionResponse; import org.apache.cloudstack.api.response.DirectDownloadCertificateResponse; import org.apache.cloudstack.api.response.GuestOSCategoryResponse; import org.apache.cloudstack.api.response.IpQuarantineResponse; @@ -48,26 +55,17 @@ import org.apache.cloudstack.api.response.TemplateResponse; import org.apache.cloudstack.api.response.UnmanagedInstanceResponse; 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.apache.cloudstack.vm.UnmanagedInstanceTO; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.MockedStatic; -import org.mockito.Mockito; -import org.mockito.Spy; -import org.mockito.junit.MockitoJUnitRunner; -import org.springframework.test.util.ReflectionTestUtils; import com.cloud.capacity.Capacity; import com.cloud.configuration.Resource; import com.cloud.domain.DomainVO; import com.cloud.host.HostVO; +import com.cloud.network.Networks; +import com.cloud.network.PhysicalNetworkTrafficType; import com.cloud.network.PublicIpQuarantine; import com.cloud.network.as.AutoScaleVmGroup; import com.cloud.network.as.AutoScaleVmGroupVO; @@ -78,6 +76,8 @@ 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.resource.icon.ResourceIconVO; import com.cloud.server.ResourceIcon; import com.cloud.server.ResourceIconManager; @@ -97,8 +97,16 @@ import com.cloud.vm.ConsoleSessionVO; import com.cloud.vm.NicSecondaryIp; import com.cloud.vm.VMInstanceVO; -import org.apache.cloudstack.api.ResponseObject; -import org.apache.cloudstack.api.response.ConsoleSessionResponse; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + @RunWith(MockitoJUnitRunner.class) public class ApiResponseHelperTest { @@ -417,6 +425,39 @@ public void testAutoScaleVmProfileResponseWithoutUserData() { } } + @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"); + + } + } + private UnmanagedInstanceTO getUnmanagedInstaceForTests() { UnmanagedInstanceTO instance = Mockito.mock(UnmanagedInstanceTO.class); Mockito.when(instance.getPowerState()).thenReturn(UnmanagedInstanceTO.PowerState.PowerOff); 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..10e9df470988 --- /dev/null +++ b/test/integration/smoke/test_network_traffic_type_api.py @@ -0,0 +1,73 @@ +# 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, + 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) + + @classmethod + def tearDownClass(cls): + super(TestTrafficTypeApi, cls).tearDownClass() + + + @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")