mirror of https://github.com/apache/cloudstack.git
Merge bc106fd8bc into b7d4df0a11
This commit is contained in:
commit
632808ec48
|
|
@ -1017,6 +1017,7 @@ public class ApiConstants {
|
|||
public static final String VPC_OFF_NAME = "vpcofferingname";
|
||||
public static final String VPC_OFFERING_CONSERVE_MODE = "vpcofferingconservemode";
|
||||
public static final String NETWORK = "network";
|
||||
public static final String VPC_ACCESS = "vpcaccess";
|
||||
public static final String VPC_ID = "vpcid";
|
||||
public static final String VPC_NAME = "vpcname";
|
||||
public static final String VPC_GATEWAY_ID = "vpcgatewayid";
|
||||
|
|
|
|||
|
|
@ -240,7 +240,7 @@ public class ListNetworksCmd extends BaseListRetrieveOnlyResourceCountCmd implem
|
|||
private void updateNetworkResponse(List<NetworkResponse> response) {
|
||||
for (NetworkResponse networkResponse : response) {
|
||||
ResourceIcon resourceIcon = resourceIconManager.getByResourceTypeAndUuid(ResourceTag.ResourceObjectType.Network, networkResponse.getId());
|
||||
if (resourceIcon == null && networkResponse.getVpcId() != null) {
|
||||
if (resourceIcon == null && networkResponse.getVpcId() != null && networkResponse.getVpcAccess()) {
|
||||
resourceIcon = resourceIconManager.getByResourceTypeAndUuid(ResourceTag.ResourceObjectType.Vpc, networkResponse.getVpcId());
|
||||
}
|
||||
if (resourceIcon == null) {
|
||||
|
|
|
|||
|
|
@ -143,6 +143,10 @@ public class IPAddressResponse extends BaseResponseWithAnnotations implements Co
|
|||
@Param(description = "Purpose of the IP address. In Acton this value is not null for IPs with isSystem=true, and can have either StaticNat or LB value")
|
||||
private String purpose;
|
||||
|
||||
@SerializedName(ApiConstants.VPC_ACCESS)
|
||||
@Param(description = "Whether the calling account has access to this network's VPC", since = "4.21.0")
|
||||
private boolean vpcAccess;
|
||||
|
||||
@SerializedName(ApiConstants.VPC_ID)
|
||||
@Param(description = "VPC ID the IP belongs to")
|
||||
private String vpcId;
|
||||
|
|
@ -301,6 +305,10 @@ public class IPAddressResponse extends BaseResponseWithAnnotations implements Co
|
|||
this.purpose = purpose;
|
||||
}
|
||||
|
||||
public void setVpcAccess(boolean vpcAccess) {
|
||||
this.vpcAccess = vpcAccess;
|
||||
}
|
||||
|
||||
public void setVpcId(String vpcId) {
|
||||
this.vpcId = vpcId;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -203,6 +203,10 @@ public class NetworkResponse extends BaseResponseWithAssociatedNetwork implement
|
|||
@Param(description = "True if Network supports specifying IP ranges, false otherwise")
|
||||
private Boolean specifyIpRanges;
|
||||
|
||||
@SerializedName(ApiConstants.VPC_ACCESS)
|
||||
@Param(description = "Whether the calling account has access to this network's VPC", since = "4.21.0")
|
||||
private Boolean vpcAccess;
|
||||
|
||||
@SerializedName(ApiConstants.VPC_ID)
|
||||
@Param(description = "VPC the Network belongs to")
|
||||
private String vpcId;
|
||||
|
|
@ -523,6 +527,14 @@ public class NetworkResponse extends BaseResponseWithAssociatedNetwork implement
|
|||
this.specifyIpRanges = specifyIpRanges;
|
||||
}
|
||||
|
||||
public void setVpcAccess(boolean vpcAccess) {
|
||||
this.vpcAccess = vpcAccess;
|
||||
}
|
||||
|
||||
public Boolean getVpcAccess() {
|
||||
return vpcAccess;
|
||||
}
|
||||
|
||||
public void setVpcId(String vpcId) {
|
||||
this.vpcId = vpcId;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1167,7 +1167,7 @@ public class ApiResponseHelper implements ResponseGenerator, ResourceIdSupport {
|
|||
}
|
||||
|
||||
|
||||
setVpcIdInResponse(ipAddr.getVpcId(), ipResponse::setVpcId, ipResponse::setVpcName);
|
||||
setVpcIdInResponse(ipAddr.getVpcId(), ipResponse::setVpcId, ipResponse::setVpcName, ipResponse::setVpcAccess);
|
||||
|
||||
|
||||
// Network id the ip is associated with (if associated networkId is
|
||||
|
|
@ -1242,20 +1242,43 @@ public class ApiResponseHelper implements ResponseGenerator, ResourceIdSupport {
|
|||
return ipResponse;
|
||||
}
|
||||
|
||||
|
||||
private void setVpcIdInResponse(Long vpcId, Consumer<String> vpcUuidSetter, Consumer<String> vpcNameSetter) {
|
||||
if (vpcId != null) {
|
||||
Vpc vpc = ApiDBUtils.findVpcById(vpcId);
|
||||
if (vpc != null) {
|
||||
try {
|
||||
_accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, false, vpc);
|
||||
vpcUuidSetter.accept(vpc.getUuid());
|
||||
} catch (PermissionDeniedException e) {
|
||||
logger.debug("Not setting the vpcId to the response because the caller does not have access to the VPC");
|
||||
}
|
||||
vpcNameSetter.accept(vpc.getName());
|
||||
}
|
||||
protected void setVpcIdInResponse(Long vpcId, Consumer<String> vpcUuidSetter, Consumer<String> vpcNameSetter, Consumer<Boolean> vpcAccessSetter) {
|
||||
if (vpcId == null) {
|
||||
return;
|
||||
}
|
||||
Vpc vpc = ApiDBUtils.findVpcById(vpcId);
|
||||
if (vpc == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
_accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, false, vpc);
|
||||
vpcAccessSetter.accept(true);
|
||||
} catch (PermissionDeniedException e) {
|
||||
vpcAccessSetter.accept(false);
|
||||
logger.debug("Setting [{}] as false because the caller does not have access to the VPC [{}].", ApiConstants.VPC_ACCESS, vpc);
|
||||
}
|
||||
vpcNameSetter.accept(vpc.getName());
|
||||
vpcUuidSetter.accept(vpc.getUuid());
|
||||
}
|
||||
|
||||
protected void setAclIdInResponse(Network network, NetworkResponse response) {
|
||||
if (network.getNetworkACLId() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
NetworkACL acl = ApiDBUtils.findByNetworkACLId(network.getNetworkACLId());
|
||||
if (acl == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Boolean.FALSE.equals(response.getVpcAccess()) && acl.getVpcId() != 0) {
|
||||
logger.debug("[{}] not set in response, since caller does not have access to it.", acl);
|
||||
return;
|
||||
}
|
||||
|
||||
response.setAclId(acl.getUuid());
|
||||
response.setAclName(acl.getName());
|
||||
}
|
||||
|
||||
private void showVmInfoForSharedNetworks(boolean forVirtualNetworks, IpAddress ipAddr, IPAddressResponse ipResponse) {
|
||||
|
|
@ -2799,7 +2822,8 @@ public class ApiResponseHelper implements ResponseGenerator, ResourceIdSupport {
|
|||
|
||||
response.setSpecifyIpRanges(network.getSpecifyIpRanges());
|
||||
|
||||
setVpcIdInResponse(network.getVpcId(), response::setVpcId, response::setVpcName);
|
||||
setVpcIdInResponse(network.getVpcId(), response::setVpcId, response::setVpcName, response::setVpcAccess);
|
||||
setAclIdInResponse(network, response);
|
||||
|
||||
setResponseAssociatedNetworkInformation(response, network.getId());
|
||||
|
||||
|
|
@ -2816,14 +2840,6 @@ public class ApiResponseHelper implements ResponseGenerator, ResourceIdSupport {
|
|||
response.setHasAnnotation(annotationDao.hasAnnotations(network.getUuid(), AnnotationService.EntityType.NETWORK.name(),
|
||||
_accountMgr.isRootAdmin(CallContext.current().getCallingAccount().getId())));
|
||||
|
||||
if (network.getNetworkACLId() != null) {
|
||||
NetworkACL acl = ApiDBUtils.findByNetworkACLId(network.getNetworkACLId());
|
||||
if (acl != null) {
|
||||
response.setAclId(acl.getUuid());
|
||||
response.setAclName(acl.getName());
|
||||
}
|
||||
}
|
||||
|
||||
response.setStrechedL2Subnet(network.isStrechedL2Network());
|
||||
if (network.isStrechedL2Network()) {
|
||||
Set<String> networkSpannedZones = new HashSet<String>();
|
||||
|
|
|
|||
|
|
@ -29,6 +29,47 @@ import java.util.Set;
|
|||
import java.util.TimeZone;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.cloud.capacity.Capacity;
|
||||
import com.cloud.configuration.Resource;
|
||||
import com.cloud.domain.DomainVO;
|
||||
import com.cloud.exception.PermissionDeniedException;
|
||||
import com.cloud.network.Network;
|
||||
import com.cloud.network.PublicIpQuarantine;
|
||||
import com.cloud.network.as.AutoScaleVmGroup;
|
||||
import com.cloud.network.as.AutoScaleVmGroupVO;
|
||||
import com.cloud.network.as.AutoScaleVmProfileVO;
|
||||
import com.cloud.network.as.dao.AutoScaleVmGroupVmMapDao;
|
||||
import com.cloud.network.dao.IPAddressDao;
|
||||
import com.cloud.network.dao.IPAddressVO;
|
||||
import com.cloud.network.dao.LoadBalancerVO;
|
||||
import com.cloud.network.dao.NetworkServiceMapDao;
|
||||
import com.cloud.network.dao.NetworkVO;
|
||||
import com.cloud.network.vpc.NetworkACL;
|
||||
import com.cloud.network.vpc.VpcVO;
|
||||
import com.cloud.storage.VMTemplateVO;
|
||||
import com.cloud.usage.UsageVO;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.user.AccountManager;
|
||||
import com.cloud.user.AccountVO;
|
||||
import com.cloud.user.User;
|
||||
import com.cloud.user.UserData;
|
||||
import com.cloud.user.UserDataVO;
|
||||
import com.cloud.user.UserVO;
|
||||
import com.cloud.user.dao.UserDataDao;
|
||||
import com.cloud.utils.net.Ip;
|
||||
import com.cloud.vm.NicSecondaryIp;
|
||||
import org.apache.cloudstack.annotation.dao.AnnotationDao;
|
||||
import org.apache.cloudstack.api.response.AutoScaleVmGroupResponse;
|
||||
import org.apache.cloudstack.api.response.AutoScaleVmProfileResponse;
|
||||
import org.apache.cloudstack.api.response.DirectDownloadCertificateResponse;
|
||||
import org.apache.cloudstack.api.response.IpQuarantineResponse;
|
||||
import org.apache.cloudstack.api.response.NetworkResponse;
|
||||
import org.apache.cloudstack.api.response.NicSecondaryIpResponse;
|
||||
import org.apache.cloudstack.api.response.UnmanagedInstanceResponse;
|
||||
import org.apache.cloudstack.api.response.UsageRecordResponse;
|
||||
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;
|
||||
|
|
@ -42,40 +83,16 @@ 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;
|
||||
import org.apache.cloudstack.api.response.NicSecondaryIpResponse;
|
||||
import org.apache.cloudstack.api.response.ResourceIconResponse;
|
||||
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 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;
|
||||
import com.cloud.network.as.AutoScaleVmProfileVO;
|
||||
import com.cloud.network.as.dao.AutoScaleVmGroupVmMapDao;
|
||||
import com.cloud.network.dao.IPAddressDao;
|
||||
import com.cloud.network.dao.IPAddressVO;
|
||||
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;
|
||||
|
|
@ -83,19 +100,7 @@ import com.cloud.server.ResourceIcon;
|
|||
import com.cloud.server.ResourceIconManager;
|
||||
import com.cloud.server.ResourceTag;
|
||||
import com.cloud.storage.GuestOsCategory;
|
||||
import com.cloud.storage.VMTemplateVO;
|
||||
import com.cloud.usage.UsageVO;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.user.AccountManager;
|
||||
import com.cloud.user.AccountVO;
|
||||
import com.cloud.user.User;
|
||||
import com.cloud.user.UserData;
|
||||
import com.cloud.user.UserDataVO;
|
||||
import com.cloud.user.UserVO;
|
||||
import com.cloud.user.dao.UserDataDao;
|
||||
import com.cloud.utils.net.Ip;
|
||||
import com.cloud.vm.ConsoleSessionVO;
|
||||
import com.cloud.vm.NicSecondaryIp;
|
||||
import com.cloud.vm.VMInstanceVO;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
|
@ -150,6 +155,12 @@ public class ApiResponseHelperTest {
|
|||
@Mock
|
||||
private VMInstanceVO vmInstanceVOMock;
|
||||
|
||||
@Mock
|
||||
private VpcVO vpcVOMock;
|
||||
|
||||
@Mock
|
||||
private NetworkACL networkACLMock;
|
||||
|
||||
@Spy
|
||||
@InjectMocks
|
||||
ApiResponseHelper apiResponseHelper = new ApiResponseHelper();
|
||||
|
|
@ -168,6 +179,9 @@ public class ApiResponseHelperTest {
|
|||
|
||||
static long autoScaleUserId = 7L;
|
||||
|
||||
static final String A_NAME = "name";
|
||||
static final String A_UUID = "021f94d4-73f9-4a9a-b003-1df9dd968a09";
|
||||
|
||||
@Before
|
||||
public void injectMocks() throws SecurityException, NoSuchFieldException,
|
||||
IllegalArgumentException, IllegalAccessException {
|
||||
|
|
@ -800,4 +814,135 @@ public class ApiResponseHelperTest {
|
|||
Assert.assertEquals(expected.getVmName(), response.getVmName());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setVpcIdInResponseTestNullVpcIdReturnNull() {
|
||||
NetworkResponse networkResponse = new NetworkResponse();
|
||||
|
||||
apiResponseHelper.setVpcIdInResponse(null, networkResponse::setVpcId, networkResponse::setVpcName, networkResponse::setVpcAccess);
|
||||
Assert.assertNull(networkResponse.getVpcId());
|
||||
Assert.assertNull(networkResponse.getVpcName());
|
||||
Assert.assertNull(networkResponse.getVpcAccess());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setVpcIdInResponseTestNullVpcReturnNull() {
|
||||
NetworkResponse networkResponse = new NetworkResponse();
|
||||
|
||||
try (MockedStatic<ApiDBUtils> utils = Mockito.mockStatic(ApiDBUtils.class)) {
|
||||
utils.when(() -> ApiDBUtils.findVpcById(1L)).thenReturn(null);
|
||||
apiResponseHelper.setVpcIdInResponse(1L, networkResponse::setVpcId, networkResponse::setVpcName, networkResponse::setVpcAccess);
|
||||
}
|
||||
Assert.assertNull(networkResponse.getVpcId());
|
||||
Assert.assertNull(networkResponse.getVpcName());
|
||||
Assert.assertNull(networkResponse.getVpcAccess());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setVpcIdInResponseCallerHasAccessReturnVpcAccessTrueAndVpcIdAndVpcName() {
|
||||
NetworkResponse networkResponse = new NetworkResponse();
|
||||
Mockito.when(vpcVOMock.getName()).thenReturn(A_NAME);
|
||||
Mockito.when(vpcVOMock.getUuid()).thenReturn(A_UUID);
|
||||
|
||||
try (MockedStatic<ApiDBUtils> utils = Mockito.mockStatic(ApiDBUtils.class)) {
|
||||
utils.when(() -> ApiDBUtils.findVpcById(1L)).thenReturn(vpcVOMock);
|
||||
apiResponseHelper.setVpcIdInResponse(1L, networkResponse::setVpcId, networkResponse::setVpcName, networkResponse::setVpcAccess);
|
||||
};
|
||||
Assert.assertEquals(A_UUID, networkResponse.getVpcId());
|
||||
Assert.assertEquals(A_NAME, networkResponse.getVpcName());
|
||||
Assert.assertTrue(networkResponse.getVpcAccess());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setVpcIdInResponseCallerDoesNotHaveAccessReturnVpcAccessFalseAndVpcIdAndVpcName() {
|
||||
NetworkResponse networkResponse = new NetworkResponse();
|
||||
Mockito.when(vpcVOMock.getName()).thenReturn(A_NAME);
|
||||
Mockito.when(vpcVOMock.getUuid()).thenReturn(A_UUID);
|
||||
|
||||
try (MockedStatic<ApiDBUtils> utils = Mockito.mockStatic(ApiDBUtils.class)) {
|
||||
utils.when(() -> ApiDBUtils.findVpcById(1L)).thenReturn(vpcVOMock);
|
||||
Mockito.doThrow(PermissionDeniedException.class).when(accountManagerMock).checkAccess(Mockito.any(), Mockito.any(), Mockito.anyBoolean(), Mockito.any());
|
||||
apiResponseHelper.setVpcIdInResponse(1L, networkResponse::setVpcId, networkResponse::setVpcName, networkResponse::setVpcAccess);
|
||||
};
|
||||
Assert.assertEquals(A_UUID, networkResponse.getVpcId());
|
||||
Assert.assertEquals(A_NAME, networkResponse.getVpcName());
|
||||
Assert.assertFalse(networkResponse.getVpcAccess());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setAclIdInResponseTestNullNetworkAclIdReturnNull() {
|
||||
NetworkResponse networkResponse = new NetworkResponse();
|
||||
Network networkMock = Mockito.mock(Network.class);
|
||||
Mockito.when(networkMock.getNetworkACLId()).thenReturn(null);
|
||||
|
||||
apiResponseHelper.setAclIdInResponse(networkMock, networkResponse);
|
||||
Assert.assertNull(networkResponse.getAclId());
|
||||
Assert.assertNull(networkResponse.getAclName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setAclIdInResponseTestNullAclReturnNull() {
|
||||
NetworkResponse networkResponse = new NetworkResponse();
|
||||
Network networkMock = Mockito.mock(Network.class);
|
||||
Mockito.when(networkMock.getNetworkACLId()).thenReturn(1L);
|
||||
|
||||
try (MockedStatic<ApiDBUtils> utils = Mockito.mockStatic(ApiDBUtils.class)) {
|
||||
utils.when(() -> ApiDBUtils.findByNetworkACLId(1L)).thenReturn(null);
|
||||
apiResponseHelper.setAclIdInResponse(networkMock, networkResponse);
|
||||
}
|
||||
Assert.assertNull(networkResponse.getAclId());
|
||||
Assert.assertNull(networkResponse.getAclName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setAclIdInResponseTestCallerDoesNotHaveAccessReturnNull() {
|
||||
NetworkResponse networkResponse = new NetworkResponse();
|
||||
networkResponse.setVpcAccess(false);
|
||||
Network networkMock = Mockito.mock(Network.class);
|
||||
Mockito.when(networkMock.getNetworkACLId()).thenReturn(1L);
|
||||
Mockito.when(networkACLMock.getVpcId()).thenReturn(2L);
|
||||
|
||||
try (MockedStatic<ApiDBUtils> utils = Mockito.mockStatic(ApiDBUtils.class)) {
|
||||
utils.when(() -> ApiDBUtils.findByNetworkACLId(1L)).thenReturn(networkACLMock);
|
||||
apiResponseHelper.setAclIdInResponse(networkMock, networkResponse);
|
||||
}
|
||||
Assert.assertNull(networkResponse.getAclId());
|
||||
Assert.assertNull(networkResponse.getAclName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setAclIdInResponseTestCallerDoesNotHaveAccessButAclIsGlobalReturnAclIdAndAclName() {
|
||||
NetworkResponse networkResponse = new NetworkResponse();
|
||||
networkResponse.setVpcAccess(false);
|
||||
Network networkMock = Mockito.mock(Network.class);
|
||||
Mockito.when(networkMock.getNetworkACLId()).thenReturn(1L);
|
||||
Mockito.when(networkACLMock.getVpcId()).thenReturn(0L);
|
||||
Mockito.when(networkACLMock.getName()).thenReturn(A_NAME);
|
||||
Mockito.when(networkACLMock.getUuid()).thenReturn(A_UUID);
|
||||
|
||||
try (MockedStatic<ApiDBUtils> utils = Mockito.mockStatic(ApiDBUtils.class)) {
|
||||
utils.when(() -> ApiDBUtils.findByNetworkACLId(1L)).thenReturn(networkACLMock);
|
||||
apiResponseHelper.setAclIdInResponse(networkMock, networkResponse);
|
||||
}
|
||||
Assert.assertEquals(A_UUID, networkResponse.getAclId());
|
||||
Assert.assertEquals(A_NAME, networkResponse.getAclName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setAclIdInResponseTestCallerHasAccessReturnAclIdAndAclName() {
|
||||
NetworkResponse networkResponse = new NetworkResponse();
|
||||
networkResponse.setVpcAccess(true);
|
||||
Network networkMock = Mockito.mock(Network.class);
|
||||
Mockito.when(networkMock.getNetworkACLId()).thenReturn(1L);
|
||||
Mockito.lenient().when(networkACLMock.getVpcId()).thenReturn(2L);
|
||||
Mockito.when(networkACLMock.getName()).thenReturn(A_NAME);
|
||||
Mockito.when(networkACLMock.getUuid()).thenReturn(A_UUID);
|
||||
|
||||
try (MockedStatic<ApiDBUtils> utils = Mockito.mockStatic(ApiDBUtils.class)) {
|
||||
utils.when(() -> ApiDBUtils.findByNetworkACLId(1L)).thenReturn(networkACLMock);
|
||||
apiResponseHelper.setAclIdInResponse(networkMock, networkResponse);
|
||||
}
|
||||
Assert.assertEquals(A_UUID, networkResponse.getAclId());
|
||||
Assert.assertEquals(A_NAME, networkResponse.getAclName());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -570,7 +570,129 @@
|
|||
<gold-outlined />
|
||||
<router-link :to="{ path: '/autoscalevmgroup/' + resource.autoscalevmgroupid }">{{ resource.autoscalevmgroupname || resource.autoscalevmgroupid }}</router-link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="resource-detail-item" v-if="resource.resourcetype && resource.resourceid && routeFromResourceType">
|
||||
<div class="resource-detail-item__label">{{ $t('label.resource') }}</div>
|
||||
<div class="resource-detail-item__details">
|
||||
<resource-label :resourceType="resource.resourcetype" :resourceId="resource.resourceid" :resourceName="resource.resourcename" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="resource-detail-item" v-if="resource.virtualmachineid">
|
||||
<div class="resource-detail-item__label">{{ $t('label.vmname') }}</div>
|
||||
<div class="resource-detail-item__details">
|
||||
<desktop-outlined />
|
||||
<router-link :to="{ path: createPathBasedOnVmType(resource.vmtype, resource.virtualmachineid) }">{{ resource.vmname || resource.vm || resource.virtualmachinename || resource.virtualmachineid }} </router-link>
|
||||
<status class="status status--end" :text="resource.vmstate" v-if="resource.vmstate"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="resource-detail-item" v-if="resource.volumeid">
|
||||
<div class="resource-detail-item__label">{{ $t('label.volume') }}</div>
|
||||
<div class="resource-detail-item__details">
|
||||
<hdd-outlined />
|
||||
<router-link v-if="validLinks.volume" :to="{ path: '/volume/' + resource.volumeid }">{{ resource.volumename || resource.volume || resource.volumeid }} </router-link>
|
||||
<span v-else>{{ resource.volumename || resource.volume || resource.volumeid }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="resource-detail-item" v-if="resource.associatednetworkid">
|
||||
<div class="resource-detail-item__label">{{ $t('label.associatednetwork') }}</div>
|
||||
<div class="resource-detail-item__details">
|
||||
<wifi-outlined />
|
||||
<router-link :to="{ path: '/guestnetwork/' + resource.associatednetworkid }">{{ resource.associatednetworkname || resource.associatednetwork || resource.associatednetworkid }} </router-link>
|
||||
</div>
|
||||
</div>
|
||||
<div class="resource-detail-item" v-if="resource.sourceipaddressnetworkid">
|
||||
<div class="resource-detail-item__label">{{ $t('label.network') }}</div>
|
||||
<div class="resource-detail-item__details">
|
||||
<wifi-outlined />
|
||||
<router-link :to="{ path: '/guestnetwork/' + resource.sourceipaddressnetworkid }">{{ resource.sourceipaddressnetworkname || resource.sourceipaddressnetworkid }} </router-link>
|
||||
</div>
|
||||
</div>
|
||||
<div class="resource-detail-item" v-if="resource.guestnetworkid">
|
||||
<div class="resource-detail-item__label">{{ $t('label.guestnetwork') }}</div>
|
||||
<div class="resource-detail-item__details">
|
||||
<gateway-outlined />
|
||||
<router-link :to="{ path: '/guestnetwork/' + resource.guestnetworkid }">{{ resource.guestnetworkname || resource.guestnetworkid }} </router-link>
|
||||
</div>
|
||||
</div>
|
||||
<div class="resource-detail-item" v-if="resource.publicip">
|
||||
<div class="resource-detail-item__label">{{ $t('label.public.ip') }}</div>
|
||||
<div class="resource-detail-item__details">
|
||||
<gateway-outlined />
|
||||
<router-link v-if="resource.publicipid" :to="{ path: '/publicip/' + resource.publicipid }">{{ resource.publicip }} </router-link>
|
||||
<copy-label v-if="resource.publicipid" :copyValue="resource.publicip" :showIcon=true />
|
||||
<copy-label v-else :label="resource.publicip" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="resource-detail-item" v-if="resource.vpcid">
|
||||
<div class="resource-detail-item__label">{{ $t('label.vpcname') }}</div>
|
||||
<div class="resource-detail-item__details">
|
||||
<span v-if="images.vpc">
|
||||
<resource-icon :image="getImage(images.vpc)" size="1x" style="margin-right: 5px"/>
|
||||
</span>
|
||||
<deployment-unit-outlined v-else />
|
||||
<router-link v-if="resource.vpcaccess" :to="{ path: '/vpc/' + resource.vpcid }">{{ resource.vpcname || resource.vpcid }}</router-link>
|
||||
<span v-else>{{ resource.vpcname || resource.vpcid }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="resource-detail-item" v-if="resource.aclid">
|
||||
<div class="resource-detail-item__label">{{ $t('label.aclid') }}</div>
|
||||
<div class="resource-detail-item__details">
|
||||
<span v-if="images.acl">
|
||||
<resource-icon :image="getImage(images.acl)" size="1x" style="margin-right: 5px"/>
|
||||
</span>
|
||||
<deployment-unit-outlined v-else />
|
||||
<router-link :to="{ path: '/acllist/' + resource.aclid }">{{ resource.aclname || resource.aclid }}</router-link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="resource-detail-item" v-if="resource.affinitygroup && resource.affinitygroup.length > 0">
|
||||
<div class="resource-detail-item__label">{{ $t('label.affinitygroup') }}</div>
|
||||
<SwapOutlined />
|
||||
<span
|
||||
v-for="(group, index) in resource.affinitygroup"
|
||||
:key="group.id"
|
||||
>
|
||||
<router-link :to="{ path: '/affinitygroup/' + group.id }">{{ group.name }}</router-link>
|
||||
<span v-if="index + 1 < resource.affinitygroup.length">, </span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="resource-detail-item" v-if="resource.templateid">
|
||||
<div class="resource-detail-item__label">{{ resource.templateformat === 'ISO'? $t('label.iso') : $t('label.templatename') }}</div>
|
||||
<div class="resource-detail-item__details">
|
||||
<resource-icon v-if="resource.icon" :image="getImage(resource.icon.base64image)" size="1x" style="margin-right: 5px"/>
|
||||
<SaveOutlined v-else />
|
||||
<router-link :to="{ path: (resource.templateformat === 'ISO' ? '/iso/' : '/template/') + resource.templateid }">{{ resource.templatedisplaytext || resource.templatename || resource.templateid }} </router-link>
|
||||
</div>
|
||||
</div>
|
||||
<div class="resource-detail-item" v-if="resource.isoid">
|
||||
<div class="resource-detail-item__label">{{ $t('label.isoname') }}</div>
|
||||
<div class="resource-detail-item__details">
|
||||
<resource-icon v-if="resource.icon" :image="getImage(resource.icon.base64image)" size="1x" style="margin-right: 5px"/>
|
||||
<UsbOutlined v-else />
|
||||
<router-link :to="{ path: '/iso/' + resource.isoid }">{{ resource.isodisplaytext || resource.isoname || resource.isoid }} </router-link>
|
||||
</div>
|
||||
</div>
|
||||
<div class="resource-detail-item" v-if="resource.serviceofferingname && resource.serviceofferingid">
|
||||
<div class="resource-detail-item__label" v-if="$route.meta.name === 'router' || $route.meta.name === 'systemvm'">{{ $t('label.system.offering') }}</div>
|
||||
<div class="resource-detail-item__label" v-else >{{ $t('label.serviceofferingname') }}</div>
|
||||
<div class="resource-detail-item__details">
|
||||
<cloud-outlined />
|
||||
<router-link v-if="!isStatic && ($route.meta.name === 'router' || $route.meta.name === 'systemvm')" :to="{ path: '/systemoffering/' + resource.serviceofferingid}">{{ resource.serviceofferingname || resource.serviceofferingid }} </router-link>
|
||||
<router-link v-else-if="$router.resolve('/computeoffering/' + resource.serviceofferingid).matched[0].redirect !== '/exception/404'" :to="{ path: '/computeoffering/' + resource.serviceofferingid }">{{ resource.serviceofferingname || resource.serviceofferingid }} </router-link>
|
||||
<span v-else>{{ resource.serviceofferingname || resource.serviceofferingid }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="resource-detail-item" v-if="resource.rootdiskofferingid && resource.rootdiskofferingdisplaytext || resource.datadiskofferingid && resource.datadiskofferingdisplaytext">
|
||||
<div class="resource-detail-item__label">{{ $t('label.diskoffering') }}</div>
|
||||
<div class="resource-detail-item__details">
|
||||
<hdd-outlined />
|
||||
<div v-if="resource.rootdiskofferingid">
|
||||
<router-link v-if="!isStatic && $router.resolve('/diskoffering/' + resource.rootdiskofferingid).matched[0].redirect !== '/exception/404'" :to="{ path: '/diskoffering/' + resource.rootdiskofferingid }">{{ resource.rootdiskofferingdisplaytext }}</router-link>
|
||||
<span v-else>{{ resource.rootdiskofferingdisplaytext }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="resource-detail-item" v-if="resource.keypairs && resource.keypairs.length > 0">
|
||||
<div class="resource-detail-item__label">{{ $t('label.keypairs') }}</div>
|
||||
<div class="resource-detail-item__details">
|
||||
|
|
|
|||
|
|
@ -585,7 +585,7 @@
|
|||
<router-link :to="{ path: '/guestnetwork/' + record.associatednetworkid }">{{ text }}</router-link>
|
||||
</template>
|
||||
<template v-if="column.key === 'vpcname'">
|
||||
<a v-if="record.vpcid">
|
||||
<a v-if="record.vpcid && record.vpcaccess">
|
||||
<router-link :to="{ path: '/vpc/' + record.vpcid }">{{ text || record.vpcid }}</router-link>
|
||||
</a>
|
||||
<span v-else>{{ text }}</span>
|
||||
|
|
|
|||
|
|
@ -145,7 +145,9 @@
|
|||
centered
|
||||
width="450px">
|
||||
<a-spin :spinning="acquireLoading" v-ctrl-enter="acquireIpAddress">
|
||||
<a-alert :message="$t('message.action.acquire.ip')" type="warning" />
|
||||
<div v-if="$route.path.startsWith('/vpc') && !isNormalUserOrProject()">
|
||||
<ownership-selection :override="possibleOwnership" @fetch-owner="fetchOwnerOptions"/>
|
||||
</div>
|
||||
<a-form layout="vertical" style="margin-top: 10px">
|
||||
<a-form-item :label="$t('label.ipaddress')">
|
||||
<infinite-scroll-select
|
||||
|
|
@ -160,6 +162,7 @@
|
|||
:autoSelectFirstOption="true"
|
||||
@change-option-value="(ip) => acquireIp = ip" />
|
||||
</a-form-item>
|
||||
<a-alert :message="$t('message.action.acquire.ip')" type="warning" />
|
||||
<div :span="24" class="action-button">
|
||||
<a-button @click="onCloseModal">{{ $t('label.cancel') }}</a-button>
|
||||
<a-button ref="submit" type="primary" @click="acquireIpAddress">{{ $t('label.ok') }}</a-button>
|
||||
|
|
@ -210,6 +213,7 @@ import TooltipButton from '@/components/widgets/TooltipButton'
|
|||
import BulkActionView from '@/components/view/BulkActionView'
|
||||
import eventBus from '@/config/eventBus'
|
||||
import InfiniteScrollSelect from '@/components/widgets/InfiniteScrollSelect'
|
||||
import OwnershipSelection from '@/views/compute/wizard/OwnershipSelection.vue'
|
||||
|
||||
export default {
|
||||
name: 'IpAddressesTab',
|
||||
|
|
@ -217,7 +221,8 @@ export default {
|
|||
Status,
|
||||
TooltipButton,
|
||||
BulkActionView,
|
||||
InfiniteScrollSelect
|
||||
InfiniteScrollSelect,
|
||||
OwnershipSelection
|
||||
},
|
||||
props: {
|
||||
resource: {
|
||||
|
|
@ -281,7 +286,12 @@ export default {
|
|||
acquireLoading: false,
|
||||
acquireIp: null,
|
||||
changeSourceNat: false,
|
||||
zoneExtNetProvider: ''
|
||||
zoneExtNetProvider: '',
|
||||
possibleOwnership: {
|
||||
domains: null,
|
||||
projects: null,
|
||||
accounts: null
|
||||
}
|
||||
}
|
||||
},
|
||||
async created () {
|
||||
|
|
@ -321,6 +331,9 @@ export default {
|
|||
}
|
||||
},
|
||||
methods: {
|
||||
isNormalUserOrProject () {
|
||||
return ['User'].includes(this.$store.getters.userInfo.roletype) || this.$store.getters.project?.id
|
||||
},
|
||||
fetchData () {
|
||||
const params = {
|
||||
listall: true,
|
||||
|
|
@ -334,6 +347,7 @@ export default {
|
|||
if (this.vpcTier) {
|
||||
params.associatednetworkid = this.vpcTier
|
||||
}
|
||||
this.getAvailableOwnersForIP()
|
||||
} else if (this.resource.type === 'Shared') {
|
||||
params.networkid = this.resource.id
|
||||
params.allocatedonly = false
|
||||
|
|
@ -362,13 +376,20 @@ export default {
|
|||
}).catch(reject)
|
||||
})
|
||||
},
|
||||
fetchListPublicIpAddress (state) {
|
||||
return new Promise((resolve, reject) => {
|
||||
getAPI('listPublicIpAddresses', this.listApiParams).then(json => {
|
||||
const listPublicIps = json.listpublicipaddressesresponse.publicipaddress || []
|
||||
resolve(listPublicIps)
|
||||
}).catch(reject)
|
||||
})
|
||||
fetchOwnerOptions (OwnerOptions) {
|
||||
this.owner = {}
|
||||
if (OwnerOptions.selectedAccountType === this.$t('label.account')) {
|
||||
if (!OwnerOptions.selectedAccount) {
|
||||
return
|
||||
}
|
||||
this.owner.account = OwnerOptions.selectedAccount
|
||||
this.owner.domainid = OwnerOptions.selectedDomain
|
||||
} else if (OwnerOptions.selectedAccountType === this.$t('label.project')) {
|
||||
if (!OwnerOptions.selectedProject) {
|
||||
return
|
||||
}
|
||||
this.owner.projectid = OwnerOptions.selectedProject
|
||||
}
|
||||
},
|
||||
handleTierSelect (tier) {
|
||||
this.vpcTier = tier
|
||||
|
|
@ -453,6 +474,11 @@ export default {
|
|||
const params = {}
|
||||
if (this.$route.path.startsWith('/vpc')) {
|
||||
params.vpcid = this.resource.id
|
||||
if (this.owner) {
|
||||
params.domainid = this.owner.domainid
|
||||
params.account = this.owner.projectid ? null : this.owner.account
|
||||
params.projectid = this.owner.projectid ? this.owner.projectid : null
|
||||
}
|
||||
if (this.vpcTier) {
|
||||
params.networkid = this.vpcTier
|
||||
}
|
||||
|
|
@ -560,6 +586,20 @@ export default {
|
|||
default: return '/vm/'
|
||||
}
|
||||
},
|
||||
getAvailableOwnersForIP () {
|
||||
this.possibleOwnership.domains = new Set([this.resource.domainid])
|
||||
this.possibleOwnership.projects = this.resource.projectid ? new Set([this.resource.projectid]) : new Set([])
|
||||
this.possibleOwnership.accounts = this.resource.projectid ? new Set([]) : new Set([this.resource.account])
|
||||
|
||||
this.resource.network.forEach(network => {
|
||||
this.possibleOwnership.domains.add(network.domainid)
|
||||
if (network.projectid) {
|
||||
this.possibleOwnership.projects.add(network.projectid)
|
||||
} else {
|
||||
this.possibleOwnership.accounts.add(network.account)
|
||||
}
|
||||
})
|
||||
},
|
||||
async onShowAcquireIp () {
|
||||
this.showAcquireIp = true
|
||||
},
|
||||
|
|
|
|||
|
|
@ -34,7 +34,14 @@
|
|||
{{ $t('label.name') }}
|
||||
</div>
|
||||
<div>
|
||||
<router-link :to="{ path: '/guestnetwork/' + network.id }">{{ network.name }} </router-link>
|
||||
<router-link
|
||||
v-if="network.projectid"
|
||||
:to="{ path: '/guestnetwork/' + network.id, query: {projectid: -1 }}">
|
||||
{{ network.name }}
|
||||
</router-link>
|
||||
<router-link v-else :to="{ path: '/guestnetwork/' + network.id }">
|
||||
{{ network.name }}
|
||||
</router-link>
|
||||
<a-tag v-if="network.broadcasturi">{{ network.broadcasturi }}</a-tag>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -58,6 +65,32 @@
|
|||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="list__col"
|
||||
v-if="(network.projectid && resource.account) || (network.projectid !== resource.projectid)"
|
||||
>
|
||||
<div class="list__label">
|
||||
{{ $t('label.project') }}
|
||||
</div>
|
||||
<div>
|
||||
<router-link :to="{ path: '/project/' + network.projectid }">
|
||||
{{ network.project }}
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="list__col"
|
||||
v-else-if="(network.account && resource.projectid) || network.account !== resource.account || network.domainid !== resource.domainid"
|
||||
>
|
||||
<div class="list__label">
|
||||
{{ $t('label.account') }}
|
||||
</div>
|
||||
<div>
|
||||
<router-link :to="{ path: '/account', query: { name: network.account, domainid: network.domainid, dataView: true } }">
|
||||
{{ network.account }}
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<a-collapse :bordered="false" style="margin-left: -18px">
|
||||
<template #expandIcon="props">
|
||||
|
|
@ -166,6 +199,9 @@
|
|||
:footer="null"
|
||||
@cancel="showCreateNetworkModal = false">
|
||||
<a-spin :spinning="modalLoading" v-ctrl-enter="handleAddNetworkSubmit">
|
||||
<div v-if="!isNormalUserOrProject()">
|
||||
<ownership-selection @fetch-owner="fetchOwnerOptions"/>
|
||||
</div>
|
||||
<a-form
|
||||
layout="vertical"
|
||||
:ref="formRef"
|
||||
|
|
@ -370,11 +406,13 @@ import { mixinForm } from '@/utils/mixin'
|
|||
import Status from '@/components/widgets/Status'
|
||||
import TooltipLabel from '@/components/widgets/TooltipLabel'
|
||||
import { getNetmaskFromCidr } from '@/utils/network'
|
||||
import OwnershipSelection from '@/views/compute/wizard/OwnershipSelection.vue'
|
||||
|
||||
export default {
|
||||
name: 'VpcTiersTab',
|
||||
mixins: [mixinForm],
|
||||
components: {
|
||||
OwnershipSelection,
|
||||
Status,
|
||||
TooltipLabel
|
||||
},
|
||||
|
|
@ -506,6 +544,9 @@ export default {
|
|||
isObjectEmpty (obj) {
|
||||
return !(obj !== null && obj !== undefined && Object.keys(obj).length > 0 && obj.constructor === Object)
|
||||
},
|
||||
isNormalUserOrProject () {
|
||||
return ['User'].includes(this.$store.getters.userInfo.roletype) || this.$store.getters.project?.id
|
||||
},
|
||||
initForm () {
|
||||
this.formRef = ref()
|
||||
this.form = reactive({})
|
||||
|
|
@ -531,11 +572,28 @@ export default {
|
|||
}
|
||||
for (const network of this.networks) {
|
||||
this.fetchLoadBalancers(network.id)
|
||||
this.fetchVMs(network.id)
|
||||
this.fetchVMs(network)
|
||||
this.updateDisplayCollapsible(network.networkofferingid, network)
|
||||
}
|
||||
this.publicLBNetworkExists()
|
||||
},
|
||||
fetchOwnerOptions (OwnerOptions) {
|
||||
this.owner = {}
|
||||
if (OwnerOptions.selectedAccountType === this.$t('label.account')) {
|
||||
if (!OwnerOptions.selectedAccount) {
|
||||
this.owner = undefined
|
||||
return
|
||||
}
|
||||
this.owner.account = OwnerOptions.selectedAccount
|
||||
this.owner.domainid = OwnerOptions.selectedDomain
|
||||
} else if (OwnerOptions.selectedAccountType === this.$t('label.project')) {
|
||||
if (!OwnerOptions.selectedProject) {
|
||||
this.owner = undefined
|
||||
return
|
||||
}
|
||||
this.owner.projectid = OwnerOptions.selectedProject
|
||||
}
|
||||
},
|
||||
fetchMtuForZone () {
|
||||
getAPI('listZones', {
|
||||
id: this.resource.zoneid
|
||||
|
|
@ -675,17 +733,21 @@ export default {
|
|||
this.fetchLoading = false
|
||||
})
|
||||
},
|
||||
fetchVMs (id) {
|
||||
fetchVMs (network) {
|
||||
this.fetchLoading = true
|
||||
getAPI('listVirtualMachines', {
|
||||
var params = {
|
||||
listAll: true,
|
||||
vpcid: this.resource.id,
|
||||
networkid: id,
|
||||
networkid: network.id,
|
||||
page: this.page,
|
||||
pagesize: this.pageSize
|
||||
}).then(json => {
|
||||
this.vms[id] = json.listvirtualmachinesresponse.virtualmachine || []
|
||||
this.itemCounts.vms[id] = json.listvirtualmachinesresponse.count || 0
|
||||
}
|
||||
if (network.projectid) {
|
||||
params.projectid = -1
|
||||
}
|
||||
getAPI('listVirtualMachines', params).then(json => {
|
||||
this.vms[network.id] = json.listvirtualmachinesresponse.virtualmachine || []
|
||||
this.itemCounts.vms[network.id] = json.listvirtualmachinesresponse.count || 0
|
||||
}).finally(() => {
|
||||
this.fetchLoading = false
|
||||
})
|
||||
|
|
@ -748,8 +810,9 @@ export default {
|
|||
this.showCreateNetworkModal = false
|
||||
var params = {
|
||||
vpcid: this.resource.id,
|
||||
domainid: this.resource.domainid,
|
||||
account: this.resource.account,
|
||||
domainid: this.owner?.domainid || this.resource.domainid,
|
||||
account: this.owner?.projectid ? null : (this.owner?.account || this.resource.account),
|
||||
projectid: this.owner?.projectid || null,
|
||||
networkOfferingId: values.networkOffering,
|
||||
name: values.name,
|
||||
displayText: values.name,
|
||||
|
|
|
|||
Loading…
Reference in New Issue