mirror of https://github.com/apache/cloudstack.git
api,server,ui: improve listing public ip for associate (#11591)
Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
This commit is contained in:
parent
dba889ea3e
commit
9ec8cc4186
|
|
@ -53,7 +53,7 @@ public class ListPublicIpAddressesCmd extends BaseListRetrieveOnlyResourceCountC
|
||||||
@Parameter(name = ApiConstants.ALLOCATED_ONLY, type = CommandType.BOOLEAN, description = "limits search results to allocated public IP addresses")
|
@Parameter(name = ApiConstants.ALLOCATED_ONLY, type = CommandType.BOOLEAN, description = "limits search results to allocated public IP addresses")
|
||||||
private Boolean allocatedOnly;
|
private Boolean allocatedOnly;
|
||||||
|
|
||||||
@Parameter(name = ApiConstants.STATE, type = CommandType.STRING, description = "lists all public IP addresses by state")
|
@Parameter(name = ApiConstants.STATE, type = CommandType.STRING, description = "lists all public IP addresses by state. A comma-separated list of states can be passed")
|
||||||
private String state;
|
private String state;
|
||||||
|
|
||||||
@Parameter(name = ApiConstants.FOR_VIRTUAL_NETWORK, type = CommandType.BOOLEAN, description = "the virtual network for the IP address")
|
@Parameter(name = ApiConstants.FOR_VIRTUAL_NETWORK, type = CommandType.BOOLEAN, description = "the virtual network for the IP address")
|
||||||
|
|
|
||||||
|
|
@ -823,6 +823,7 @@ import com.cloud.user.dao.AccountDao;
|
||||||
import com.cloud.user.dao.SSHKeyPairDao;
|
import com.cloud.user.dao.SSHKeyPairDao;
|
||||||
import com.cloud.user.dao.UserDao;
|
import com.cloud.user.dao.UserDao;
|
||||||
import com.cloud.user.dao.UserDataDao;
|
import com.cloud.user.dao.UserDataDao;
|
||||||
|
import com.cloud.utils.EnumUtils;
|
||||||
import com.cloud.utils.NumbersUtil;
|
import com.cloud.utils.NumbersUtil;
|
||||||
import com.cloud.utils.Pair;
|
import com.cloud.utils.Pair;
|
||||||
import com.cloud.utils.PasswordGenerator;
|
import com.cloud.utils.PasswordGenerator;
|
||||||
|
|
@ -2419,6 +2420,22 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
|
||||||
return new Pair<>(result.first(), result.second());
|
return new Pair<>(result.first(), result.second());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected List<IpAddress.State> getStatesForIpAddressSearch(final ListPublicIpAddressesCmd cmd) {
|
||||||
|
final String statesStr = cmd.getState();
|
||||||
|
final List<IpAddress.State> states = new ArrayList<>();
|
||||||
|
if (StringUtils.isBlank(statesStr)) {
|
||||||
|
return states;
|
||||||
|
}
|
||||||
|
for (String s : StringUtils.split(statesStr, ",")) {
|
||||||
|
IpAddress.State state = EnumUtils.getEnumIgnoreCase(IpAddress.State.class, s.trim());
|
||||||
|
if (state == null) {
|
||||||
|
throw new InvalidParameterValueException("Invalid state: " + s);
|
||||||
|
}
|
||||||
|
states.add(state);
|
||||||
|
}
|
||||||
|
return states;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Pair<List<? extends IpAddress>, Integer> searchForIPAddresses(final ListPublicIpAddressesCmd cmd) {
|
public Pair<List<? extends IpAddress>, Integer> searchForIPAddresses(final ListPublicIpAddressesCmd cmd) {
|
||||||
final Long associatedNetworkId = cmd.getAssociatedNetworkId();
|
final Long associatedNetworkId = cmd.getAssociatedNetworkId();
|
||||||
|
|
@ -2429,20 +2446,20 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
|
||||||
final Long networkId = cmd.getNetworkId();
|
final Long networkId = cmd.getNetworkId();
|
||||||
final Long vpcId = cmd.getVpcId();
|
final Long vpcId = cmd.getVpcId();
|
||||||
|
|
||||||
final String state = cmd.getState();
|
final List<IpAddress.State> states = getStatesForIpAddressSearch(cmd);
|
||||||
Boolean isAllocated = cmd.isAllocatedOnly();
|
Boolean isAllocated = cmd.isAllocatedOnly();
|
||||||
if (isAllocated == null) {
|
if (isAllocated == null) {
|
||||||
if (state != null && (state.equalsIgnoreCase(IpAddress.State.Free.name()) || state.equalsIgnoreCase(IpAddress.State.Reserved.name()))) {
|
if (states.contains(IpAddress.State.Free) || states.contains(IpAddress.State.Reserved)) {
|
||||||
isAllocated = Boolean.FALSE;
|
isAllocated = Boolean.FALSE;
|
||||||
} else {
|
} else {
|
||||||
isAllocated = Boolean.TRUE; // default
|
isAllocated = Boolean.TRUE; // default
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (state != null && (state.equalsIgnoreCase(IpAddress.State.Free.name()) || state.equalsIgnoreCase(IpAddress.State.Reserved.name()))) {
|
if (states.contains(IpAddress.State.Free) || states.contains(IpAddress.State.Reserved)) {
|
||||||
if (isAllocated) {
|
if (isAllocated) {
|
||||||
throw new InvalidParameterValueException("Conflict: allocatedonly is true but state is Free");
|
throw new InvalidParameterValueException("Conflict: allocatedonly is true but state is Free");
|
||||||
}
|
}
|
||||||
} else if (state != null && state.equalsIgnoreCase(IpAddress.State.Allocated.name())) {
|
} else if (states.contains(IpAddress.State.Allocated)) {
|
||||||
isAllocated = Boolean.TRUE;
|
isAllocated = Boolean.TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2521,10 +2538,8 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
|
||||||
Boolean isRecursive = cmd.isRecursive();
|
Boolean isRecursive = cmd.isRecursive();
|
||||||
final List<Long> permittedAccounts = new ArrayList<>();
|
final List<Long> permittedAccounts = new ArrayList<>();
|
||||||
ListProjectResourcesCriteria listProjectResourcesCriteria = null;
|
ListProjectResourcesCriteria listProjectResourcesCriteria = null;
|
||||||
boolean isAllocatedOrReserved = false;
|
boolean isAllocatedOrReserved = isAllocated ||
|
||||||
if (isAllocated || IpAddress.State.Reserved.name().equalsIgnoreCase(state)) {
|
(states.size() == 1 && IpAddress.State.Reserved.equals(states.get(0)));
|
||||||
isAllocatedOrReserved = true;
|
|
||||||
}
|
|
||||||
if (isAllocatedOrReserved || (vlanType == VlanType.VirtualNetwork && (caller.getType() != Account.Type.ADMIN || cmd.getDomainId() != null))) {
|
if (isAllocatedOrReserved || (vlanType == VlanType.VirtualNetwork && (caller.getType() != Account.Type.ADMIN || cmd.getDomainId() != null))) {
|
||||||
final Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject = new Ternary<>(cmd.getDomainId(), cmd.isRecursive(),
|
final Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject = new Ternary<>(cmd.getDomainId(), cmd.isRecursive(),
|
||||||
null);
|
null);
|
||||||
|
|
@ -2538,7 +2553,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
|
||||||
buildParameters(sb, cmd, vlanType == VlanType.VirtualNetwork ? true : isAllocated);
|
buildParameters(sb, cmd, vlanType == VlanType.VirtualNetwork ? true : isAllocated);
|
||||||
|
|
||||||
SearchCriteria<IPAddressVO> sc = sb.create();
|
SearchCriteria<IPAddressVO> sc = sb.create();
|
||||||
setParameters(sc, cmd, vlanType, isAllocated);
|
setParameters(sc, cmd, vlanType, isAllocated, states);
|
||||||
|
|
||||||
if (isAllocatedOrReserved || (vlanType == VlanType.VirtualNetwork && (caller.getType() != Account.Type.ADMIN || cmd.getDomainId() != null))) {
|
if (isAllocatedOrReserved || (vlanType == VlanType.VirtualNetwork && (caller.getType() != Account.Type.ADMIN || cmd.getDomainId() != null))) {
|
||||||
_accountMgr.buildACLSearchCriteria(sc, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria);
|
_accountMgr.buildACLSearchCriteria(sc, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria);
|
||||||
|
|
@ -2606,7 +2621,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
|
||||||
buildParameters(searchBuilder, cmd, false);
|
buildParameters(searchBuilder, cmd, false);
|
||||||
|
|
||||||
SearchCriteria<IPAddressVO> searchCriteria = searchBuilder.create();
|
SearchCriteria<IPAddressVO> searchCriteria = searchBuilder.create();
|
||||||
setParameters(searchCriteria, cmd, vlanType, false);
|
setParameters(searchCriteria, cmd, vlanType, false, states);
|
||||||
searchCriteria.setParameters("state", IpAddress.State.Free.name());
|
searchCriteria.setParameters("state", IpAddress.State.Free.name());
|
||||||
addrs.addAll(_publicIpAddressDao.search(searchCriteria, searchFilter)); // Free IPs on shared network
|
addrs.addAll(_publicIpAddressDao.search(searchCriteria, searchFilter)); // Free IPs on shared network
|
||||||
}
|
}
|
||||||
|
|
@ -2619,7 +2634,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
|
||||||
sb2.and("quarantinedPublicIpsIdsNIN", sb2.entity().getId(), SearchCriteria.Op.NIN);
|
sb2.and("quarantinedPublicIpsIdsNIN", sb2.entity().getId(), SearchCriteria.Op.NIN);
|
||||||
|
|
||||||
SearchCriteria<IPAddressVO> sc2 = sb2.create();
|
SearchCriteria<IPAddressVO> sc2 = sb2.create();
|
||||||
setParameters(sc2, cmd, vlanType, isAllocated);
|
setParameters(sc2, cmd, vlanType, isAllocated, states);
|
||||||
sc2.setParameters("ids", freeAddrIds.toArray());
|
sc2.setParameters("ids", freeAddrIds.toArray());
|
||||||
_publicIpAddressDao.buildQuarantineSearchCriteria(sc2);
|
_publicIpAddressDao.buildQuarantineSearchCriteria(sc2);
|
||||||
addrs.addAll(_publicIpAddressDao.search(sc2, searchFilter)); // Allocated + Free
|
addrs.addAll(_publicIpAddressDao.search(sc2, searchFilter)); // Allocated + Free
|
||||||
|
|
@ -2649,7 +2664,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
|
||||||
sb.and("isSourceNat", sb.entity().isSourceNat(), SearchCriteria.Op.EQ);
|
sb.and("isSourceNat", sb.entity().isSourceNat(), SearchCriteria.Op.EQ);
|
||||||
sb.and("isStaticNat", sb.entity().isOneToOneNat(), SearchCriteria.Op.EQ);
|
sb.and("isStaticNat", sb.entity().isOneToOneNat(), SearchCriteria.Op.EQ);
|
||||||
sb.and("vpcId", sb.entity().getVpcId(), SearchCriteria.Op.EQ);
|
sb.and("vpcId", sb.entity().getVpcId(), SearchCriteria.Op.EQ);
|
||||||
sb.and("state", sb.entity().getState(), SearchCriteria.Op.EQ);
|
sb.and("state", sb.entity().getState(), SearchCriteria.Op.IN);
|
||||||
sb.and("display", sb.entity().isDisplay(), SearchCriteria.Op.EQ);
|
sb.and("display", sb.entity().isDisplay(), SearchCriteria.Op.EQ);
|
||||||
sb.and(FOR_SYSTEMVMS, sb.entity().isForSystemVms(), SearchCriteria.Op.EQ);
|
sb.and(FOR_SYSTEMVMS, sb.entity().isForSystemVms(), SearchCriteria.Op.EQ);
|
||||||
|
|
||||||
|
|
@ -2692,7 +2707,8 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setParameters(SearchCriteria<IPAddressVO> sc, final ListPublicIpAddressesCmd cmd, VlanType vlanType, Boolean isAllocated) {
|
protected void setParameters(SearchCriteria<IPAddressVO> sc, final ListPublicIpAddressesCmd cmd, VlanType vlanType,
|
||||||
|
Boolean isAllocated, List<IpAddress.State> states) {
|
||||||
final Object keyword = cmd.getKeyword();
|
final Object keyword = cmd.getKeyword();
|
||||||
final Long physicalNetworkId = cmd.getPhysicalNetworkId();
|
final Long physicalNetworkId = cmd.getPhysicalNetworkId();
|
||||||
final Long sourceNetworkId = cmd.getNetworkId();
|
final Long sourceNetworkId = cmd.getNetworkId();
|
||||||
|
|
@ -2703,7 +2719,6 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
|
||||||
final Boolean sourceNat = cmd.isSourceNat();
|
final Boolean sourceNat = cmd.isSourceNat();
|
||||||
final Boolean staticNat = cmd.isStaticNat();
|
final Boolean staticNat = cmd.isStaticNat();
|
||||||
final Boolean forDisplay = cmd.getDisplay();
|
final Boolean forDisplay = cmd.getDisplay();
|
||||||
final String state = cmd.getState();
|
|
||||||
final Boolean forSystemVms = cmd.getForSystemVMs();
|
final Boolean forSystemVms = cmd.getForSystemVMs();
|
||||||
final boolean forProvider = cmd.isForProvider();
|
final boolean forProvider = cmd.isForProvider();
|
||||||
final Map<String, String> tags = cmd.getTags();
|
final Map<String, String> tags = cmd.getTags();
|
||||||
|
|
@ -2760,13 +2775,14 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
|
||||||
sc.setParameters("display", forDisplay);
|
sc.setParameters("display", forDisplay);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state != null) {
|
if (CollectionUtils.isNotEmpty(states)) {
|
||||||
sc.setParameters("state", state);
|
sc.setParameters("state", states.toArray());
|
||||||
} else if (isAllocated != null && isAllocated) {
|
} else if (isAllocated != null && isAllocated) {
|
||||||
sc.setParameters("state", IpAddress.State.Allocated);
|
sc.setParameters("state", IpAddress.State.Allocated);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IpAddressManagerImpl.getSystemvmpublicipreservationmodestrictness().value() && IpAddress.State.Free.name().equalsIgnoreCase(state)) {
|
if (IpAddressManagerImpl.getSystemvmpublicipreservationmodestrictness().value() &&
|
||||||
|
states.contains(IpAddress.State.Free)) {
|
||||||
sc.setParameters(FOR_SYSTEMVMS, false);
|
sc.setParameters(FOR_SYSTEMVMS, false);
|
||||||
} else {
|
} else {
|
||||||
sc.setParameters(FOR_SYSTEMVMS, forSystemVms);
|
sc.setParameters(FOR_SYSTEMVMS, forSystemVms);
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ import static org.mockito.Mockito.when;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.cloudstack.annotation.dao.AnnotationDao;
|
import org.apache.cloudstack.annotation.dao.AnnotationDao;
|
||||||
|
|
@ -258,14 +259,14 @@ public class ManagementServerImplTest {
|
||||||
Mockito.when(cmd.getId()).thenReturn(null);
|
Mockito.when(cmd.getId()).thenReturn(null);
|
||||||
Mockito.when(cmd.isSourceNat()).thenReturn(null);
|
Mockito.when(cmd.isSourceNat()).thenReturn(null);
|
||||||
Mockito.when(cmd.isStaticNat()).thenReturn(null);
|
Mockito.when(cmd.isStaticNat()).thenReturn(null);
|
||||||
Mockito.when(cmd.getState()).thenReturn(IpAddress.State.Free.name());
|
|
||||||
Mockito.when(cmd.getTags()).thenReturn(null);
|
Mockito.when(cmd.getTags()).thenReturn(null);
|
||||||
spy.setParameters(sc, cmd, VlanType.VirtualNetwork, Boolean.FALSE);
|
List<IpAddress.State> states = Collections.singletonList(IpAddress.State.Free);
|
||||||
|
spy.setParameters(sc, cmd, VlanType.VirtualNetwork, Boolean.FALSE, states);
|
||||||
|
|
||||||
Mockito.verify(sc, Mockito.times(1)).setJoinParameters("vlanSearch", "vlanType", VlanType.VirtualNetwork);
|
Mockito.verify(sc, Mockito.times(1)).setJoinParameters("vlanSearch", "vlanType", VlanType.VirtualNetwork);
|
||||||
Mockito.verify(sc, Mockito.times(1)).setParameters("display", false);
|
Mockito.verify(sc, Mockito.times(1)).setParameters("display", false);
|
||||||
Mockito.verify(sc, Mockito.times(1)).setParameters("sourceNetworkId", 10L);
|
Mockito.verify(sc, Mockito.times(1)).setParameters("sourceNetworkId", 10L);
|
||||||
Mockito.verify(sc, Mockito.times(1)).setParameters("state", "Free");
|
Mockito.verify(sc, Mockito.times(1)).setParameters("state", states.toArray());
|
||||||
Mockito.verify(sc, Mockito.times(1)).setParameters("forsystemvms", false);
|
Mockito.verify(sc, Mockito.times(1)).setParameters("forsystemvms", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -281,14 +282,14 @@ public class ManagementServerImplTest {
|
||||||
Mockito.when(cmd.getId()).thenReturn(null);
|
Mockito.when(cmd.getId()).thenReturn(null);
|
||||||
Mockito.when(cmd.isSourceNat()).thenReturn(null);
|
Mockito.when(cmd.isSourceNat()).thenReturn(null);
|
||||||
Mockito.when(cmd.isStaticNat()).thenReturn(null);
|
Mockito.when(cmd.isStaticNat()).thenReturn(null);
|
||||||
Mockito.when(cmd.getState()).thenReturn(IpAddress.State.Free.name());
|
|
||||||
Mockito.when(cmd.getTags()).thenReturn(null);
|
Mockito.when(cmd.getTags()).thenReturn(null);
|
||||||
spy.setParameters(sc, cmd, VlanType.VirtualNetwork, Boolean.FALSE);
|
List<IpAddress.State> states = Collections.singletonList(IpAddress.State.Free);
|
||||||
|
spy.setParameters(sc, cmd, VlanType.VirtualNetwork, Boolean.FALSE, states);
|
||||||
|
|
||||||
Mockito.verify(sc, Mockito.times(1)).setJoinParameters("vlanSearch", "vlanType", VlanType.VirtualNetwork);
|
Mockito.verify(sc, Mockito.times(1)).setJoinParameters("vlanSearch", "vlanType", VlanType.VirtualNetwork);
|
||||||
Mockito.verify(sc, Mockito.times(1)).setParameters("display", false);
|
Mockito.verify(sc, Mockito.times(1)).setParameters("display", false);
|
||||||
Mockito.verify(sc, Mockito.times(1)).setParameters("sourceNetworkId", 10L);
|
Mockito.verify(sc, Mockito.times(1)).setParameters("sourceNetworkId", 10L);
|
||||||
Mockito.verify(sc, Mockito.times(1)).setParameters("state", "Free");
|
Mockito.verify(sc, Mockito.times(1)).setParameters("state", states.toArray());
|
||||||
Mockito.verify(sc, Mockito.times(1)).setParameters("forsystemvms", false);
|
Mockito.verify(sc, Mockito.times(1)).setParameters("forsystemvms", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -304,13 +305,13 @@ public class ManagementServerImplTest {
|
||||||
Mockito.when(cmd.getId()).thenReturn(null);
|
Mockito.when(cmd.getId()).thenReturn(null);
|
||||||
Mockito.when(cmd.isSourceNat()).thenReturn(null);
|
Mockito.when(cmd.isSourceNat()).thenReturn(null);
|
||||||
Mockito.when(cmd.isStaticNat()).thenReturn(null);
|
Mockito.when(cmd.isStaticNat()).thenReturn(null);
|
||||||
Mockito.when(cmd.getState()).thenReturn(null);
|
|
||||||
Mockito.when(cmd.getTags()).thenReturn(null);
|
Mockito.when(cmd.getTags()).thenReturn(null);
|
||||||
spy.setParameters(sc, cmd, VlanType.VirtualNetwork, Boolean.TRUE);
|
spy.setParameters(sc, cmd, VlanType.VirtualNetwork, Boolean.TRUE, Collections.emptyList());
|
||||||
|
|
||||||
Mockito.verify(sc, Mockito.times(1)).setJoinParameters("vlanSearch", "vlanType", VlanType.VirtualNetwork);
|
Mockito.verify(sc, Mockito.times(1)).setJoinParameters("vlanSearch", "vlanType", VlanType.VirtualNetwork);
|
||||||
Mockito.verify(sc, Mockito.times(1)).setParameters("display", false);
|
Mockito.verify(sc, Mockito.times(1)).setParameters("display", false);
|
||||||
Mockito.verify(sc, Mockito.times(1)).setParameters("sourceNetworkId", 10L);
|
Mockito.verify(sc, Mockito.times(1)).setParameters("sourceNetworkId", 10L);
|
||||||
|
Mockito.verify(sc, Mockito.times(1)).setParameters("state", IpAddress.State.Allocated);
|
||||||
Mockito.verify(sc, Mockito.times(1)).setParameters("forsystemvms", false);
|
Mockito.verify(sc, Mockito.times(1)).setParameters("forsystemvms", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -326,13 +327,13 @@ public class ManagementServerImplTest {
|
||||||
Mockito.when(cmd.getId()).thenReturn(null);
|
Mockito.when(cmd.getId()).thenReturn(null);
|
||||||
Mockito.when(cmd.isSourceNat()).thenReturn(null);
|
Mockito.when(cmd.isSourceNat()).thenReturn(null);
|
||||||
Mockito.when(cmd.isStaticNat()).thenReturn(null);
|
Mockito.when(cmd.isStaticNat()).thenReturn(null);
|
||||||
Mockito.when(cmd.getState()).thenReturn(null);
|
|
||||||
Mockito.when(cmd.getTags()).thenReturn(null);
|
Mockito.when(cmd.getTags()).thenReturn(null);
|
||||||
spy.setParameters(sc, cmd, VlanType.VirtualNetwork, Boolean.TRUE);
|
spy.setParameters(sc, cmd, VlanType.VirtualNetwork, Boolean.TRUE, Collections.emptyList());
|
||||||
|
|
||||||
Mockito.verify(sc, Mockito.times(1)).setJoinParameters("vlanSearch", "vlanType", VlanType.VirtualNetwork);
|
Mockito.verify(sc, Mockito.times(1)).setJoinParameters("vlanSearch", "vlanType", VlanType.VirtualNetwork);
|
||||||
Mockito.verify(sc, Mockito.times(1)).setParameters("display", false);
|
Mockito.verify(sc, Mockito.times(1)).setParameters("display", false);
|
||||||
Mockito.verify(sc, Mockito.times(1)).setParameters("sourceNetworkId", 10L);
|
Mockito.verify(sc, Mockito.times(1)).setParameters("sourceNetworkId", 10L);
|
||||||
|
Mockito.verify(sc, Mockito.times(1)).setParameters("state", IpAddress.State.Allocated);
|
||||||
Mockito.verify(sc, Mockito.times(1)).setParameters("forsystemvms", false);
|
Mockito.verify(sc, Mockito.times(1)).setParameters("forsystemvms", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1033,4 +1034,49 @@ public class ManagementServerImplTest {
|
||||||
Assert.assertNotNull(spy.getExternalVmConsole(virtualMachine, host));
|
Assert.assertNotNull(spy.getExternalVmConsole(virtualMachine, host));
|
||||||
Mockito.verify(extensionManager).getInstanceConsole(virtualMachine, host);
|
Mockito.verify(extensionManager).getInstanceConsole(virtualMachine, host);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getStatesForIpAddressSearchReturnsValidStates() {
|
||||||
|
ListPublicIpAddressesCmd cmd = Mockito.mock(ListPublicIpAddressesCmd.class);
|
||||||
|
Mockito.when(cmd.getState()).thenReturn("Allocated ,free");
|
||||||
|
List<IpAddress.State> result = spy.getStatesForIpAddressSearch(cmd);
|
||||||
|
Assert.assertEquals(2, result.size());
|
||||||
|
Assert.assertTrue(result.contains(IpAddress.State.Allocated));
|
||||||
|
Assert.assertTrue(result.contains(IpAddress.State.Free));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getStatesForIpAddressSearchReturnsEmptyListForNullState() {
|
||||||
|
ListPublicIpAddressesCmd cmd = Mockito.mock(ListPublicIpAddressesCmd.class);
|
||||||
|
Mockito.when(cmd.getState()).thenReturn(null);
|
||||||
|
List<IpAddress.State> result = spy.getStatesForIpAddressSearch(cmd);
|
||||||
|
Assert.assertTrue(result.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getStatesForIpAddressSearchReturnsEmptyListForBlankState() {
|
||||||
|
ListPublicIpAddressesCmd cmd = Mockito.mock(ListPublicIpAddressesCmd.class);
|
||||||
|
Mockito.when(cmd.getState()).thenReturn(" ");
|
||||||
|
List<IpAddress.State> result = spy.getStatesForIpAddressSearch(cmd);
|
||||||
|
Assert.assertTrue(result.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = InvalidParameterValueException.class)
|
||||||
|
public void getStatesForIpAddressSearchThrowsExceptionForInvalidState() {
|
||||||
|
ListPublicIpAddressesCmd cmd = Mockito.mock(ListPublicIpAddressesCmd.class);
|
||||||
|
Mockito.when(cmd.getState()).thenReturn("InvalidState");
|
||||||
|
spy.getStatesForIpAddressSearch(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getStatesForIpAddressSearchHandlesMixedValidAndInvalidStates() {
|
||||||
|
ListPublicIpAddressesCmd cmd = Mockito.mock(ListPublicIpAddressesCmd.class);
|
||||||
|
Mockito.when(cmd.getState()).thenReturn("Allocated,InvalidState");
|
||||||
|
try {
|
||||||
|
spy.getStatesForIpAddressSearch(cmd);
|
||||||
|
Assert.fail("Expected InvalidParameterValueException to be thrown");
|
||||||
|
} catch (InvalidParameterValueException e) {
|
||||||
|
Assert.assertEquals("Invalid state: InvalidState", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,7 @@
|
||||||
- defaultOption (Object, optional): Preselected object to include initially
|
- defaultOption (Object, optional): Preselected object to include initially
|
||||||
- showIcon (Boolean, optional): Whether to show icon for the options. Default is true
|
- showIcon (Boolean, optional): Whether to show icon for the options. Default is true
|
||||||
- defaultIcon (String, optional): Icon to be shown when there is no resource icon for the option. Default is 'cloud-outlined'
|
- defaultIcon (String, optional): Icon to be shown when there is no resource icon for the option. Default is 'cloud-outlined'
|
||||||
|
- autoSelectFirstOption (Boolean, optional): Whether to automatically select the first option when options are loaded. Default is false
|
||||||
|
|
||||||
Events:
|
Events:
|
||||||
- @change-option-value (Function): Emits the selected option value(s) when value(s) changes. Do not use @change as it will give warnings and may not work
|
- @change-option-value (Function): Emits the selected option value(s) when value(s) changes. Do not use @change as it will give warnings and may not work
|
||||||
|
|
@ -81,7 +82,7 @@
|
||||||
<resource-icon v-if="option.icon && option.icon.base64image" :image="option.icon.base64image" size="1x" style="margin-right: 5px"/>
|
<resource-icon v-if="option.icon && option.icon.base64image" :image="option.icon.base64image" size="1x" style="margin-right: 5px"/>
|
||||||
<render-icon v-else :icon="defaultIcon" style="margin-right: 5px" />
|
<render-icon v-else :icon="defaultIcon" style="margin-right: 5px" />
|
||||||
</span>
|
</span>
|
||||||
<span>{{ option[optionLabelKey] }}</span>
|
<span>{{ optionLabelFn ? optionLabelFn(option) : option[optionLabelKey] }}</span>
|
||||||
</span>
|
</span>
|
||||||
</a-select-option>
|
</a-select-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
|
|
@ -120,6 +121,10 @@ export default {
|
||||||
type: String,
|
type: String,
|
||||||
default: 'name'
|
default: 'name'
|
||||||
},
|
},
|
||||||
|
optionLabelFn: {
|
||||||
|
type: Function,
|
||||||
|
default: null
|
||||||
|
},
|
||||||
defaultOption: {
|
defaultOption: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: null
|
default: null
|
||||||
|
|
@ -135,6 +140,10 @@ export default {
|
||||||
pageSize: {
|
pageSize: {
|
||||||
type: Number,
|
type: Number,
|
||||||
default: null
|
default: null
|
||||||
|
},
|
||||||
|
autoSelectFirstOption: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data () {
|
data () {
|
||||||
|
|
@ -147,11 +156,12 @@ export default {
|
||||||
searchTimer: null,
|
searchTimer: null,
|
||||||
scrollHandlerAttached: false,
|
scrollHandlerAttached: false,
|
||||||
preselectedOptionValue: null,
|
preselectedOptionValue: null,
|
||||||
successiveFetches: 0
|
successiveFetches: 0,
|
||||||
|
canSelectFirstOption: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created () {
|
created () {
|
||||||
this.addDefaultOptionIfNeeded(true)
|
this.addDefaultOptionIfNeeded()
|
||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
this.preselectedOptionValue = this.$attrs.value
|
this.preselectedOptionValue = this.$attrs.value
|
||||||
|
|
@ -208,6 +218,7 @@ export default {
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
this.$notifyError(error)
|
this.$notifyError(error)
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
|
this.canSelectFirstOption = true
|
||||||
if (this.successiveFetches === 0) {
|
if (this.successiveFetches === 0) {
|
||||||
this.loading = false
|
this.loading = false
|
||||||
}
|
}
|
||||||
|
|
@ -218,6 +229,12 @@ export default {
|
||||||
(Array.isArray(this.preselectedOptionValue) && this.preselectedOptionValue.length === 0) ||
|
(Array.isArray(this.preselectedOptionValue) && this.preselectedOptionValue.length === 0) ||
|
||||||
this.successiveFetches >= this.maxSuccessiveFetches) {
|
this.successiveFetches >= this.maxSuccessiveFetches) {
|
||||||
this.resetPreselectedOptionValue()
|
this.resetPreselectedOptionValue()
|
||||||
|
if (!this.canSelectFirstOption && this.autoSelectFirstOption && this.options.length > 0) {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.preselectedOptionValue = this.options[0][this.optionValueKey]
|
||||||
|
this.onChange(this.preselectedOptionValue)
|
||||||
|
})
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const matchValue = Array.isArray(this.preselectedOptionValue) ? this.preselectedOptionValue[0] : this.preselectedOptionValue
|
const matchValue = Array.isArray(this.preselectedOptionValue) ? this.preselectedOptionValue[0] : this.preselectedOptionValue
|
||||||
|
|
@ -239,6 +256,7 @@ export default {
|
||||||
},
|
},
|
||||||
addDefaultOptionIfNeeded () {
|
addDefaultOptionIfNeeded () {
|
||||||
if (this.defaultOption) {
|
if (this.defaultOption) {
|
||||||
|
this.canSelectFirstOption = true
|
||||||
this.options.push(this.defaultOption)
|
this.options.push(this.defaultOption)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -148,20 +148,17 @@
|
||||||
<a-alert :message="$t('message.action.acquire.ip')" type="warning" />
|
<a-alert :message="$t('message.action.acquire.ip')" type="warning" />
|
||||||
<a-form layout="vertical" style="margin-top: 10px">
|
<a-form layout="vertical" style="margin-top: 10px">
|
||||||
<a-form-item :label="$t('label.ipaddress')">
|
<a-form-item :label="$t('label.ipaddress')">
|
||||||
<a-select
|
<infinite-scroll-select
|
||||||
v-focus="true"
|
v-focus="true"
|
||||||
style="width: 100%;"
|
|
||||||
v-model:value="acquireIp"
|
v-model:value="acquireIp"
|
||||||
showSearch
|
api="listPublicIpAddresses"
|
||||||
optionFilterProp="label"
|
:apiParams="listApiParamsForAssociate"
|
||||||
:filterOption="(input, option) => {
|
resourceType="publicipaddress"
|
||||||
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
|
optionValueKey="ipaddress"
|
||||||
}" >
|
:optionLabelFn="ip => ip.ipaddress + ' (' + ip.state + ')'"
|
||||||
<a-select-option
|
defaultIcon="environment-outlined"
|
||||||
v-for="ip in listPublicIpAddress"
|
:autoSelectFirstOption="true"
|
||||||
:key="ip.ipaddress"
|
@change-option-value="(ip) => acquireIp = ip" />
|
||||||
:label="ip.ipaddress + '(' + ip.state + ')'">{{ ip.ipaddress }} ({{ ip.state }})</a-select-option>
|
|
||||||
</a-select>
|
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<div :span="24" class="action-button">
|
<div :span="24" class="action-button">
|
||||||
<a-button @click="onCloseModal">{{ $t('label.cancel') }}</a-button>
|
<a-button @click="onCloseModal">{{ $t('label.cancel') }}</a-button>
|
||||||
|
|
@ -212,13 +209,15 @@ import Status from '@/components/widgets/Status'
|
||||||
import TooltipButton from '@/components/widgets/TooltipButton'
|
import TooltipButton from '@/components/widgets/TooltipButton'
|
||||||
import BulkActionView from '@/components/view/BulkActionView'
|
import BulkActionView from '@/components/view/BulkActionView'
|
||||||
import eventBus from '@/config/eventBus'
|
import eventBus from '@/config/eventBus'
|
||||||
|
import InfiniteScrollSelect from '@/components/widgets/InfiniteScrollSelect'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'IpAddressesTab',
|
name: 'IpAddressesTab',
|
||||||
components: {
|
components: {
|
||||||
Status,
|
Status,
|
||||||
TooltipButton,
|
TooltipButton,
|
||||||
BulkActionView
|
BulkActionView,
|
||||||
|
InfiniteScrollSelect
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
resource: {
|
resource: {
|
||||||
|
|
@ -281,7 +280,6 @@ export default {
|
||||||
showAcquireIp: false,
|
showAcquireIp: false,
|
||||||
acquireLoading: false,
|
acquireLoading: false,
|
||||||
acquireIp: null,
|
acquireIp: null,
|
||||||
listPublicIpAddress: [],
|
|
||||||
changeSourceNat: false,
|
changeSourceNat: false,
|
||||||
zoneExtNetProvider: ''
|
zoneExtNetProvider: ''
|
||||||
}
|
}
|
||||||
|
|
@ -302,6 +300,26 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
inject: ['parentFetchData'],
|
inject: ['parentFetchData'],
|
||||||
|
computed: {
|
||||||
|
listApiParams () {
|
||||||
|
const params = {
|
||||||
|
zoneid: this.resource.zoneid,
|
||||||
|
domainid: this.resource.domainid,
|
||||||
|
account: this.resource.account,
|
||||||
|
forvirtualnetwork: true,
|
||||||
|
allocatedonly: false
|
||||||
|
}
|
||||||
|
if (['nsx', 'netris'].includes(this.zoneExtNetProvider?.toLowerCase())) {
|
||||||
|
params.forprovider = true
|
||||||
|
}
|
||||||
|
return params
|
||||||
|
},
|
||||||
|
listApiParamsForAssociate () {
|
||||||
|
const params = this.listApiParams
|
||||||
|
params.state = 'Free,Reserved'
|
||||||
|
return params
|
||||||
|
}
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
fetchData () {
|
fetchData () {
|
||||||
const params = {
|
const params = {
|
||||||
|
|
@ -344,19 +362,9 @@ export default {
|
||||||
}).catch(reject)
|
}).catch(reject)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
fetchListPublicIpAddress () {
|
fetchListPublicIpAddress (state) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const params = {
|
getAPI('listPublicIpAddresses', this.listApiParams).then(json => {
|
||||||
zoneid: this.resource.zoneid,
|
|
||||||
domainid: this.resource.domainid,
|
|
||||||
account: this.resource.account,
|
|
||||||
forvirtualnetwork: true,
|
|
||||||
allocatedonly: false
|
|
||||||
}
|
|
||||||
if (['nsx', 'netris'].includes(this.zoneExtNetProvider?.toLowerCase())) {
|
|
||||||
params.forprovider = true
|
|
||||||
}
|
|
||||||
getAPI('listPublicIpAddresses', params).then(json => {
|
|
||||||
const listPublicIps = json.listpublicipaddressesresponse.publicipaddress || []
|
const listPublicIps = json.listpublicipaddressesresponse.publicipaddress || []
|
||||||
resolve(listPublicIps)
|
resolve(listPublicIps)
|
||||||
}).catch(reject)
|
}).catch(reject)
|
||||||
|
|
@ -554,30 +562,6 @@ export default {
|
||||||
},
|
},
|
||||||
async onShowAcquireIp () {
|
async onShowAcquireIp () {
|
||||||
this.showAcquireIp = true
|
this.showAcquireIp = true
|
||||||
this.acquireLoading = true
|
|
||||||
this.listPublicIpAddress = []
|
|
||||||
|
|
||||||
try {
|
|
||||||
const listPublicIpAddress = await this.fetchListPublicIpAddress()
|
|
||||||
listPublicIpAddress.forEach(item => {
|
|
||||||
if (item.state === 'Free' || item.state === 'Reserved') {
|
|
||||||
this.listPublicIpAddress.push({
|
|
||||||
ipaddress: item.ipaddress,
|
|
||||||
state: item.state
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
this.listPublicIpAddress.sort(function (a, b) {
|
|
||||||
if (a.ipaddress < b.ipaddress) { return -1 }
|
|
||||||
if (a.ipaddress > b.ipaddress) { return 1 }
|
|
||||||
return 0
|
|
||||||
})
|
|
||||||
this.acquireIp = this.listPublicIpAddress && this.listPublicIpAddress.length > 0 ? this.listPublicIpAddress[0].ipaddress : null
|
|
||||||
this.acquireLoading = false
|
|
||||||
} catch (e) {
|
|
||||||
this.acquireLoading = false
|
|
||||||
this.$notifyError(e)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
onCloseModal () {
|
onCloseModal () {
|
||||||
this.showAcquireIp = false
|
this.showAcquireIp = false
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
package com.cloud.utils;
|
package com.cloud.utils;
|
||||||
|
|
||||||
public class EnumUtils {
|
public class EnumUtils extends org.apache.commons.lang3.EnumUtils {
|
||||||
public static String listValues(Enum<?>[] enums) {
|
public static String listValues(Enum<?>[] enums) {
|
||||||
StringBuilder b = new StringBuilder("[");
|
StringBuilder b = new StringBuilder("[");
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue