mirror of
https://github.com/apache/cloudstack.git
synced 2025-11-02 20:02:29 +01:00
CLOUDSTACK-5810: addSecondaryIp to vm's nic - derive the ip owner from the vm instance account, not from the caller
This commit is contained in:
parent
647ea6e2d0
commit
b15431e574
@ -168,7 +168,7 @@ public interface NetworkService {
|
||||
InsufficientCapacityException;
|
||||
|
||||
/* Requests an IP address for the guest nic */
|
||||
NicSecondaryIp allocateSecondaryGuestIP(Account account, long zoneId, Long nicId, Long networkId, String ipaddress) throws InsufficientAddressCapacityException;
|
||||
NicSecondaryIp allocateSecondaryGuestIP(long nicId, String ipaddress) throws InsufficientAddressCapacityException;
|
||||
|
||||
boolean releaseSecondaryIpFromNic(long ipAddressId);
|
||||
|
||||
|
||||
@ -47,5 +47,5 @@ public interface SecurityGroupService {
|
||||
|
||||
public List<? extends SecurityRule> authorizeSecurityGroupEgress(AuthorizeSecurityGroupEgressCmd cmd);
|
||||
|
||||
public boolean securityGroupRulesForVmSecIp(Long nicId, Long networkId, String secondaryIp, boolean ruleAction);
|
||||
public boolean securityGroupRulesForVmSecIp(long nicId, String secondaryIp, boolean ruleAction);
|
||||
}
|
||||
|
||||
@ -16,8 +16,6 @@
|
||||
// under the License.
|
||||
package org.apache.cloudstack.api.command.user.vm;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.ApiCommandJobType;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
@ -28,6 +26,7 @@ import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.apache.cloudstack.api.response.NicResponse;
|
||||
import org.apache.cloudstack.api.response.NicSecondaryIpResponse;
|
||||
import org.apache.cloudstack.context.CallContext;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.dc.DataCenter;
|
||||
import com.cloud.dc.DataCenter.NetworkType;
|
||||
@ -39,10 +38,10 @@ import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.exception.ResourceAllocationException;
|
||||
import com.cloud.exception.ResourceUnavailableException;
|
||||
import com.cloud.network.Network;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.utils.net.NetUtils;
|
||||
import com.cloud.vm.Nic;
|
||||
import com.cloud.vm.NicSecondaryIp;
|
||||
import com.cloud.vm.VirtualMachine;
|
||||
|
||||
@APICommand(name = "addIpToNic", description = "Assigns secondary IP to NIC", responseObject = NicSecondaryIpResponse.class)
|
||||
public class AddIpToVmNicCmd extends BaseAsyncCmd {
|
||||
@ -52,11 +51,7 @@ public class AddIpToVmNicCmd extends BaseAsyncCmd {
|
||||
/////////////////////////////////////////////////////
|
||||
//////////////// API parameters /////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
@Parameter(name = ApiConstants.NIC_ID,
|
||||
type = CommandType.UUID,
|
||||
entityType = NicResponse.class,
|
||||
required = true,
|
||||
description = "the ID of the nic to which you want to assign private IP")
|
||||
@Parameter(name = ApiConstants.NIC_ID, type = CommandType.UUID, entityType = NicResponse.class, required = true, description = "the ID of the nic to which you want to assign private IP")
|
||||
private Long nicId;
|
||||
|
||||
@Parameter(name = ApiConstants.IP_ADDRESS, type = CommandType.STRING, required = false, description = "Secondary IP Address")
|
||||
@ -70,36 +65,19 @@ public class AddIpToVmNicCmd extends BaseAsyncCmd {
|
||||
return "nic_secondary_ips";
|
||||
}
|
||||
|
||||
public String getAccountName() {
|
||||
return CallContext.current().getCallingAccount().getAccountName();
|
||||
}
|
||||
|
||||
public long getDomainId() {
|
||||
return CallContext.current().getCallingAccount().getDomainId();
|
||||
}
|
||||
|
||||
private long getZoneId() {
|
||||
Network ntwk = _entityMgr.findById(Network.class, getNetworkId());
|
||||
if (ntwk == null) {
|
||||
throw new InvalidParameterValueException("Can't find zone id for specified");
|
||||
}
|
||||
return ntwk.getDataCenterId();
|
||||
}
|
||||
|
||||
public Long getNetworkId() {
|
||||
private long getNetworkId() {
|
||||
Nic nic = _entityMgr.findById(Nic.class, nicId);
|
||||
if (nic == null) {
|
||||
throw new InvalidParameterValueException("Can't find network id for specified nic");
|
||||
}
|
||||
Long networkId = nic.getNetworkId();
|
||||
return networkId;
|
||||
return nic.getNetworkId();
|
||||
}
|
||||
|
||||
public Long getNicId() {
|
||||
public long getNicId() {
|
||||
return nicId;
|
||||
}
|
||||
|
||||
public String getIpaddress() {
|
||||
private String getIpaddress() {
|
||||
if (ipAddr != null) {
|
||||
return ipAddr;
|
||||
} else {
|
||||
@ -107,18 +85,12 @@ public class AddIpToVmNicCmd extends BaseAsyncCmd {
|
||||
}
|
||||
}
|
||||
|
||||
public NetworkType getNetworkType() {
|
||||
private NetworkType getNetworkType() {
|
||||
Network ntwk = _entityMgr.findById(Network.class, getNetworkId());
|
||||
DataCenter dc = _entityMgr.findById(DataCenter.class, ntwk.getDataCenterId());
|
||||
return dc.getNetworkType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getEntityOwnerId() {
|
||||
Account caller = CallContext.current().getCallingAccount();
|
||||
return caller.getAccountId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType() {
|
||||
return EventTypes.EVENT_NET_IP_ASSIGN;
|
||||
@ -126,7 +98,7 @@ public class AddIpToVmNicCmd extends BaseAsyncCmd {
|
||||
|
||||
@Override
|
||||
public String getEventDescription() {
|
||||
return "associating ip to nic id: " + getNetworkId() + " in zone " + getZoneId();
|
||||
return "associating ip to nic id=" + getNicId() + " belonging to network id=" + getNetworkId();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
@ -156,7 +128,7 @@ public class AddIpToVmNicCmd extends BaseAsyncCmd {
|
||||
}
|
||||
|
||||
try {
|
||||
result = _networkService.allocateSecondaryGuestIP(_accountService.getAccount(getEntityOwnerId()), getZoneId(), getNicId(), getNetworkId(), getIpaddress());
|
||||
result = _networkService.allocateSecondaryGuestIP(getNicId(), getIpaddress());
|
||||
} catch (InsufficientAddressCapacityException e) {
|
||||
throw new InvalidParameterValueException("Allocating guest ip for nic failed");
|
||||
}
|
||||
@ -166,7 +138,7 @@ public class AddIpToVmNicCmd extends BaseAsyncCmd {
|
||||
if (getNetworkType() == NetworkType.Basic) {
|
||||
// add security group rules for the secondary ip addresses
|
||||
boolean success = false;
|
||||
success = _securityGroupService.securityGroupRulesForVmSecIp(getNicId(), getNetworkId(), secondaryIp, true);
|
||||
success = _securityGroupService.securityGroupRulesForVmSecIp(getNicId(), secondaryIp, true);
|
||||
if (success == false) {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to set security group rules for the secondary ip");
|
||||
}
|
||||
@ -197,4 +169,16 @@ public class AddIpToVmNicCmd extends BaseAsyncCmd {
|
||||
return ApiCommandJobType.IpAddress;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getEntityOwnerId() {
|
||||
Nic nic = _entityMgr.findById(Nic.class, nicId);
|
||||
if (nic == null) {
|
||||
throw new InvalidParameterValueException("Can't find nic for id specified");
|
||||
}
|
||||
long vmId = nic.getInstanceId();
|
||||
VirtualMachine vm = _entityMgr.findById(VirtualMachine.class, vmId);
|
||||
|
||||
return vm.getAccountId();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -142,7 +142,7 @@ public class RemoveIpFromVmNicCmd extends BaseAsyncCmd {
|
||||
if (getNetworkType() == NetworkType.Basic) {
|
||||
//remove the security group rules for this secondary ip
|
||||
boolean success = false;
|
||||
success = _securityGroupService.securityGroupRulesForVmSecIp(nicSecIp.getNicId(), nicSecIp.getNetworkId(), nicSecIp.getIp4Address(), false);
|
||||
success = _securityGroupService.securityGroupRulesForVmSecIp(nicSecIp.getNicId(), nicSecIp.getIp4Address(), false);
|
||||
if (success == false) {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to set security group rules for the secondary ip");
|
||||
}
|
||||
|
||||
@ -25,7 +25,6 @@ import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.mockito.Matchers;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import org.apache.cloudstack.api.ResponseGenerator;
|
||||
import org.apache.cloudstack.api.command.user.vm.AddIpToVmNicCmd;
|
||||
import org.apache.cloudstack.api.command.user.vm.RemoveIpFromVmNicCmd;
|
||||
@ -39,7 +38,6 @@ import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.exception.ResourceAllocationException;
|
||||
import com.cloud.exception.ResourceUnavailableException;
|
||||
import com.cloud.network.NetworkService;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.vm.NicSecondaryIp;
|
||||
|
||||
public class AddIpToVmNicTest extends TestCase {
|
||||
@ -68,7 +66,7 @@ public class AddIpToVmNicTest extends TestCase {
|
||||
NicSecondaryIp secIp = Mockito.mock(NicSecondaryIp.class);
|
||||
|
||||
Mockito.when(
|
||||
networkService.allocateSecondaryGuestIP(Matchers.any(Account.class), Matchers.anyLong(), Matchers.anyLong(), Matchers.anyLong(), Matchers.anyString()))
|
||||
networkService.allocateSecondaryGuestIP(Matchers.anyLong(), Matchers.anyString()))
|
||||
.thenReturn(secIp);
|
||||
|
||||
ipTonicCmd._networkService = networkService;
|
||||
@ -88,7 +86,7 @@ public class AddIpToVmNicTest extends TestCase {
|
||||
AddIpToVmNicCmd ipTonicCmd = Mockito.mock(AddIpToVmNicCmd.class);
|
||||
|
||||
Mockito.when(
|
||||
networkService.allocateSecondaryGuestIP(Matchers.any(Account.class), Matchers.anyLong(), Matchers.anyLong(), Matchers.anyLong(), Matchers.anyString()))
|
||||
networkService.allocateSecondaryGuestIP(Matchers.anyLong(), Matchers.anyString()))
|
||||
.thenReturn(null);
|
||||
|
||||
ipTonicCmd._networkService = networkService;
|
||||
|
||||
@ -21,7 +21,6 @@ import java.util.List;
|
||||
import org.apache.cloudstack.framework.config.ConfigKey;
|
||||
|
||||
import com.cloud.dc.DataCenter;
|
||||
import com.cloud.dc.Pod;
|
||||
import com.cloud.dc.Vlan.VlanType;
|
||||
import com.cloud.exception.ConcurrentOperationException;
|
||||
import com.cloud.exception.InsufficientAddressCapacityException;
|
||||
@ -169,8 +168,8 @@ public interface IpAddressManager {
|
||||
|
||||
int getRuleCountForIp(Long addressId, FirewallRule.Purpose purpose, FirewallRule.State state);
|
||||
|
||||
public String allocateGuestIP(Account ipOwner, boolean isSystem, long zoneId, Long networkId, String requestedIp) throws InsufficientAddressCapacityException;
|
||||
public String allocateGuestIP(Network network, String requestedIp) throws InsufficientAddressCapacityException;
|
||||
|
||||
String allocatePublicIpForGuestNic(Long networkId, DataCenter dc, Pod pod, Account caller, String requestedIp) throws InsufficientAddressCapacityException;
|
||||
String allocatePublicIpForGuestNic(Network network, Account ipOwner, String requestedIp) throws InsufficientAddressCapacityException;
|
||||
|
||||
}
|
||||
|
||||
@ -33,7 +33,7 @@ import com.cloud.vm.NicSecondaryIp;
|
||||
@Table(name = "nic_secondary_ips")
|
||||
public class NicSecondaryIpVO implements NicSecondaryIp {
|
||||
|
||||
public NicSecondaryIpVO(Long nicId, String ipaddr, Long vmId, Long accountId, Long domainId, Long networkId) {
|
||||
public NicSecondaryIpVO(long nicId, String ipaddr, long vmId, long accountId, long domainId, long networkId) {
|
||||
this.nicId = nicId;
|
||||
this.vmId = vmId;
|
||||
this.ip4Address = ipaddr;
|
||||
@ -57,7 +57,7 @@ public class NicSecondaryIpVO implements NicSecondaryIp {
|
||||
long domainId;
|
||||
|
||||
@Column(name = "account_id", updatable = false)
|
||||
private Long accountId;
|
||||
private long accountId;
|
||||
|
||||
@Column(name = "ip4_address")
|
||||
String ip4Address;
|
||||
@ -75,93 +75,53 @@ public class NicSecondaryIpVO implements NicSecondaryIp {
|
||||
String uuid = UUID.randomUUID().toString();
|
||||
|
||||
@Column(name = "vmId")
|
||||
Long vmId;
|
||||
long vmId;
|
||||
|
||||
@Override
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getNicId() {
|
||||
return nicId;
|
||||
}
|
||||
|
||||
public void setNicId(long nicId) {
|
||||
this.nicId = nicId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getDomainId() {
|
||||
return domainId;
|
||||
}
|
||||
|
||||
public void setDomainId(Long domainId) {
|
||||
this.domainId = domainId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getAccountId() {
|
||||
return accountId;
|
||||
}
|
||||
|
||||
public void setAccountId(Long accountId) {
|
||||
this.accountId = accountId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIp4Address() {
|
||||
return ip4Address;
|
||||
}
|
||||
|
||||
public void setIp4Address(String ip4Address) {
|
||||
this.ip4Address = ip4Address;
|
||||
}
|
||||
|
||||
public String getIp6Address() {
|
||||
return ip6Address;
|
||||
}
|
||||
|
||||
public void setIp6Address(String ip6Address) {
|
||||
this.ip6Address = ip6Address;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getNetworkId() {
|
||||
return networkId;
|
||||
}
|
||||
|
||||
public void setNetworkId(long networkId) {
|
||||
this.networkId = networkId;
|
||||
}
|
||||
|
||||
public Date getCreated() {
|
||||
return created;
|
||||
}
|
||||
|
||||
public void setCreated(Date created) {
|
||||
this.created = created;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
public void setUuid(String uuid) {
|
||||
this.uuid = uuid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getVmId() {
|
||||
return vmId;
|
||||
}
|
||||
|
||||
public void setVmId(Long vmId) {
|
||||
this.vmId = vmId;
|
||||
}
|
||||
}
|
||||
|
||||
@ -28,8 +28,6 @@ import java.util.UUID;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import org.apache.cloudstack.acl.ControlledEntity.ACLType;
|
||||
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
|
||||
import org.apache.cloudstack.context.CallContext;
|
||||
@ -41,6 +39,7 @@ import org.apache.cloudstack.region.PortableIp;
|
||||
import org.apache.cloudstack.region.PortableIpDao;
|
||||
import org.apache.cloudstack.region.PortableIpVO;
|
||||
import org.apache.cloudstack.region.Region;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.agent.AgentManager;
|
||||
import com.cloud.alert.AlertManager;
|
||||
@ -389,9 +388,8 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage
|
||||
SearchBuilder<PodVlanMapVO> podVlanMapSB = _podVlanMapDao.createSearchBuilder();
|
||||
podVlanMapSB.and("podId", podVlanMapSB.entity().getPodId(), Op.EQ);
|
||||
AssignIpAddressFromPodVlanSearch.join("podVlanMapSB", podVlanMapSB, podVlanMapSB.entity().getVlanDbId(), AssignIpAddressFromPodVlanSearch.entity().getVlanId(),
|
||||
JoinType.INNER);
|
||||
AssignIpAddressFromPodVlanSearch.join("vlan", podVlanSearch, podVlanSearch.entity().getId(), AssignIpAddressFromPodVlanSearch.entity().getVlanId(),
|
||||
JoinType.INNER);
|
||||
JoinType.INNER);
|
||||
AssignIpAddressFromPodVlanSearch.join("vlan", podVlanSearch, podVlanSearch.entity().getId(), AssignIpAddressFromPodVlanSearch.entity().getVlanId(), JoinType.INNER);
|
||||
AssignIpAddressFromPodVlanSearch.done();
|
||||
|
||||
Network.State.getStateMachine().registerListener(new NetworkStateListener(_usageEventDao, _networksDao));
|
||||
@ -402,7 +400,7 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage
|
||||
}
|
||||
|
||||
private IpAddress allocateIP(Account ipOwner, boolean isSystem, long zoneId) throws ResourceAllocationException, InsufficientAddressCapacityException,
|
||||
ConcurrentOperationException {
|
||||
ConcurrentOperationException {
|
||||
Account caller = CallContext.current().getCallingAccount();
|
||||
long callerUserId = CallContext.current().getCallingUserId();
|
||||
// check permissions
|
||||
@ -465,7 +463,7 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage
|
||||
|
||||
@Override
|
||||
public boolean applyRules(List<? extends FirewallRule> rules, FirewallRule.Purpose purpose, NetworkRuleApplier applier, boolean continueOnError)
|
||||
throws ResourceUnavailableException {
|
||||
throws ResourceUnavailableException {
|
||||
if (rules == null || rules.size() == 0) {
|
||||
s_logger.debug("There are no rules to forward to the network elements");
|
||||
return true;
|
||||
@ -640,20 +638,19 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage
|
||||
|
||||
@Override
|
||||
public PublicIp assignPublicIpAddress(long dcId, Long podId, Account owner, VlanType type, Long networkId, String requestedIp, boolean isSystem)
|
||||
throws InsufficientAddressCapacityException {
|
||||
throws InsufficientAddressCapacityException {
|
||||
return fetchNewPublicIp(dcId, podId, null, owner, type, networkId, false, true, requestedIp, isSystem, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PublicIp assignPublicIpAddressFromVlans(long dcId, Long podId, Account owner, VlanType type, List<Long> vlanDbIds, Long networkId, String requestedIp,
|
||||
boolean isSystem) throws InsufficientAddressCapacityException {
|
||||
public PublicIp assignPublicIpAddressFromVlans(long dcId, Long podId, Account owner, VlanType type, List<Long> vlanDbIds, Long networkId, String requestedIp, boolean isSystem)
|
||||
throws InsufficientAddressCapacityException {
|
||||
return fetchNewPublicIp(dcId, podId, vlanDbIds, owner, type, networkId, false, true, requestedIp, isSystem, null);
|
||||
}
|
||||
|
||||
@DB
|
||||
public PublicIp fetchNewPublicIp(final long dcId, final Long podId, final List<Long> vlanDbIds, final Account owner, final VlanType vlanUse,
|
||||
final Long guestNetworkId, final boolean sourceNat, final boolean assign, final String requestedIp, final boolean isSystem, final Long vpcId)
|
||||
throws InsufficientAddressCapacityException {
|
||||
public PublicIp fetchNewPublicIp(final long dcId, final Long podId, final List<Long> vlanDbIds, final Account owner, final VlanType vlanUse, final Long guestNetworkId,
|
||||
final boolean sourceNat, final boolean assign, final String requestedIp, final boolean isSystem, final Long vpcId) throws InsufficientAddressCapacityException {
|
||||
IPAddressVO addr = Transaction.execute(new TransactionCallbackWithException<IPAddressVO, InsufficientAddressCapacityException>() {
|
||||
@Override
|
||||
public IPAddressVO doInTransaction(TransactionStatus status) throws InsufficientAddressCapacityException {
|
||||
@ -796,8 +793,8 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage
|
||||
@Override
|
||||
public void markPublicIpAsAllocated(final IPAddressVO addr) {
|
||||
|
||||
assert (addr.getState() == IpAddress.State.Allocating || addr.getState() == IpAddress.State.Free) : "Unable to transition from state " + addr.getState() +
|
||||
" to " + IpAddress.State.Allocated;
|
||||
assert (addr.getState() == IpAddress.State.Allocating || addr.getState() == IpAddress.State.Free) : "Unable to transition from state " + addr.getState() + " to "
|
||||
+ IpAddress.State.Allocated;
|
||||
Transaction.execute(new TransactionCallbackNoReturn() {
|
||||
@Override
|
||||
public void doInTransactionWithoutResult(TransactionStatus status) {
|
||||
@ -813,8 +810,8 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage
|
||||
String guestType = vlan.getVlanType().toString();
|
||||
|
||||
if (!isIpDedicated(addr)) {
|
||||
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NET_IP_ASSIGN, owner.getId(), addr.getDataCenterId(), addr.getId(), addr.getAddress()
|
||||
.toString(), addr.isSourceNat(), guestType, addr.getSystem(), addr.getClass().getName(), addr.getUuid());
|
||||
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NET_IP_ASSIGN, owner.getId(), addr.getDataCenterId(), addr.getId(), addr.getAddress().toString(),
|
||||
addr.isSourceNat(), guestType, addr.getSystem(), addr.getClass().getName(), addr.getUuid());
|
||||
}
|
||||
|
||||
if (updateIpResourceCount(addr)) {
|
||||
@ -835,7 +832,7 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage
|
||||
@Override
|
||||
public PublicIp assignSourceNatIpAddressToGuestNetwork(Account owner, Network guestNetwork) throws InsufficientAddressCapacityException, ConcurrentOperationException {
|
||||
assert (guestNetwork.getTrafficType() != null) : "You're asking for a source nat but your network "
|
||||
+ "can't participate in source nat. What do you have to say for yourself?";
|
||||
+ "can't participate in source nat. What do you have to say for yourself?";
|
||||
long dcId = guestNetwork.getDataCenterId();
|
||||
|
||||
IPAddressVO sourceNatIp = getExistingSourceNatInNetwork(owner.getId(), guestNetwork.getId());
|
||||
@ -853,7 +850,7 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage
|
||||
@DB
|
||||
@Override
|
||||
public PublicIp assignDedicateIpAddress(Account owner, final Long guestNtwkId, final Long vpcId, final long dcId, final boolean isSourceNat)
|
||||
throws ConcurrentOperationException, InsufficientAddressCapacityException {
|
||||
throws ConcurrentOperationException, InsufficientAddressCapacityException {
|
||||
|
||||
final long ownerId = owner.getId();
|
||||
|
||||
@ -932,7 +929,7 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage
|
||||
// but still be associated with the account. Its up to caller of this function to decide when to invoke IPAssociation
|
||||
@Override
|
||||
public boolean applyIpAssociations(Network network, boolean postApplyRules, boolean continueOnError, List<? extends PublicIpAddress> publicIps)
|
||||
throws ResourceUnavailableException {
|
||||
throws ResourceUnavailableException {
|
||||
boolean success = true;
|
||||
|
||||
Map<PublicIpAddress, Set<Service>> ipToServices = _networkModel.getIpToServices(publicIps, postApplyRules, true);
|
||||
@ -976,8 +973,8 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage
|
||||
|
||||
@DB
|
||||
@Override
|
||||
public IpAddress allocateIp(final Account ipOwner, final boolean isSystem, Account caller, long callerUserId, final DataCenter zone)
|
||||
throws ConcurrentOperationException, ResourceAllocationException, InsufficientAddressCapacityException {
|
||||
public IpAddress allocateIp(final Account ipOwner, final boolean isSystem, Account caller, long callerUserId, final DataCenter zone) throws ConcurrentOperationException,
|
||||
ResourceAllocationException, InsufficientAddressCapacityException {
|
||||
|
||||
final VlanType vlanType = VlanType.VirtualNetwork;
|
||||
final boolean assign = false;
|
||||
@ -1012,8 +1009,8 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage
|
||||
PublicIp ip = fetchNewPublicIp(zone.getId(), null, null, ipOwner, vlanType, null, false, assign, null, isSystem, null);
|
||||
|
||||
if (ip == null) {
|
||||
InsufficientAddressCapacityException ex =
|
||||
new InsufficientAddressCapacityException("Unable to find available public IP addresses", DataCenter.class, zone.getId());
|
||||
InsufficientAddressCapacityException ex = new InsufficientAddressCapacityException("Unable to find available public IP addresses", DataCenter.class, zone
|
||||
.getId());
|
||||
ex.addProxyObject(ApiDBUtils.findZoneById(zone.getId()).getUuid());
|
||||
throw ex;
|
||||
}
|
||||
@ -1040,8 +1037,8 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage
|
||||
|
||||
@Override
|
||||
@DB
|
||||
public IpAddress allocatePortableIp(final Account ipOwner, Account caller, final long dcId, final Long networkId, final Long vpcID)
|
||||
throws ConcurrentOperationException, ResourceAllocationException, InsufficientAddressCapacityException {
|
||||
public IpAddress allocatePortableIp(final Account ipOwner, Account caller, final long dcId, final Long networkId, final Long vpcID) throws ConcurrentOperationException,
|
||||
ResourceAllocationException, InsufficientAddressCapacityException {
|
||||
|
||||
GlobalLock portableIpLock = GlobalLock.getInternLock("PortablePublicIpRange");
|
||||
IPAddressVO ipaddr;
|
||||
@ -1056,8 +1053,8 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage
|
||||
|
||||
List<PortableIpVO> portableIpVOs = _portableIpDao.listByRegionIdAndState(1, PortableIp.State.Free);
|
||||
if (portableIpVOs == null || portableIpVOs.isEmpty()) {
|
||||
InsufficientAddressCapacityException ex =
|
||||
new InsufficientAddressCapacityException("Unable to find available portable IP addresses", Region.class, new Long(1));
|
||||
InsufficientAddressCapacityException ex = new InsufficientAddressCapacityException("Unable to find available portable IP addresses", Region.class,
|
||||
new Long(1));
|
||||
throw ex;
|
||||
}
|
||||
|
||||
@ -1077,22 +1074,20 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage
|
||||
long physicalNetworkId = _networkModel.getDefaultPhysicalNetworkByZoneAndTrafficType(dcId, TrafficType.Public).getId();
|
||||
Network network = _networkModel.getSystemNetworkByZoneAndTrafficType(dcId, TrafficType.Public);
|
||||
String range = allocatedPortableIp.getAddress() + "-" + allocatedPortableIp.getAddress();
|
||||
VlanVO vlan =
|
||||
new VlanVO(VlanType.VirtualNetwork, allocatedPortableIp.getVlan(), allocatedPortableIp.getGateway(), allocatedPortableIp.getNetmask(), dcId,
|
||||
VlanVO vlan = new VlanVO(VlanType.VirtualNetwork, allocatedPortableIp.getVlan(), allocatedPortableIp.getGateway(), allocatedPortableIp.getNetmask(), dcId,
|
||||
range, network.getId(), physicalNetworkId, null, null, null);
|
||||
vlan = _vlanDao.persist(vlan);
|
||||
|
||||
// provision the portable IP in to user_ip_address table
|
||||
IPAddressVO ipaddr =
|
||||
new IPAddressVO(new Ip(allocatedPortableIp.getAddress()), dcId, networkId, vpcID, physicalNetworkId, network.getId(), vlan.getId(), true);
|
||||
IPAddressVO ipaddr = new IPAddressVO(new Ip(allocatedPortableIp.getAddress()), dcId, networkId, vpcID, physicalNetworkId, network.getId(), vlan.getId(), true);
|
||||
ipaddr.setState(State.Allocated);
|
||||
ipaddr.setAllocatedTime(new Date());
|
||||
ipaddr.setAllocatedInDomainId(ipOwner.getDomainId());
|
||||
ipaddr.setAllocatedToAccountId(ipOwner.getId());
|
||||
ipaddr = _ipAddressDao.persist(ipaddr);
|
||||
|
||||
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_PORTABLE_IP_ASSIGN, ipaddr.getId(), ipaddr.getDataCenterId(), ipaddr.getId(), ipaddr.getAddress()
|
||||
.toString(), ipaddr.isSourceNat(), null, ipaddr.getSystem(), ipaddr.getClass().getName(), ipaddr.getUuid());
|
||||
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_PORTABLE_IP_ASSIGN, ipaddr.getId(), ipaddr.getDataCenterId(), ipaddr.getId(),
|
||||
ipaddr.getAddress().toString(), ipaddr.isSourceNat(), null, ipaddr.getSystem(), ipaddr.getClass().getName(), ipaddr.getUuid());
|
||||
|
||||
return ipaddr;
|
||||
}
|
||||
@ -1135,7 +1130,7 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage
|
||||
@DB
|
||||
@Override
|
||||
public IPAddressVO associateIPToGuestNetwork(long ipId, long networkId, boolean releaseOnFailure) throws ResourceAllocationException, ResourceUnavailableException,
|
||||
InsufficientAddressCapacityException, ConcurrentOperationException {
|
||||
InsufficientAddressCapacityException, ConcurrentOperationException {
|
||||
Account caller = CallContext.current().getCallingAccount();
|
||||
Account owner = null;
|
||||
|
||||
@ -1153,7 +1148,7 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage
|
||||
_accountMgr.checkAccess(CallContext.current().getCallingAccount(), AccessType.UseNetwork, false, network);
|
||||
} else {
|
||||
throw new InvalidParameterValueException("IP can be associated with guest network of 'shared' type only if "
|
||||
+ "network services Source Nat, Static Nat, Port Forwarding, Load balancing, firewall are enabled in the network");
|
||||
+ "network services Source Nat, Static Nat, Port Forwarding, Load balancing, firewall are enabled in the network");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -1198,15 +1193,15 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage
|
||||
if (zone.getNetworkType() == NetworkType.Advanced) {
|
||||
// In Advance zone allow to do IP assoc only for Isolated networks with source nat service enabled
|
||||
if (network.getGuestType() == GuestType.Isolated && !(_networkModel.areServicesSupportedInNetwork(network.getId(), Service.SourceNat))) {
|
||||
throw new InvalidParameterValueException("In zone of type " + NetworkType.Advanced + " ip address can be associated only to the network of guest type " +
|
||||
GuestType.Isolated + " with the " + Service.SourceNat.getName() + " enabled");
|
||||
throw new InvalidParameterValueException("In zone of type " + NetworkType.Advanced + " ip address can be associated only to the network of guest type "
|
||||
+ GuestType.Isolated + " with the " + Service.SourceNat.getName() + " enabled");
|
||||
}
|
||||
|
||||
// In Advance zone allow to do IP assoc only for shared networks with source nat/static nat/lb/pf services enabled
|
||||
if (network.getGuestType() == GuestType.Shared && !isSharedNetworkOfferingWithServices(network.getNetworkOfferingId())) {
|
||||
throw new InvalidParameterValueException("In zone of type " + NetworkType.Advanced + " ip address can be associated with network of guest type " +
|
||||
GuestType.Shared + "only if at " + "least one of the services " + Service.SourceNat.getName() + "/" + Service.StaticNat.getName() + "/" +
|
||||
Service.Lb.getName() + "/" + Service.PortForwarding.getName() + " is enabled");
|
||||
throw new InvalidParameterValueException("In zone of type " + NetworkType.Advanced + " ip address can be associated with network of guest type " + GuestType.Shared
|
||||
+ "only if at " + "least one of the services " + Service.SourceNat.getName() + "/" + Service.StaticNat.getName() + "/" + Service.Lb.getName() + "/"
|
||||
+ Service.PortForwarding.getName() + " is enabled");
|
||||
}
|
||||
}
|
||||
|
||||
@ -1259,27 +1254,27 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage
|
||||
|
||||
protected boolean isSharedNetworkOfferingWithServices(long networkOfferingId) {
|
||||
NetworkOfferingVO networkOffering = _networkOfferingDao.findById(networkOfferingId);
|
||||
if ((networkOffering.getGuestType() == Network.GuestType.Shared) &&
|
||||
(_networkModel.areServicesSupportedByNetworkOffering(networkOfferingId, Service.SourceNat) ||
|
||||
_networkModel.areServicesSupportedByNetworkOffering(networkOfferingId, Service.StaticNat) ||
|
||||
_networkModel.areServicesSupportedByNetworkOffering(networkOfferingId, Service.Firewall) ||
|
||||
_networkModel.areServicesSupportedByNetworkOffering(networkOfferingId, Service.PortForwarding) || _networkModel.areServicesSupportedByNetworkOffering(
|
||||
networkOfferingId, Service.Lb))) {
|
||||
if ((networkOffering.getGuestType() == Network.GuestType.Shared)
|
||||
&& (_networkModel.areServicesSupportedByNetworkOffering(networkOfferingId, Service.SourceNat)
|
||||
|| _networkModel.areServicesSupportedByNetworkOffering(networkOfferingId, Service.StaticNat)
|
||||
|| _networkModel.areServicesSupportedByNetworkOffering(networkOfferingId, Service.Firewall)
|
||||
|| _networkModel.areServicesSupportedByNetworkOffering(networkOfferingId, Service.PortForwarding) || _networkModel.areServicesSupportedByNetworkOffering(
|
||||
networkOfferingId, Service.Lb))) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPAddressVO associatePortableIPToGuestNetwork(long ipAddrId, long networkId, boolean releaseOnFailure) throws ResourceAllocationException,
|
||||
ResourceUnavailableException, InsufficientAddressCapacityException, ConcurrentOperationException {
|
||||
public IPAddressVO associatePortableIPToGuestNetwork(long ipAddrId, long networkId, boolean releaseOnFailure) throws ResourceAllocationException, ResourceUnavailableException,
|
||||
InsufficientAddressCapacityException, ConcurrentOperationException {
|
||||
return associateIPToGuestNetwork(ipAddrId, networkId, releaseOnFailure);
|
||||
}
|
||||
|
||||
@DB
|
||||
@Override
|
||||
public IPAddressVO disassociatePortableIPToGuestNetwork(long ipId, long networkId) throws ResourceAllocationException, ResourceUnavailableException,
|
||||
InsufficientAddressCapacityException, ConcurrentOperationException {
|
||||
InsufficientAddressCapacityException, ConcurrentOperationException {
|
||||
|
||||
Account caller = CallContext.current().getCallingAccount();
|
||||
Account owner = null;
|
||||
@ -1386,7 +1381,7 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage
|
||||
@DB
|
||||
@Override
|
||||
public void transferPortableIP(final long ipAddrId, long currentNetworkId, long newNetworkId) throws ResourceAllocationException, ResourceUnavailableException,
|
||||
InsufficientAddressCapacityException, ConcurrentOperationException {
|
||||
InsufficientAddressCapacityException, ConcurrentOperationException {
|
||||
|
||||
Network srcNetwork = _networksDao.findById(currentNetworkId);
|
||||
if (srcNetwork == null) {
|
||||
@ -1454,7 +1449,7 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage
|
||||
// trigger an action event for the transfer of portable IP across the networks, so that external entities
|
||||
// monitoring for this event can initiate the route advertisement for the availability of IP from the zoe
|
||||
ActionEventUtils.onActionEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, Domain.ROOT_DOMAIN, EventTypes.EVENT_PORTABLE_IP_TRANSFER,
|
||||
"Portable IP associated is transferred from network " + currentNetworkId + " to " + newNetworkId);
|
||||
"Portable IP associated is transferred from network " + currentNetworkId + " to " + newNetworkId);
|
||||
}
|
||||
|
||||
protected List<? extends Network> getIsolatedNetworksWithSourceNATOwnedByAccountInZone(long zoneId, Account owner) {
|
||||
@ -1465,7 +1460,7 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage
|
||||
@Override
|
||||
@DB
|
||||
public boolean associateIpAddressListToAccount(long userId, final long accountId, final long zoneId, final Long vlanId, final Network guestNetworkFinal)
|
||||
throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException, ResourceAllocationException {
|
||||
throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException, ResourceAllocationException {
|
||||
final Account owner = _accountMgr.getActiveAccountById(accountId);
|
||||
|
||||
if (guestNetworkFinal != null && guestNetworkFinal.getTrafficType() != TrafficType.Guest) {
|
||||
@ -1477,7 +1472,7 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage
|
||||
pair = Transaction.execute(new TransactionCallbackWithException<Ternary<Boolean, List<NetworkOfferingVO>, Network>, Exception>() {
|
||||
@Override
|
||||
public Ternary<Boolean, List<NetworkOfferingVO>, Network> doInTransaction(TransactionStatus status) throws InsufficientCapacityException,
|
||||
ResourceAllocationException {
|
||||
ResourceAllocationException {
|
||||
boolean createNetwork = false;
|
||||
Network guestNetwork = guestNetworkFinal;
|
||||
|
||||
@ -1489,41 +1484,37 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage
|
||||
guestNetwork = networks.get(0);
|
||||
} else {
|
||||
throw new InvalidParameterValueException("Error, more than 1 Guest Isolated Networks with SourceNAT "
|
||||
+ "service enabled found for this account, cannot assosiate the IP range, please provide the network ID");
|
||||
+ "service enabled found for this account, cannot assosiate the IP range, please provide the network ID");
|
||||
}
|
||||
}
|
||||
|
||||
// create new Virtual network (Isolated with SourceNAT) for the user if it doesn't exist
|
||||
List<NetworkOfferingVO> requiredOfferings = _networkOfferingDao.listByAvailability(Availability.Required, false);
|
||||
if (requiredOfferings.size() < 1) {
|
||||
throw new CloudRuntimeException("Unable to find network offering with availability=" + Availability.Required +
|
||||
" to automatically create the network as part of createVlanIpRange");
|
||||
throw new CloudRuntimeException("Unable to find network offering with availability=" + Availability.Required
|
||||
+ " to automatically create the network as part of createVlanIpRange");
|
||||
}
|
||||
if (createNetwork) {
|
||||
if (requiredOfferings.get(0).getState() == NetworkOffering.State.Enabled) {
|
||||
long physicalNetworkId =
|
||||
_networkModel.findPhysicalNetworkId(zoneId, requiredOfferings.get(0).getTags(), requiredOfferings.get(0).getTrafficType());
|
||||
long physicalNetworkId = _networkModel.findPhysicalNetworkId(zoneId, requiredOfferings.get(0).getTags(), requiredOfferings.get(0).getTrafficType());
|
||||
// Validate physical network
|
||||
PhysicalNetwork physicalNetwork = _physicalNetworkDao.findById(physicalNetworkId);
|
||||
if (physicalNetwork == null) {
|
||||
throw new InvalidParameterValueException("Unable to find physical network with id: " + physicalNetworkId + " and tag: " +
|
||||
requiredOfferings.get(0).getTags());
|
||||
throw new InvalidParameterValueException("Unable to find physical network with id: " + physicalNetworkId + " and tag: "
|
||||
+ requiredOfferings.get(0).getTags());
|
||||
}
|
||||
|
||||
s_logger.debug("Creating network for account " + owner + " from the network offering id=" + requiredOfferings.get(0).getId() +
|
||||
" as a part of createVlanIpRange process");
|
||||
guestNetwork =
|
||||
_networkMgr.createGuestNetwork(requiredOfferings.get(0).getId(), owner.getAccountName() + "-network",
|
||||
owner.getAccountName() + "-network", null, null, null, null, owner, null, physicalNetwork, zoneId, ACLType.Account, null, null, null,
|
||||
null, true, null);
|
||||
s_logger.debug("Creating network for account " + owner + " from the network offering id=" + requiredOfferings.get(0).getId()
|
||||
+ " as a part of createVlanIpRange process");
|
||||
guestNetwork = _networkMgr.createGuestNetwork(requiredOfferings.get(0).getId(), owner.getAccountName() + "-network", owner.getAccountName()
|
||||
+ "-network", null, null, null, null, owner, null, physicalNetwork, zoneId, ACLType.Account, null, null, null, null, true, null);
|
||||
if (guestNetwork == null) {
|
||||
s_logger.warn("Failed to create default Virtual network for the account " + accountId + "in zone " + zoneId);
|
||||
throw new CloudRuntimeException("Failed to create a Guest Isolated Networks with SourceNAT " +
|
||||
"service enabled as a part of createVlanIpRange, for the account " + accountId + "in zone " + zoneId);
|
||||
throw new CloudRuntimeException("Failed to create a Guest Isolated Networks with SourceNAT "
|
||||
+ "service enabled as a part of createVlanIpRange, for the account " + accountId + "in zone " + zoneId);
|
||||
}
|
||||
} else {
|
||||
throw new CloudRuntimeException("Required network offering id=" + requiredOfferings.get(0).getId() + " is not in " +
|
||||
NetworkOffering.State.Enabled);
|
||||
throw new CloudRuntimeException("Required network offering id=" + requiredOfferings.get(0).getId() + " is not in " + NetworkOffering.State.Enabled);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1586,8 +1577,7 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage
|
||||
guestNetwork = implementedNetwork.second();
|
||||
} catch (Exception ex) {
|
||||
s_logger.warn("Failed to implement network " + guestNetwork + " elements and resources as a part of" + " network provision due to ", ex);
|
||||
CloudRuntimeException e =
|
||||
new CloudRuntimeException("Failed to implement network (with specified id)"
|
||||
CloudRuntimeException e = new CloudRuntimeException("Failed to implement network (with specified id)"
|
||||
+ " elements and resources as a part of network provision for persistent network");
|
||||
e.addProxyObject(guestNetwork.getUuid(), "networkId");
|
||||
throw e;
|
||||
@ -1621,8 +1611,8 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage
|
||||
String guestType = vlan.getVlanType().toString();
|
||||
if (!isIpDedicated(ip)) {
|
||||
String eventType = ip.isPortable() ? EventTypes.EVENT_PORTABLE_IP_RELEASE : EventTypes.EVENT_NET_IP_RELEASE;
|
||||
UsageEventUtils.publishUsageEvent(eventType, ip.getAllocatedToAccountId(), ip.getDataCenterId(), addrId, ip.getAddress().addr(),
|
||||
ip.isSourceNat(), guestType, ip.getSystem(), ip.getClass().getName(), ip.getUuid());
|
||||
UsageEventUtils.publishUsageEvent(eventType, ip.getAllocatedToAccountId(), ip.getDataCenterId(), addrId, ip.getAddress().addr(), ip.isSourceNat(),
|
||||
guestType, ip.getSystem(), ip.getClass().getName(), ip.getUuid());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1817,7 +1807,7 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage
|
||||
@Override
|
||||
@DB
|
||||
public void allocateDirectIp(final NicProfile nic, final DataCenter dc, final VirtualMachineProfile vm, final Network network, final String requestedIpv4,
|
||||
final String requestedIpv6) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException {
|
||||
final String requestedIpv6) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException {
|
||||
Transaction.execute(new TransactionCallbackWithExceptionNoReturn<InsufficientAddressCapacityException>() {
|
||||
@Override
|
||||
public void doInTransactionWithoutResult(TransactionStatus status) throws InsufficientAddressCapacityException {
|
||||
@ -1898,8 +1888,8 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage
|
||||
}
|
||||
|
||||
@Override
|
||||
public String allocatePublicIpForGuestNic(Long networkId, DataCenter dc, Pod pod, Account owner, String requestedIp) throws InsufficientAddressCapacityException {
|
||||
PublicIp ip = assignPublicIpAddress(dc.getId(), null, owner, VlanType.DirectAttached, networkId, requestedIp, false);
|
||||
public String allocatePublicIpForGuestNic(Network network, Account owner, String requestedIp) throws InsufficientAddressCapacityException {
|
||||
PublicIp ip = assignPublicIpAddress(network.getDataCenterId(), null, owner, VlanType.DirectAttached, network.getId(), requestedIp, false);
|
||||
if (ip == null) {
|
||||
s_logger.debug("There is no free public ip address");
|
||||
return null;
|
||||
@ -1909,16 +1899,8 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage
|
||||
}
|
||||
|
||||
@Override
|
||||
public String allocateGuestIP(Account ipOwner, boolean isSystem, long zoneId, Long networkId, String requestedIp) throws InsufficientAddressCapacityException {
|
||||
String ipaddr = null;
|
||||
Account caller = CallContext.current().getCallingAccount();
|
||||
// check permissions
|
||||
Network network = _networksDao.findById(networkId);
|
||||
|
||||
_accountMgr.checkAccess(caller, null, false, network);
|
||||
|
||||
ipaddr = acquireGuestIpAddress(network, requestedIp);
|
||||
return ipaddr;
|
||||
public String allocateGuestIP(Network network, String requestedIp) throws InsufficientAddressCapacityException {
|
||||
return acquireGuestIpAddress(network, requestedIp);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -63,7 +63,6 @@ import com.cloud.dc.DataCenter;
|
||||
import com.cloud.dc.DataCenter.NetworkType;
|
||||
import com.cloud.dc.DataCenterVO;
|
||||
import com.cloud.dc.DataCenterVnetVO;
|
||||
import com.cloud.dc.Pod;
|
||||
import com.cloud.dc.Vlan.VlanType;
|
||||
import com.cloud.dc.VlanVO;
|
||||
import com.cloud.dc.dao.AccountVlanMapDao;
|
||||
@ -640,14 +639,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public NicSecondaryIp allocateSecondaryGuestIP(Account ipOwner, long zoneId, final Long nicId, final Long networkId, String requestedIp)
|
||||
throws InsufficientAddressCapacityException {
|
||||
|
||||
String ipaddr = null;
|
||||
|
||||
if (networkId == null) {
|
||||
throw new InvalidParameterValueException("Invalid network id is given");
|
||||
}
|
||||
public NicSecondaryIp allocateSecondaryGuestIP(final long nicId, String requestedIp) throws InsufficientAddressCapacityException {
|
||||
|
||||
Account caller = CallContext.current().getCallingAccount();
|
||||
|
||||
@ -665,47 +657,30 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService {
|
||||
if (vm == null) {
|
||||
throw new InvalidParameterValueException("There is no vm with the nic");
|
||||
}
|
||||
|
||||
final long networkId = nicVO.getNetworkId();
|
||||
final Account ipOwner = _accountMgr.getAccount(vm.getAccountId());
|
||||
|
||||
// verify permissions
|
||||
_accountMgr.checkAccess(ipOwner, null, true, vm);
|
||||
_accountMgr.checkAccess(caller, null, true, vm);
|
||||
|
||||
Network network = _networksDao.findById(networkId);
|
||||
if (network == null) {
|
||||
throw new InvalidParameterValueException("Invalid network id is given");
|
||||
}
|
||||
final Long accountId = ipOwner.getAccountId();
|
||||
final Long domainId = ipOwner.getDomainId();
|
||||
|
||||
// Validate network offering
|
||||
NetworkOfferingVO ntwkOff = _networkOfferingDao.findById(network.getNetworkOfferingId());
|
||||
|
||||
DataCenter dc = _dcDao.findById(network.getDataCenterId());
|
||||
|
||||
DataCenter zone = _entityMgr.findById(DataCenter.class, zoneId);
|
||||
if (zone == null) {
|
||||
throw new InvalidParameterValueException("Invalid zone Id is given");
|
||||
}
|
||||
|
||||
s_logger.debug("Calling the ip allocation ...");
|
||||
if (dc.getNetworkType() == NetworkType.Advanced && network.getGuestType() == Network.GuestType.Isolated) {
|
||||
String ipaddr = null;
|
||||
//Isolated network can exist in Basic zone only, so no need to verify the zone type
|
||||
if (network.getGuestType() == Network.GuestType.Isolated) {
|
||||
try {
|
||||
ipaddr = _ipAddrMgr.allocateGuestIP(ipOwner, false, zoneId, networkId, requestedIp);
|
||||
ipaddr = _ipAddrMgr.allocateGuestIP(network, requestedIp);
|
||||
} catch (InsufficientAddressCapacityException e) {
|
||||
throw new InvalidParameterValueException("Allocating guest ip for nic failed");
|
||||
}
|
||||
} else if (dc.getNetworkType() == NetworkType.Basic || ntwkOff.getGuestType() == Network.GuestType.Shared) {
|
||||
//handle the basic networks here
|
||||
VMInstanceVO vmi = (VMInstanceVO)vm;
|
||||
Long podId = vmi.getPodIdToDeployIn();
|
||||
if (podId == null) {
|
||||
throw new InvalidParameterValueException("vm pod id is null");
|
||||
}
|
||||
Pod pod = _hostPodDao.findById(podId);
|
||||
if (pod == null) {
|
||||
throw new InvalidParameterValueException("vm pod is null");
|
||||
}
|
||||
|
||||
} else if (network.getGuestType() == Network.GuestType.Shared) {
|
||||
try {
|
||||
ipaddr = _ipAddrMgr.allocatePublicIpForGuestNic(networkId, dc, pod, caller, requestedIp);
|
||||
ipaddr = _ipAddrMgr.allocatePublicIpForGuestNic(network, ipOwner, requestedIp);
|
||||
if (ipaddr == null) {
|
||||
throw new InvalidParameterValueException("Allocating ip to guest nic " + nicId + " failed");
|
||||
}
|
||||
@ -734,7 +709,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService {
|
||||
|
||||
s_logger.debug("Setting nic_secondary_ip table ...");
|
||||
Long vmId = nicVO.getInstanceId();
|
||||
NicSecondaryIpVO secondaryIpVO = new NicSecondaryIpVO(nicId, addrFinal, vmId, accountId, domainId, networkId);
|
||||
NicSecondaryIpVO secondaryIpVO = new NicSecondaryIpVO(nicId, addrFinal, vmId, ipOwner.getId(), ipOwner.getDomainId(), networkId);
|
||||
_nicSecondaryIpDao.persist(secondaryIpVO);
|
||||
return secondaryIpVO.getId();
|
||||
}
|
||||
|
||||
@ -40,9 +40,6 @@ import javax.ejb.Local;
|
||||
import javax.inject.Inject;
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import org.apache.cloudstack.api.command.user.securitygroup.AuthorizeSecurityGroupEgressCmd;
|
||||
import org.apache.cloudstack.api.command.user.securitygroup.AuthorizeSecurityGroupIngressCmd;
|
||||
import org.apache.cloudstack.api.command.user.securitygroup.CreateSecurityGroupCmd;
|
||||
@ -54,6 +51,8 @@ import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationSe
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
||||
import org.apache.cloudstack.managed.context.ManagedContextRunnable;
|
||||
import org.apache.cloudstack.utils.identity.ManagementServerNode;
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.agent.AgentManager;
|
||||
import com.cloud.agent.api.NetworkRulesSystemVmCommand;
|
||||
@ -122,8 +121,7 @@ import com.cloud.vm.dao.UserVmDao;
|
||||
import com.cloud.vm.dao.VMInstanceDao;
|
||||
|
||||
@Local(value = {SecurityGroupManager.class, SecurityGroupService.class})
|
||||
public class SecurityGroupManagerImpl extends ManagerBase implements SecurityGroupManager, SecurityGroupService,
|
||||
StateListener<State, VirtualMachine.Event, VirtualMachine> {
|
||||
public class SecurityGroupManagerImpl extends ManagerBase implements SecurityGroupManager, SecurityGroupService, StateListener<State, VirtualMachine.Event, VirtualMachine> {
|
||||
public static final Logger s_logger = Logger.getLogger(SecurityGroupManagerImpl.class);
|
||||
|
||||
@Inject
|
||||
@ -464,8 +462,8 @@ public class SecurityGroupManagerImpl extends ManagerBase implements SecurityGro
|
||||
// For each group, find the security rules that allow the group
|
||||
for (SecurityGroupVMMapVO mapVO : groupsForVm) {// FIXME: use custom sql in the dao
|
||||
//Add usage events for security group assign
|
||||
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_SECURITY_GROUP_ASSIGN, vm.getAccountId(), vm.getDataCenterId(), vm.getId(), mapVO.getSecurityGroupId(),
|
||||
vm.getClass().getName(), vm.getUuid());
|
||||
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_SECURITY_GROUP_ASSIGN, vm.getAccountId(), vm.getDataCenterId(), vm.getId(), mapVO.getSecurityGroupId(), vm
|
||||
.getClass().getName(), vm.getUuid());
|
||||
|
||||
List<SecurityGroupRuleVO> allowingRules = _securityGroupRuleDao.listByAllowedSecurityGroupId(mapVO.getSecurityGroupId());
|
||||
// For each security rule that allows a group that the vm belongs to, find the group it belongs to
|
||||
@ -480,8 +478,8 @@ public class SecurityGroupManagerImpl extends ManagerBase implements SecurityGro
|
||||
// For each group, find the security rules rules that allow the group
|
||||
for (SecurityGroupVMMapVO mapVO : groupsForVm) {// FIXME: use custom sql in the dao
|
||||
//Add usage events for security group remove
|
||||
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_SECURITY_GROUP_REMOVE, vm.getAccountId(), vm.getDataCenterId(), vm.getId(), mapVO.getSecurityGroupId(),
|
||||
vm.getClass().getName(), vm.getUuid());
|
||||
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_SECURITY_GROUP_REMOVE, vm.getAccountId(), vm.getDataCenterId(), vm.getId(), mapVO.getSecurityGroupId(), vm
|
||||
.getClass().getName(), vm.getUuid());
|
||||
|
||||
List<SecurityGroupRuleVO> allowingRules = _securityGroupRuleDao.listByAllowedSecurityGroupId(mapVO.getSecurityGroupId());
|
||||
// For each security rule that allows a group that the vm belongs to, find the group it belongs to
|
||||
@ -505,27 +503,27 @@ public class SecurityGroupManagerImpl extends ManagerBase implements SecurityGro
|
||||
}
|
||||
|
||||
protected SecurityGroupRulesCmd generateRulesetCmd(String vmName, String guestIp, String guestMac, Long vmId, String signature, long seqnum,
|
||||
Map<PortAndProto, Set<String>> ingressRules, Map<PortAndProto, Set<String>> egressRules, List<String> secIps) {
|
||||
Map<PortAndProto, Set<String>> ingressRules, Map<PortAndProto, Set<String>> egressRules, List<String> secIps) {
|
||||
List<IpPortAndProto> ingressResult = new ArrayList<IpPortAndProto>();
|
||||
List<IpPortAndProto> egressResult = new ArrayList<IpPortAndProto>();
|
||||
for (PortAndProto pAp : ingressRules.keySet()) {
|
||||
Set<String> cidrs = ingressRules.get(pAp);
|
||||
if (cidrs.size() > 0) {
|
||||
IpPortAndProto ipPortAndProto =
|
||||
new SecurityGroupRulesCmd.IpPortAndProto(pAp.getProto(), pAp.getStartPort(), pAp.getEndPort(), cidrs.toArray(new String[cidrs.size()]));
|
||||
IpPortAndProto ipPortAndProto = new SecurityGroupRulesCmd.IpPortAndProto(pAp.getProto(), pAp.getStartPort(), pAp.getEndPort(), cidrs.toArray(new String[cidrs
|
||||
.size()]));
|
||||
ingressResult.add(ipPortAndProto);
|
||||
}
|
||||
}
|
||||
for (PortAndProto pAp : egressRules.keySet()) {
|
||||
Set<String> cidrs = egressRules.get(pAp);
|
||||
if (cidrs.size() > 0) {
|
||||
IpPortAndProto ipPortAndProto =
|
||||
new SecurityGroupRulesCmd.IpPortAndProto(pAp.getProto(), pAp.getStartPort(), pAp.getEndPort(), cidrs.toArray(new String[cidrs.size()]));
|
||||
IpPortAndProto ipPortAndProto = new SecurityGroupRulesCmd.IpPortAndProto(pAp.getProto(), pAp.getStartPort(), pAp.getEndPort(), cidrs.toArray(new String[cidrs
|
||||
.size()]));
|
||||
egressResult.add(ipPortAndProto);
|
||||
}
|
||||
}
|
||||
return new SecurityGroupRulesCmd(guestIp, guestMac, vmName, vmId, signature, seqnum, ingressResult.toArray(new IpPortAndProto[ingressResult.size()]),
|
||||
egressResult.toArray(new IpPortAndProto[egressResult.size()]), secIps);
|
||||
egressResult.toArray(new IpPortAndProto[egressResult.size()]), secIps);
|
||||
}
|
||||
|
||||
protected void handleVmStopped(VMInstanceVO vm) {
|
||||
@ -590,7 +588,7 @@ public class SecurityGroupManagerImpl extends ManagerBase implements SecurityGro
|
||||
}
|
||||
|
||||
private List<SecurityGroupRuleVO> authorizeSecurityGroupRule(final Long securityGroupId, String protocol, Integer startPort, Integer endPort, Integer icmpType,
|
||||
Integer icmpCode, final List<String> cidrList, Map groupList, final SecurityRuleType ruleType) {
|
||||
Integer icmpCode, final List<String> cidrList, Map groupList, final SecurityRuleType ruleType) {
|
||||
Integer startPortOrType = null;
|
||||
Integer endPortOrCode = null;
|
||||
|
||||
@ -685,19 +683,19 @@ public class SecurityGroupManagerImpl extends ManagerBase implements SecurityGro
|
||||
|
||||
if ((group == null) || (authorizedAccountName == null)) {
|
||||
throw new InvalidParameterValueException(
|
||||
"Invalid user group specified, fields 'group' and 'account' cannot be null, please specify groups in the form: userGroupList[0].group=XXX&userGroupList[0].account=YYY");
|
||||
"Invalid user group specified, fields 'group' and 'account' cannot be null, please specify groups in the form: userGroupList[0].group=XXX&userGroupList[0].account=YYY");
|
||||
}
|
||||
|
||||
Account authorizedAccount = _accountDao.findActiveAccount(authorizedAccountName, domainId);
|
||||
if (authorizedAccount == null) {
|
||||
throw new InvalidParameterValueException("Nonexistent account: " + authorizedAccountName + " when trying to authorize security group rule for " +
|
||||
securityGroupId + ":" + protocol + ":" + startPortOrType + ":" + endPortOrCode);
|
||||
throw new InvalidParameterValueException("Nonexistent account: " + authorizedAccountName + " when trying to authorize security group rule for "
|
||||
+ securityGroupId + ":" + protocol + ":" + startPortOrType + ":" + endPortOrCode);
|
||||
}
|
||||
|
||||
SecurityGroupVO groupVO = _securityGroupDao.findByAccountAndName(authorizedAccount.getId(), group);
|
||||
if (groupVO == null) {
|
||||
throw new InvalidParameterValueException("Nonexistent group " + group + " for account " + authorizedAccountName + "/" + domainId +
|
||||
" is given, unable to authorize security group rule.");
|
||||
throw new InvalidParameterValueException("Nonexistent group " + group + " for account " + authorizedAccountName + "/" + domainId
|
||||
+ " is given, unable to authorize security group rule.");
|
||||
}
|
||||
|
||||
// Check permissions
|
||||
@ -737,21 +735,19 @@ public class SecurityGroupManagerImpl extends ManagerBase implements SecurityGro
|
||||
throw new ConcurrentAccessException("Failed to acquire lock on security group: " + ngId);
|
||||
}
|
||||
}
|
||||
SecurityGroupRuleVO securityGroupRule =
|
||||
_securityGroupRuleDao.findByProtoPortsAndAllowedGroupId(securityGroup.getId(), protocolFinal, startPortOrTypeFinal, endPortOrCodeFinal,
|
||||
ngVO.getId());
|
||||
SecurityGroupRuleVO securityGroupRule = _securityGroupRuleDao.findByProtoPortsAndAllowedGroupId(securityGroup.getId(), protocolFinal, startPortOrTypeFinal,
|
||||
endPortOrCodeFinal, ngVO.getId());
|
||||
if ((securityGroupRule != null) && (securityGroupRule.getRuleType() == ruleType)) {
|
||||
continue; // rule already exists.
|
||||
}
|
||||
securityGroupRule =
|
||||
new SecurityGroupRuleVO(ruleType, securityGroup.getId(), startPortOrTypeFinal, endPortOrCodeFinal, protocolFinal, ngVO.getId());
|
||||
securityGroupRule = new SecurityGroupRuleVO(ruleType, securityGroup.getId(), startPortOrTypeFinal, endPortOrCodeFinal, protocolFinal, ngVO.getId());
|
||||
securityGroupRule = _securityGroupRuleDao.persist(securityGroupRule);
|
||||
newRules.add(securityGroupRule);
|
||||
}
|
||||
if (cidrList != null) {
|
||||
for (String cidr : cidrList) {
|
||||
SecurityGroupRuleVO securityGroupRule =
|
||||
_securityGroupRuleDao.findByProtoPortsAndCidr(securityGroup.getId(), protocolFinal, startPortOrTypeFinal, endPortOrCodeFinal, cidr);
|
||||
SecurityGroupRuleVO securityGroupRule = _securityGroupRuleDao.findByProtoPortsAndCidr(securityGroup.getId(), protocolFinal, startPortOrTypeFinal,
|
||||
endPortOrCodeFinal, cidr);
|
||||
if ((securityGroupRule != null) && (securityGroupRule.getRuleType() == ruleType)) {
|
||||
continue;
|
||||
}
|
||||
@ -893,8 +889,8 @@ public class SecurityGroupManagerImpl extends ManagerBase implements SecurityGro
|
||||
|
||||
_serverId = ManagementServerNode.getManagementServerId();
|
||||
|
||||
s_logger.info("SecurityGroupManager: num worker threads=" + _numWorkerThreads + ", time between cleanups=" + _timeBetweenCleanups + " global lock timeout=" +
|
||||
_globalWorkLockTimeout);
|
||||
s_logger.info("SecurityGroupManager: num worker threads=" + _numWorkerThreads + ", time between cleanups=" + _timeBetweenCleanups + " global lock timeout="
|
||||
+ _globalWorkLockTimeout);
|
||||
createThreadPools();
|
||||
|
||||
return true;
|
||||
@ -928,7 +924,7 @@ public class SecurityGroupManagerImpl extends ManagerBase implements SecurityGro
|
||||
Account accVO = _accountDao.findById(accountId);
|
||||
if (accVO != null) {
|
||||
return createSecurityGroup(SecurityGroupManager.DEFAULT_GROUP_NAME, SecurityGroupManager.DEFAULT_GROUP_DESCRIPTION, accVO.getDomainId(), accVO.getId(),
|
||||
accVO.getAccountName());
|
||||
accVO.getAccountName());
|
||||
}
|
||||
}
|
||||
return groupVO;
|
||||
@ -1002,8 +998,7 @@ public class SecurityGroupManagerImpl extends ManagerBase implements SecurityGro
|
||||
nicSecIps = _nicSecIpDao.getSecondaryIpAddressesForNic(nic.getId());
|
||||
}
|
||||
}
|
||||
SecurityGroupRulesCmd cmd =
|
||||
generateRulesetCmd(vm.getInstanceName(), vm.getPrivateIpAddress(), vm.getPrivateMacAddress(), vm.getId(),
|
||||
SecurityGroupRulesCmd cmd = generateRulesetCmd(vm.getInstanceName(), vm.getPrivateIpAddress(), vm.getPrivateMacAddress(), vm.getId(),
|
||||
generateRulesetSignature(ingressRules, egressRules), seqnum, ingressRules, egressRules, nicSecIps);
|
||||
Commands cmds = new Commands(cmd);
|
||||
try {
|
||||
@ -1053,8 +1048,8 @@ public class SecurityGroupManagerImpl extends ManagerBase implements SecurityGro
|
||||
SecurityGroupVO ngrpLock = _securityGroupDao.lockRow(securityGroup.getId(), false);
|
||||
if (ngrpLock == null) {
|
||||
s_logger.warn("Failed to acquire lock on network group id=" + securityGroup.getId() + " name=" + securityGroup.getName());
|
||||
throw new ConcurrentModificationException("Failed to acquire lock on network group id=" + securityGroup.getId() + " name=" +
|
||||
securityGroup.getName());
|
||||
throw new ConcurrentModificationException("Failed to acquire lock on network group id=" + securityGroup.getId() + " name="
|
||||
+ securityGroup.getName());
|
||||
}
|
||||
if (_securityGroupVMMapDao.findByVmIdGroupId(userVmId, securityGroup.getId()) == null) {
|
||||
SecurityGroupVMMapVO groupVmMapVO = new SecurityGroupVMMapVO(securityGroup.getId(), userVmId);
|
||||
@ -1334,17 +1329,22 @@ public class SecurityGroupManagerImpl extends ManagerBase implements SecurityGro
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean securityGroupRulesForVmSecIp(Long nicId, Long networkId, String secondaryIp, boolean ruleAction) {
|
||||
public boolean securityGroupRulesForVmSecIp(long nicId, String secondaryIp, boolean ruleAction) {
|
||||
Account caller = CallContext.current().getCallingAccount();
|
||||
|
||||
String vmMac = null;
|
||||
String vmName = null;
|
||||
|
||||
if (secondaryIp == null || nicId == null || networkId == null) {
|
||||
throw new InvalidParameterValueException("Vm nicId or networkId or secondaryIp can't be null");
|
||||
if (secondaryIp == null) {
|
||||
throw new InvalidParameterValueException("Vm secondaryIp can't be null");
|
||||
}
|
||||
|
||||
NicVO nic = _nicDao.findById(nicId);
|
||||
Long vmId = nic.getInstanceId();
|
||||
long vmId = nic.getInstanceId();
|
||||
UserVm vm = _userVMDao.findById(vmId);
|
||||
if (vm == null || vm.getType() != VirtualMachine.Type.User) {
|
||||
throw new InvalidParameterValueException("Can't configure the SG ipset, arprules rules for the non existing or non user vm");
|
||||
}
|
||||
|
||||
// Verify permissions
|
||||
_accountMgr.checkAccess(caller, null, false, vm);
|
||||
|
||||
// Validate parameters
|
||||
List<SecurityGroupVO> vmSgGrps = getSecurityGroupsForVm(vmId);
|
||||
@ -1353,28 +1353,17 @@ public class SecurityGroupManagerImpl extends ManagerBase implements SecurityGro
|
||||
return true;
|
||||
}
|
||||
|
||||
Account caller = CallContext.current().getCallingAccount();
|
||||
|
||||
for (SecurityGroupVO securityGroup : vmSgGrps) {
|
||||
Account owner = _accountMgr.getAccount(securityGroup.getAccountId());
|
||||
if (owner == null) {
|
||||
throw new InvalidParameterValueException("Unable to find security group owner by id=" + securityGroup.getAccountId());
|
||||
}
|
||||
// Verify permissions
|
||||
_accountMgr.checkAccess(caller, null, true, securityGroup);
|
||||
}
|
||||
|
||||
UserVm vm = _userVMDao.findById(vmId);
|
||||
if (vm.getType() != VirtualMachine.Type.User) {
|
||||
throw new InvalidParameterValueException("Can't configure the SG ipset, arprules rules for the non user vm");
|
||||
}
|
||||
|
||||
if (vm != null) {
|
||||
vmMac = vm.getPrivateMacAddress();
|
||||
vmName = vm.getInstanceName();
|
||||
if (vmMac == null || vmName == null) {
|
||||
throw new InvalidParameterValueException("vm name or vm mac can't be null");
|
||||
}
|
||||
String vmMac = vm.getPrivateMacAddress();
|
||||
String vmName = vm.getInstanceName();
|
||||
if (vmMac == null || vmName == null) {
|
||||
throw new InvalidParameterValueException("vm name or vm mac can't be null");
|
||||
}
|
||||
|
||||
//create command for the to add ip in ipset and arptables rules
|
||||
|
||||
@ -791,7 +791,7 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkOrches
|
||||
}
|
||||
|
||||
@Override
|
||||
public NicSecondaryIp allocateSecondaryGuestIP(Account account, long zoneId, Long nicId, Long networkId, String ipaddress) {
|
||||
public NicSecondaryIp allocateSecondaryGuestIP(long nicId, String ipaddress) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user