mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
Add New API endpoint: UpdateVlanIpRange (#5411)
* Added Logic to update the user_ip_address table * Edited ConfigurationManagerImpl * Refactor UpdateVlanIpRangeCmd location * Checkstyle corrections * Mock updateVlanAndPublicIpRange * Changes: - UpdateVlanIpRangeCmd - changed since to 4.15.0 - ConfigurationService - Updated Javadoc - ConfigurationManager - Updated Javadoc - Added Unit tests - Added license - Update server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java - fix some bugs in #5411 and add support for ipv6 and forsystemvms - fix #5411: disallow forsystemvms if ip range is dedicated - update #5411: ui changes - update #5411: support gateway/netmask change - update #5411: change to sync call and fix bugs Co-authored-by: kioie <kioieddy@google.com> Co-authored-by: kioie <kioi@outlook.com> Co-authored-by: dahn <daan.hoogland@gmail.com>
This commit is contained in:
parent
3b4523f22a
commit
747608f75f
@ -39,6 +39,7 @@ import org.apache.cloudstack.api.command.admin.vlan.CreateVlanIpRangeCmd;
|
||||
import org.apache.cloudstack.api.command.admin.vlan.DedicatePublicIpRangeCmd;
|
||||
import org.apache.cloudstack.api.command.admin.vlan.DeleteVlanIpRangeCmd;
|
||||
import org.apache.cloudstack.api.command.admin.vlan.ReleasePublicIpRangeCmd;
|
||||
import org.apache.cloudstack.api.command.admin.vlan.UpdateVlanIpRangeCmd;
|
||||
import org.apache.cloudstack.api.command.admin.zone.CreateZoneCmd;
|
||||
import org.apache.cloudstack.api.command.admin.zone.DeleteZoneCmd;
|
||||
import org.apache.cloudstack.api.command.admin.zone.UpdateZoneCmd;
|
||||
@ -272,6 +273,12 @@ public interface ConfigurationService {
|
||||
Vlan createVlanAndPublicIpRange(CreateVlanIpRangeCmd cmd) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException,
|
||||
ResourceAllocationException;
|
||||
|
||||
/**
|
||||
* Updates the IP address Range for the VLAN on the database
|
||||
* @return The Updated Vlan Object
|
||||
*/
|
||||
Vlan updateVlanAndPublicIpRange(UpdateVlanIpRangeCmd cmd) throws ConcurrentOperationException,
|
||||
ResourceUnavailableException, ResourceAllocationException;
|
||||
/**
|
||||
* Marks the the account with the default zone-id.
|
||||
*
|
||||
|
||||
@ -324,6 +324,7 @@ public class EventTypes {
|
||||
public static final String EVENT_VLAN_IP_RANGE_DELETE = "VLAN.IP.RANGE.DELETE";
|
||||
public static final String EVENT_VLAN_IP_RANGE_DEDICATE = "VLAN.IP.RANGE.DEDICATE";
|
||||
public static final String EVENT_VLAN_IP_RANGE_RELEASE = "VLAN.IP.RANGE.RELEASE";
|
||||
public static final String EVENT_VLAN_IP_RANGE_UPDATE = "VLAN.IP.RANGE.UPDATE";
|
||||
|
||||
public static final String EVENT_MANAGEMENT_IP_RANGE_CREATE = "MANAGEMENT.IP.RANGE.CREATE";
|
||||
public static final String EVENT_MANAGEMENT_IP_RANGE_DELETE = "MANAGEMENT.IP.RANGE.DELETE";
|
||||
|
||||
@ -0,0 +1,167 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
package org.apache.cloudstack.api.command.admin.vlan;
|
||||
|
||||
import org.apache.cloudstack.acl.RoleType;
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.ApiErrorCode;
|
||||
import org.apache.cloudstack.api.BaseCmd;
|
||||
import org.apache.cloudstack.api.Parameter;
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.apache.cloudstack.api.response.VlanIpRangeResponse;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.dc.Vlan;
|
||||
import com.cloud.exception.ConcurrentOperationException;
|
||||
import com.cloud.exception.ResourceAllocationException;
|
||||
import com.cloud.exception.ResourceUnavailableException;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.utils.net.NetUtils;
|
||||
|
||||
@APICommand(name = UpdateVlanIpRangeCmd.APINAME, description = "Updates a VLAN IP range.", responseObject =
|
||||
VlanIpRangeResponse.class, since = "4.16.0",
|
||||
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false,
|
||||
authorized = {RoleType.Admin})
|
||||
public class UpdateVlanIpRangeCmd extends BaseCmd {
|
||||
|
||||
public static final String APINAME = "updateVlanIpRange";
|
||||
public static final Logger s_logger = Logger.getLogger(UpdateVlanIpRangeCmd.class.getName());
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
//////////////// API parameters /////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = VlanIpRangeResponse.class, required = true,
|
||||
description = "the UUID of the VLAN IP range")
|
||||
private Long id;
|
||||
|
||||
@Parameter(name = ApiConstants.GATEWAY, type = CommandType.STRING, description = "the gateway of the VLAN IP range")
|
||||
private String gateway;
|
||||
|
||||
@Parameter(name = ApiConstants.NETMASK, type = CommandType.STRING, description = "the netmask of the VLAN IP range")
|
||||
private String netmask;
|
||||
|
||||
@Parameter(name = ApiConstants.START_IP, type = CommandType.STRING, description = "the beginning IP address in the VLAN IP range")
|
||||
private String startIp;
|
||||
|
||||
@Parameter(name = ApiConstants.END_IP, type = CommandType.STRING,
|
||||
description = "the ending IP address in the VLAN IP range")
|
||||
private String endIp;
|
||||
|
||||
@Parameter(name = ApiConstants.START_IPV6, type = CommandType.STRING, description = "the beginning IPv6 address in the IPv6 network range")
|
||||
private String startIpv6;
|
||||
|
||||
@Parameter(name = ApiConstants.END_IPV6, type = CommandType.STRING, description = "the ending IPv6 address in the IPv6 network range")
|
||||
private String endIpv6;
|
||||
|
||||
@Parameter(name = ApiConstants.IP6_GATEWAY, type = CommandType.STRING, description = "the gateway of the IPv6 network")
|
||||
private String ip6Gateway;
|
||||
|
||||
@Parameter(name = ApiConstants.IP6_CIDR, type = CommandType.STRING, description = "the CIDR of IPv6 network, must be at least /64")
|
||||
private String ip6Cidr;
|
||||
|
||||
@Parameter(name = ApiConstants.FOR_SYSTEM_VMS, type = CommandType.BOOLEAN, description = "true if IP range is set to system vms, false if not")
|
||||
private Boolean forSystemVms;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////////// Accessors ///////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getGateway() {
|
||||
return gateway;
|
||||
}
|
||||
|
||||
public String getEndIp() {
|
||||
return endIp;
|
||||
}
|
||||
|
||||
public String getNetmask() {
|
||||
return netmask;
|
||||
}
|
||||
|
||||
public String getStartIp() {
|
||||
return startIp;
|
||||
}
|
||||
|
||||
public String getStartIpv6() {
|
||||
if (startIpv6 == null) {
|
||||
return null;
|
||||
}
|
||||
return NetUtils.standardizeIp6Address(startIpv6);
|
||||
}
|
||||
|
||||
public String getEndIpv6() {
|
||||
if (endIpv6 == null) {
|
||||
return null;
|
||||
}
|
||||
return NetUtils.standardizeIp6Address(endIpv6);
|
||||
}
|
||||
|
||||
public String getIp6Gateway() {
|
||||
if (ip6Gateway == null) {
|
||||
return null;
|
||||
}
|
||||
return NetUtils.standardizeIp6Address(ip6Gateway);
|
||||
}
|
||||
|
||||
public String getIp6Cidr() {
|
||||
if (ip6Cidr == null) {
|
||||
return null;
|
||||
}
|
||||
return NetUtils.standardizeIp6Cidr(ip6Cidr);
|
||||
}
|
||||
|
||||
public Boolean isForSystemVms() {
|
||||
return forSystemVms;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////// API Implementation///////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public void execute() throws ResourceUnavailableException, ResourceAllocationException {
|
||||
try {
|
||||
Vlan result = _configService.updateVlanAndPublicIpRange(this);
|
||||
if (result != null) {
|
||||
VlanIpRangeResponse response = _responseGenerator.createVlanIpRangeResponse(result);
|
||||
response.setResponseName(getCommandName());
|
||||
this.setResponseObject(response);
|
||||
} else {
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to Update vlan ip range");
|
||||
}
|
||||
} catch (ConcurrentOperationException ex) {
|
||||
s_logger.warn("Exception: ", ex);
|
||||
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommandName() {
|
||||
return APINAME.toLowerCase() + BaseCmd.RESPONSE_SUFFIX;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getEntityOwnerId() {
|
||||
return Account.ACCOUNT_ID_SYSTEM;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,78 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
package org.apache.cloudstack.api.command.admin.vlan;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.cloudstack.api.ResponseGenerator;
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.apache.cloudstack.api.response.VlanIpRangeResponse;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import com.cloud.configuration.ConfigurationService;
|
||||
import com.cloud.dc.Vlan;
|
||||
import com.cloud.exception.ResourceAllocationException;
|
||||
import com.cloud.exception.ResourceUnavailableException;
|
||||
|
||||
public class UpdateVlanIpRangeCmdTest extends TestCase {
|
||||
|
||||
private UpdateVlanIpRangeCmd updateVlanIpRangeCmd;
|
||||
private ResponseGenerator responseGenerator;
|
||||
|
||||
@Test
|
||||
public void testUpdateSuccess() throws Exception {
|
||||
|
||||
ConfigurationService configService = Mockito.mock(ConfigurationService.class);
|
||||
Vlan result = Mockito.mock(Vlan.class);
|
||||
|
||||
responseGenerator = Mockito.mock(ResponseGenerator.class);
|
||||
updateVlanIpRangeCmd = new UpdateVlanIpRangeCmd();
|
||||
|
||||
Mockito.when(configService.updateVlanAndPublicIpRange(updateVlanIpRangeCmd)).thenReturn(result);
|
||||
updateVlanIpRangeCmd._configService = configService;
|
||||
|
||||
VlanIpRangeResponse ipRes = Mockito.mock(VlanIpRangeResponse.class);
|
||||
Mockito.when(responseGenerator.createVlanIpRangeResponse(result)).thenReturn(ipRes);
|
||||
|
||||
updateVlanIpRangeCmd._responseGenerator = responseGenerator;
|
||||
try {
|
||||
updateVlanIpRangeCmd.execute();
|
||||
} catch (ServerApiException ex) {
|
||||
assertEquals("Failed to Update vlan ip range", ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateFailure() throws ResourceAllocationException, ResourceUnavailableException {
|
||||
|
||||
ConfigurationService configService = Mockito.mock(ConfigurationService.class);
|
||||
|
||||
responseGenerator = Mockito.mock(ResponseGenerator.class);
|
||||
updateVlanIpRangeCmd = new UpdateVlanIpRangeCmd();
|
||||
updateVlanIpRangeCmd._configService = configService;
|
||||
|
||||
Mockito.when(configService.updateVlanAndPublicIpRange(updateVlanIpRangeCmd)).thenReturn(null);
|
||||
|
||||
try {
|
||||
updateVlanIpRangeCmd.execute();
|
||||
} catch (ServerApiException ex) {
|
||||
assertEquals("Failed to Update vlan ip range", ex.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -118,11 +118,19 @@ public class VlanVO implements Vlan {
|
||||
return vlanGateway;
|
||||
}
|
||||
|
||||
public void setVlanGateway(String vlanGateway) {
|
||||
this.vlanGateway = vlanGateway;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVlanNetmask() {
|
||||
return vlanNetmask;
|
||||
}
|
||||
|
||||
public void setVlanNetmask(String vlanNetmask) {
|
||||
this.vlanNetmask = vlanNetmask;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getDataCenterId() {
|
||||
return dataCenterId;
|
||||
@ -234,6 +242,6 @@ public class VlanVO implements Vlan {
|
||||
}
|
||||
|
||||
public void setIpRange(String ipRange) {
|
||||
this.ip6Range = ipRange;
|
||||
this.ipRange = ipRange;
|
||||
}
|
||||
}
|
||||
|
||||
@ -19,6 +19,7 @@ package com.cloud.network.dao;
|
||||
import java.util.List;
|
||||
|
||||
import com.cloud.dc.Vlan.VlanType;
|
||||
import com.cloud.network.IpAddress.State;
|
||||
import com.cloud.utils.db.GenericDao;
|
||||
import com.cloud.utils.net.Ip;
|
||||
|
||||
@ -32,6 +33,8 @@ public interface IPAddressDao extends GenericDao<IPAddressVO, Long> {
|
||||
|
||||
List<IPAddressVO> listByVlanId(long vlanId);
|
||||
|
||||
List<IPAddressVO> listByVlanIdAndState(long vlanId, State state);
|
||||
|
||||
List<IPAddressVO> listByDcIdIpAddress(long dcId, String ipAddress);
|
||||
|
||||
List<IPAddressVO> listByDcId(long dcId);
|
||||
|
||||
@ -78,6 +78,7 @@ public class IPAddressDaoImpl extends GenericDaoBase<IPAddressVO, Long> implemen
|
||||
AllFieldsSearch.and("dataCenterId", AllFieldsSearch.entity().getDataCenterId(), Op.EQ);
|
||||
AllFieldsSearch.and("ipAddress", AllFieldsSearch.entity().getAddress(), Op.EQ);
|
||||
AllFieldsSearch.and("vlan", AllFieldsSearch.entity().getVlanId(), Op.EQ);
|
||||
AllFieldsSearch.and("state", AllFieldsSearch.entity().getState(), Op.EQ);
|
||||
AllFieldsSearch.and("accountId", AllFieldsSearch.entity().getAllocatedToAccountId(), Op.EQ);
|
||||
AllFieldsSearch.and("sourceNat", AllFieldsSearch.entity().isSourceNat(), Op.EQ);
|
||||
AllFieldsSearch.and("network", AllFieldsSearch.entity().getAssociatedWithNetworkId(), Op.EQ);
|
||||
@ -471,4 +472,12 @@ public class IPAddressDaoImpl extends GenericDaoBase<IPAddressVO, Long> implemen
|
||||
sc.setParameters("vlan", vlandbId);
|
||||
lockRows(sc, null, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<IPAddressVO> listByVlanIdAndState(long vlanId, State state) {
|
||||
SearchCriteria<IPAddressVO> sc = AllFieldsSearch.create();
|
||||
sc.setParameters("vlan", vlanId);
|
||||
sc.setParameters("state", state);
|
||||
return listBy(sc);
|
||||
}
|
||||
}
|
||||
|
||||
@ -18,6 +18,7 @@ package com.cloud.network.dao;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.cloud.network.IpAddress;
|
||||
import com.cloud.network.UserIpv6AddressVO;
|
||||
import com.cloud.utils.db.GenericDao;
|
||||
|
||||
@ -26,6 +27,8 @@ public interface UserIpv6AddressDao extends GenericDao<UserIpv6AddressVO, Long>
|
||||
|
||||
List<UserIpv6AddressVO> listByVlanId(long vlanId);
|
||||
|
||||
List<UserIpv6AddressVO> listByVlanIdAndState(long vlanId, IpAddress.State state);
|
||||
|
||||
List<UserIpv6AddressVO> listByDcId(long dcId);
|
||||
|
||||
List<UserIpv6AddressVO> listByNetwork(long networkId);
|
||||
|
||||
@ -19,6 +19,7 @@ package com.cloud.network.dao;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
import com.cloud.network.IpAddress;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@ -43,6 +44,7 @@ public class UserIpv6AddressDaoImpl extends GenericDaoBase<UserIpv6AddressVO, Lo
|
||||
AllFieldsSearch.and("dataCenterId", AllFieldsSearch.entity().getDataCenterId(), Op.EQ);
|
||||
AllFieldsSearch.and("ipAddress", AllFieldsSearch.entity().getAddress(), Op.EQ);
|
||||
AllFieldsSearch.and("vlan", AllFieldsSearch.entity().getVlanId(), Op.EQ);
|
||||
AllFieldsSearch.and("state", AllFieldsSearch.entity().getState(), Op.EQ);
|
||||
AllFieldsSearch.and("accountId", AllFieldsSearch.entity().getAccountId(), Op.EQ);
|
||||
AllFieldsSearch.and("network", AllFieldsSearch.entity().getNetworkId(), Op.EQ);
|
||||
AllFieldsSearch.and("physicalNetworkId", AllFieldsSearch.entity().getPhysicalNetworkId(), Op.EQ);
|
||||
@ -69,6 +71,14 @@ public class UserIpv6AddressDaoImpl extends GenericDaoBase<UserIpv6AddressVO, Lo
|
||||
return listBy(sc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserIpv6AddressVO> listByVlanIdAndState(long vlanId, IpAddress.State state) {
|
||||
SearchCriteria<UserIpv6AddressVO> sc = AllFieldsSearch.create();
|
||||
sc.setParameters("vlan", vlanId);
|
||||
sc.setParameters("state", state);
|
||||
return listBy(sc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserIpv6AddressVO> listByDcId(long dcId) {
|
||||
SearchCriteria<UserIpv6AddressVO> sc = AllFieldsSearch.create();
|
||||
|
||||
@ -26,6 +26,7 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
@ -35,10 +36,12 @@ import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.Vector;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import com.googlecode.ipv6.IPv6Address;
|
||||
import org.apache.cloudstack.acl.SecurityChecker;
|
||||
import org.apache.cloudstack.affinity.AffinityGroup;
|
||||
import org.apache.cloudstack.affinity.AffinityGroupService;
|
||||
@ -69,6 +72,7 @@ import org.apache.cloudstack.api.command.admin.vlan.CreateVlanIpRangeCmd;
|
||||
import org.apache.cloudstack.api.command.admin.vlan.DedicatePublicIpRangeCmd;
|
||||
import org.apache.cloudstack.api.command.admin.vlan.DeleteVlanIpRangeCmd;
|
||||
import org.apache.cloudstack.api.command.admin.vlan.ReleasePublicIpRangeCmd;
|
||||
import org.apache.cloudstack.api.command.admin.vlan.UpdateVlanIpRangeCmd;
|
||||
import org.apache.cloudstack.api.command.admin.zone.CreateZoneCmd;
|
||||
import org.apache.cloudstack.api.command.admin.zone.DeleteZoneCmd;
|
||||
import org.apache.cloudstack.api.command.admin.zone.UpdateZoneCmd;
|
||||
@ -167,6 +171,7 @@ import com.cloud.host.HostVO;
|
||||
import com.cloud.host.dao.HostDao;
|
||||
import com.cloud.host.dao.HostTagsDao;
|
||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||
import com.cloud.network.IpAddress;
|
||||
import com.cloud.network.IpAddressManager;
|
||||
import com.cloud.network.Network;
|
||||
import com.cloud.network.Network.Capability;
|
||||
@ -178,6 +183,7 @@ import com.cloud.network.NetworkService;
|
||||
import com.cloud.network.Networks.BroadcastDomainType;
|
||||
import com.cloud.network.Networks.TrafficType;
|
||||
import com.cloud.network.PhysicalNetwork;
|
||||
import com.cloud.network.UserIpv6AddressVO;
|
||||
import com.cloud.network.dao.FirewallRulesDao;
|
||||
import com.cloud.network.dao.IPAddressDao;
|
||||
import com.cloud.network.dao.IPAddressVO;
|
||||
@ -187,6 +193,7 @@ import com.cloud.network.dao.PhysicalNetworkDao;
|
||||
import com.cloud.network.dao.PhysicalNetworkTrafficTypeDao;
|
||||
import com.cloud.network.dao.PhysicalNetworkTrafficTypeVO;
|
||||
import com.cloud.network.dao.PhysicalNetworkVO;
|
||||
import com.cloud.network.dao.UserIpv6AddressDao;
|
||||
import com.cloud.network.rules.LoadBalancerContainer.Scheme;
|
||||
import com.cloud.network.vpc.VpcManager;
|
||||
import com.cloud.offering.DiskOffering;
|
||||
@ -403,7 +410,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
||||
StoragePoolTagsDao storagePoolTagDao;
|
||||
@Inject
|
||||
private AnnotationDao annotationDao;
|
||||
|
||||
@Inject
|
||||
UserIpv6AddressDao _ipv6Dao;
|
||||
|
||||
// FIXME - why don't we have interface for DataCenterLinkLocalIpAddressDao?
|
||||
@Inject
|
||||
@ -4239,6 +4247,260 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vlan updateVlanAndPublicIpRange(UpdateVlanIpRangeCmd cmd) throws ConcurrentOperationException,
|
||||
ResourceUnavailableException,ResourceAllocationException {
|
||||
|
||||
return updateVlanAndPublicIpRange(cmd.getId(), cmd.getStartIp(),cmd.getEndIp(), cmd.getGateway(),cmd.getNetmask(),
|
||||
cmd.getStartIpv6(), cmd.getEndIpv6(), cmd.getIp6Gateway(), cmd.getIp6Cidr(), cmd.isForSystemVms());
|
||||
}
|
||||
|
||||
@DB
|
||||
@ActionEvent(eventType = EventTypes.EVENT_VLAN_IP_RANGE_UPDATE, eventDescription = "update vlan ip Range", async
|
||||
= false)
|
||||
public Vlan updateVlanAndPublicIpRange(final long id, String startIp,
|
||||
String endIp,
|
||||
String gateway,
|
||||
String netmask,
|
||||
String startIpv6,
|
||||
String endIpv6,
|
||||
String ip6Gateway,
|
||||
String ip6Cidr,
|
||||
Boolean forSystemVms) throws ConcurrentOperationException {
|
||||
|
||||
VlanVO vlanRange = _vlanDao.findById(id);
|
||||
if (vlanRange == null) {
|
||||
throw new InvalidParameterValueException("Please specify a valid IP range id.");
|
||||
}
|
||||
|
||||
final boolean ipv4 = vlanRange.getVlanGateway() != null;
|
||||
final boolean ipv6 = vlanRange.getIp6Gateway() != null;
|
||||
if (!ipv4) {
|
||||
if (startIp != null || endIp != null || gateway != null || netmask != null) {
|
||||
throw new InvalidParameterValueException("IPv4 is not support in this IP range.");
|
||||
}
|
||||
}
|
||||
if (!ipv6) {
|
||||
if (startIpv6 != null || endIpv6 != null || ip6Gateway != null || ip6Cidr != null) {
|
||||
throw new InvalidParameterValueException("IPv6 is not support in this IP range.");
|
||||
}
|
||||
}
|
||||
|
||||
final Boolean isRangeForSystemVM = checkIfVlanRangeIsForSystemVM(id);
|
||||
if (forSystemVms != null && isRangeForSystemVM != forSystemVms) {
|
||||
if (VlanType.DirectAttached.equals(vlanRange.getVlanType())) {
|
||||
throw new InvalidParameterValueException("forSystemVms is not available for this IP range with vlan type: " + VlanType.DirectAttached);
|
||||
}
|
||||
// Check if range has already been dedicated
|
||||
final List<AccountVlanMapVO> maps = _accountVlanMapDao.listAccountVlanMapsByVlan(id);
|
||||
if (maps != null && !maps.isEmpty()) {
|
||||
throw new InvalidParameterValueException("Specified Public IP range has already been dedicated to an account");
|
||||
}
|
||||
|
||||
List<DomainVlanMapVO> domainmaps = _domainVlanMapDao.listDomainVlanMapsByVlan(id);
|
||||
if (domainmaps != null && !domainmaps.isEmpty()) {
|
||||
throw new InvalidParameterValueException("Specified Public IP range has already been dedicated to a domain");
|
||||
}
|
||||
}
|
||||
if (ipv4) {
|
||||
updateVlanAndIpv4Range(id, vlanRange, startIp, endIp, gateway, netmask, isRangeForSystemVM, forSystemVms);
|
||||
}
|
||||
if (ipv6) {
|
||||
updateVlanAndIpv6Range(id, vlanRange, startIpv6, endIpv6, ip6Gateway, ip6Cidr, isRangeForSystemVM, forSystemVms);
|
||||
}
|
||||
return _vlanDao.findById(id);
|
||||
}
|
||||
|
||||
private void updateVlanAndIpv4Range(final long id, final VlanVO vlanRange,
|
||||
String startIp,
|
||||
String endIp,
|
||||
String gateway,
|
||||
String netmask,
|
||||
final Boolean isRangeForSystemVM,
|
||||
final Boolean forSystemVms) {
|
||||
final List<IPAddressVO> listAllocatedIPs = _publicIpAddressDao.listByVlanIdAndState(id, IpAddress.State.Allocated);
|
||||
|
||||
if (gateway != null && !gateway.equals(vlanRange.getVlanGateway()) && CollectionUtils.isNotEmpty(listAllocatedIPs)) {
|
||||
throw new InvalidParameterValueException(String.format("Unable to change gateway to %s because some IPs are in use", gateway));
|
||||
}
|
||||
if (netmask != null && !netmask.equals(vlanRange.getVlanNetmask()) && CollectionUtils.isNotEmpty(listAllocatedIPs)) {
|
||||
throw new InvalidParameterValueException(String.format("Unable to change netmask to %s because some IPs are in use", netmask));
|
||||
}
|
||||
|
||||
gateway = MoreObjects.firstNonNull(gateway, vlanRange.getVlanGateway());
|
||||
netmask = MoreObjects.firstNonNull(netmask, vlanRange.getVlanNetmask());
|
||||
|
||||
final String[] existingVlanIPRangeArray = vlanRange.getIpRange().split("-");
|
||||
final String currentStartIP = existingVlanIPRangeArray[0];
|
||||
final String currentEndIP = existingVlanIPRangeArray[1];
|
||||
|
||||
startIp = MoreObjects.firstNonNull(startIp, currentStartIP);
|
||||
endIp = MoreObjects.firstNonNull(endIp, currentEndIP);
|
||||
|
||||
final String cidr = NetUtils.ipAndNetMaskToCidr(gateway, netmask);
|
||||
if (Strings.isNullOrEmpty(cidr)) {
|
||||
throw new InvalidParameterValueException(String.format("Invalid gateway (%s) or netmask (%s)", gateway, netmask));
|
||||
}
|
||||
final String cidrAddress = getCidrAddress(cidr);
|
||||
final long cidrSize = getCidrSize(cidr);
|
||||
|
||||
checkIpRange(startIp, endIp, cidrAddress, cidrSize);
|
||||
|
||||
checkGatewayOverlap(startIp, endIp, gateway);
|
||||
|
||||
checkAllocatedIpsAreWithinVlanRange(listAllocatedIPs, startIp, endIp, forSystemVms);
|
||||
|
||||
try {
|
||||
final String newStartIP = startIp;
|
||||
final String newEndIP = endIp;
|
||||
|
||||
VlanVO range = _vlanDao.acquireInLockTable(id, 30);
|
||||
if (range == null) {
|
||||
throw new CloudRuntimeException("Unable to acquire vlan configuration: " + id);
|
||||
}
|
||||
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("lock vlan " + id + " is acquired");
|
||||
}
|
||||
|
||||
commitUpdateVlanAndIpRange(id, newStartIP, newEndIP, currentStartIP, currentEndIP, gateway, netmask,true, isRangeForSystemVM, forSystemVms);
|
||||
|
||||
} catch (final Exception e) {
|
||||
s_logger.error("Unable to edit VlanRange due to " + e.getMessage(), e);
|
||||
throw new CloudRuntimeException("Failed to edit VlanRange. Please contact Cloud Support.");
|
||||
} finally {
|
||||
_vlanDao.releaseFromLockTable(id);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateVlanAndIpv6Range(final long id, final VlanVO vlanRange,
|
||||
String startIpv6,
|
||||
String endIpv6,
|
||||
String ip6Gateway,
|
||||
String ip6Cidr,
|
||||
final Boolean isRangeForSystemVM,
|
||||
final Boolean forSystemVms) {
|
||||
final List<UserIpv6AddressVO> listAllocatedIPs = _ipv6Dao.listByVlanIdAndState(id, IpAddress.State.Allocated);
|
||||
|
||||
if (ip6Gateway != null && !ip6Gateway.equals(vlanRange.getIp6Gateway()) && CollectionUtils.isNotEmpty(listAllocatedIPs)) {
|
||||
throw new InvalidParameterValueException(String.format("Unable to change ipv6 gateway to %s because some IPs are in use", ip6Gateway));
|
||||
}
|
||||
if (ip6Cidr != null && !ip6Cidr.equals(vlanRange.getIp6Cidr()) && CollectionUtils.isNotEmpty(listAllocatedIPs)) {
|
||||
throw new InvalidParameterValueException(String.format("Unable to change ipv6 cidr to %s because some IPs are in use", ip6Cidr));
|
||||
}
|
||||
ip6Gateway = MoreObjects.firstNonNull(ip6Gateway, vlanRange.getIp6Gateway());
|
||||
ip6Cidr = MoreObjects.firstNonNull(ip6Cidr, vlanRange.getIp6Cidr());
|
||||
|
||||
final String[] existingVlanIPRangeArray = vlanRange.getIp6Range().split("-");
|
||||
final String currentStartIPv6 = existingVlanIPRangeArray[0];
|
||||
final String currentEndIPv6 = existingVlanIPRangeArray[1];
|
||||
|
||||
startIpv6 = MoreObjects.firstNonNull(startIpv6, currentStartIPv6);
|
||||
endIpv6 = MoreObjects.firstNonNull(endIpv6, currentEndIPv6);
|
||||
|
||||
if (startIpv6 != currentStartIPv6 || endIpv6 != currentEndIPv6) {
|
||||
_networkModel.checkIp6Parameters(startIpv6, endIpv6, ip6Gateway, ip6Cidr);
|
||||
checkAllocatedIpv6sAreWithinVlanRange(listAllocatedIPs, startIpv6, endIpv6);
|
||||
|
||||
try {
|
||||
VlanVO range = _vlanDao.acquireInLockTable(id, 30);
|
||||
if (range == null) {
|
||||
throw new CloudRuntimeException("Unable to acquire vlan configuration: " + id);
|
||||
}
|
||||
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("lock vlan " + id + " is acquired");
|
||||
}
|
||||
|
||||
commitUpdateVlanAndIpRange(id, startIpv6, endIpv6, currentStartIPv6, currentEndIPv6, ip6Gateway, ip6Cidr, false, isRangeForSystemVM,forSystemVms);
|
||||
|
||||
} catch (final Exception e) {
|
||||
s_logger.error("Unable to edit VlanRange due to " + e.getMessage(), e);
|
||||
throw new CloudRuntimeException("Failed to edit VlanRange. Please contact Cloud Support.");
|
||||
} finally {
|
||||
_vlanDao.releaseFromLockTable(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private VlanVO commitUpdateVlanAndIpRange(final Long id, final String newStartIP, final String newEndIP, final String currentStartIP, final String currentEndIP,
|
||||
final String gateway, final String netmask,
|
||||
final boolean ipv4, final Boolean isRangeForSystemVM, final Boolean forSystemvms) {
|
||||
|
||||
return Transaction.execute(new TransactionCallback<VlanVO>() {
|
||||
@Override
|
||||
public VlanVO doInTransaction(final TransactionStatus status) {
|
||||
VlanVO vlanRange = _vlanDao.findById(id);
|
||||
s_logger.debug("Updating vlan range " + vlanRange.getId());
|
||||
if (ipv4) {
|
||||
vlanRange.setIpRange(newStartIP + "-" + newEndIP);
|
||||
vlanRange.setVlanGateway(gateway);
|
||||
vlanRange.setVlanNetmask(netmask);
|
||||
_vlanDao.update(vlanRange.getId(), vlanRange);
|
||||
if (!updatePublicIPRange(newStartIP, currentStartIP, newEndIP, currentEndIP, vlanRange.getDataCenterId(), vlanRange.getId(), vlanRange.getNetworkId(), vlanRange.getPhysicalNetworkId(), isRangeForSystemVM, forSystemvms)) {
|
||||
throw new CloudRuntimeException("Failed to update IPv4 range. Please contact Cloud Support.");
|
||||
}
|
||||
} else {
|
||||
vlanRange.setIp6Range(newStartIP + "-" + newEndIP);
|
||||
vlanRange.setIp6Gateway(gateway);
|
||||
vlanRange.setIp6Cidr(netmask);
|
||||
_vlanDao.update(vlanRange.getId(), vlanRange);
|
||||
}
|
||||
return vlanRange;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private boolean checkIfVlanRangeIsForSystemVM(final long vlanId) {
|
||||
List<IPAddressVO> existingPublicIPs = _publicIpAddressDao.listByVlanId(vlanId);
|
||||
boolean initialIsSystemVmValue = existingPublicIPs.get(0).isForSystemVms();
|
||||
for (IPAddressVO existingIPs : existingPublicIPs) {
|
||||
if (initialIsSystemVmValue != existingIPs.isForSystemVms()) {
|
||||
throw new CloudRuntimeException("Your \"For System VM\" value seems to be inconsistent with the rest of the records. Please contact Cloud Support");
|
||||
}
|
||||
}
|
||||
return initialIsSystemVmValue;
|
||||
}
|
||||
|
||||
private void checkAllocatedIpsAreWithinVlanRange
|
||||
(List<IPAddressVO> listAllocatedIPs, String startIp, String endIp, Boolean forSystemVms) {
|
||||
Collections.sort(listAllocatedIPs, Comparator.comparing(IPAddressVO::getAddress));
|
||||
for (IPAddressVO allocatedIP : listAllocatedIPs) {
|
||||
if ((!Strings.isNullOrEmpty(startIp) && NetUtils.ip2Long(startIp) > NetUtils.ip2Long(allocatedIP.getAddress().addr()))
|
||||
|| (!Strings.isNullOrEmpty(endIp) && NetUtils.ip2Long(endIp) < NetUtils.ip2Long(allocatedIP.getAddress().addr()))) {
|
||||
throw new InvalidParameterValueException(String.format("The start IP address must be less than or equal to %s which is already in use. "
|
||||
+ "The end IP address must be greater than or equal to %s which is already in use. "
|
||||
+ "There are %d IPs already allocated in this range.",
|
||||
listAllocatedIPs.get(0).getAddress(), listAllocatedIPs.get(listAllocatedIPs.size() - 1).getAddress(), listAllocatedIPs.size()));
|
||||
}
|
||||
if (forSystemVms != null && allocatedIP.isForSystemVms() != forSystemVms) {
|
||||
throw new InvalidParameterValueException(String.format("IP %s is in use, cannot change forSystemVms of the IP range", allocatedIP.getAddress().addr()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void checkAllocatedIpv6sAreWithinVlanRange(List<UserIpv6AddressVO> listAllocatedIPs, String startIpv6, String endIpv6) {
|
||||
Collections.sort(listAllocatedIPs, Comparator.comparing(UserIpv6AddressVO::getAddress));
|
||||
for (UserIpv6AddressVO allocatedIP : listAllocatedIPs) {
|
||||
if ((!Strings.isNullOrEmpty(startIpv6)
|
||||
&& IPv6Address.fromString(startIpv6).toBigInteger().compareTo(IPv6Address.fromString(allocatedIP.getAddress()).toBigInteger()) > 0)
|
||||
|| (!Strings.isNullOrEmpty(endIpv6)
|
||||
&& IPv6Address.fromString(endIpv6).toBigInteger().compareTo(IPv6Address.fromString(allocatedIP.getAddress()).toBigInteger()) < 0)) {
|
||||
throw new InvalidParameterValueException(String.format("The start IPv6 address must be less than or equal to %s which is already in use. "
|
||||
+ "The end IPv6 address must be greater than or equal to %s which is already in use. "
|
||||
+ "There are %d IPv6 addresses already allocated in this range.",
|
||||
listAllocatedIPs.get(0).getAddress(), listAllocatedIPs.get(listAllocatedIPs.size() - 1).getAddress(), listAllocatedIPs.size()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void checkGatewayOverlap(String startIp, String endIp, String gateway) {
|
||||
if (NetUtils.ipRangesOverlap(startIp, endIp, gateway, gateway)) {
|
||||
throw new InvalidParameterValueException("The gateway shouldn't overlap the new start/end ip "
|
||||
+ "addresses");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@DB
|
||||
public boolean deleteVlanAndPublicIpRange(final long userId, final long vlanDbId, final Account caller) {
|
||||
@ -4292,7 +4554,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
||||
throw new InvalidParameterValueException("Can't delete account specific vlan " + vlanDbId + " as ip " + ip
|
||||
+ " belonging to the range has firewall rules applied. Cleanup the rules first");
|
||||
}
|
||||
if (ip.getAllocatedTime() != null) {// This means IP is allocated
|
||||
if (ip.getAllocatedTime() != null) {
|
||||
// This means IP is allocated
|
||||
// release public ip address here
|
||||
success = _ipAddrMgr.disassociatePublicIpAddress(ip.getId(), userId, caller);
|
||||
}
|
||||
@ -4568,6 +4831,59 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
||||
}
|
||||
});
|
||||
|
||||
return CollectionUtils.isEmpty(problemIps);
|
||||
}
|
||||
|
||||
@DB
|
||||
protected boolean updatePublicIPRange(final String newStartIP, final String currentStartIP, final String newEndIP, final String currentEndIP, final long zoneId, final long vlanDbId, final long sourceNetworkid, final long physicalNetworkId, final boolean isRangeForSystemVM, final Boolean forSystemVms) {
|
||||
long newStartIPLong = NetUtils.ip2Long(newStartIP);
|
||||
long newEndIPLong = NetUtils.ip2Long(newEndIP);
|
||||
long currentStartIPLong = NetUtils.ip2Long(currentStartIP);
|
||||
long currentEndIPLong = NetUtils.ip2Long(currentEndIP);
|
||||
|
||||
List<Long> currentIPRange = new ArrayList<>();
|
||||
List<Long> newIPRange = new ArrayList<>();
|
||||
while (newStartIPLong <= newEndIPLong) {
|
||||
newIPRange.add(newStartIPLong);
|
||||
newStartIPLong++;
|
||||
}
|
||||
while (currentStartIPLong <= currentEndIPLong) {
|
||||
currentIPRange.add(currentStartIPLong);
|
||||
currentStartIPLong++;
|
||||
}
|
||||
|
||||
final List<String> problemIps = Transaction.execute(new TransactionCallback<List<String>>() {
|
||||
|
||||
@Override
|
||||
public List<String> doInTransaction(final TransactionStatus status) {
|
||||
final IPRangeConfig config = new IPRangeConfig();
|
||||
Vector<String> configResult = new Vector<>();
|
||||
List<Long> ipAddressesToAdd = new ArrayList(newIPRange);
|
||||
ipAddressesToAdd.removeAll(currentIPRange);
|
||||
if (ipAddressesToAdd.size() > 0) {
|
||||
for (Long startIP : ipAddressesToAdd) {
|
||||
configResult.addAll(config.savePublicIPRange(TransactionLegacy.currentTxn(), startIP, startIP, zoneId, vlanDbId, sourceNetworkid, physicalNetworkId, forSystemVms != null ? forSystemVms : isRangeForSystemVM));
|
||||
}
|
||||
}
|
||||
List<Long> ipAddressesToDelete = new ArrayList(currentIPRange);
|
||||
ipAddressesToDelete.removeAll(newIPRange);
|
||||
if (ipAddressesToDelete.size() > 0) {
|
||||
for (Long startIP : ipAddressesToDelete) {
|
||||
configResult.addAll(config.deletePublicIPRange(TransactionLegacy.currentTxn(), startIP, startIP, vlanDbId));
|
||||
}
|
||||
}
|
||||
if (forSystemVms != null && isRangeForSystemVM != forSystemVms) {
|
||||
List<Long> ipAddressesToUpdate = new ArrayList(currentIPRange);
|
||||
ipAddressesToUpdate.removeAll(ipAddressesToDelete);
|
||||
if (ipAddressesToUpdate.size() > 0) {
|
||||
for (Long startIP : ipAddressesToUpdate) {
|
||||
configResult.addAll(config.updatePublicIPRange(TransactionLegacy.currentTxn(), startIP, startIP, vlanDbId, forSystemVms));
|
||||
}
|
||||
}
|
||||
}
|
||||
return configResult;
|
||||
}
|
||||
});
|
||||
return problemIps != null && problemIps.size() == 0;
|
||||
}
|
||||
|
||||
|
||||
@ -262,6 +262,7 @@ import org.apache.cloudstack.api.command.admin.vlan.DedicatePublicIpRangeCmd;
|
||||
import org.apache.cloudstack.api.command.admin.vlan.DeleteVlanIpRangeCmd;
|
||||
import org.apache.cloudstack.api.command.admin.vlan.ListVlanIpRangesCmd;
|
||||
import org.apache.cloudstack.api.command.admin.vlan.ReleasePublicIpRangeCmd;
|
||||
import org.apache.cloudstack.api.command.admin.vlan.UpdateVlanIpRangeCmd;
|
||||
import org.apache.cloudstack.api.command.admin.vm.AddNicToVMCmdByAdmin;
|
||||
import org.apache.cloudstack.api.command.admin.vm.AssignVMCmd;
|
||||
import org.apache.cloudstack.api.command.admin.vm.DeployVMCmdByAdmin;
|
||||
@ -3105,6 +3106,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
|
||||
cmdList.add(RegisterCmd.class);
|
||||
cmdList.add(UpdateUserCmd.class);
|
||||
cmdList.add(CreateVlanIpRangeCmd.class);
|
||||
cmdList.add(UpdateVlanIpRangeCmd.class);
|
||||
cmdList.add(DeleteVlanIpRangeCmd.class);
|
||||
cmdList.add(ListVlanIpRangesCmd.class);
|
||||
cmdList.add(DedicatePublicIpRangeCmd.class);
|
||||
|
||||
@ -313,9 +313,8 @@ public class IPRangeConfig {
|
||||
return problemIPs;
|
||||
}
|
||||
|
||||
private Vector<String> deletePublicIPRange(TransactionLegacy txn, long startIP, long endIP, long vlanDbId) {
|
||||
String deleteSql = "DELETE FROM `cloud`.`user_ip_address` WHERE public_ip_address = ? AND vlan_id = ?";
|
||||
String isPublicIPAllocatedSelectSql = "SELECT * FROM `cloud`.`user_ip_address` WHERE public_ip_address = ? AND vlan_id = ?";
|
||||
public Vector<String> updatePublicIPRange(TransactionLegacy txn, long startIP, long endIP, long vlanDbId, boolean forSystemvms) {
|
||||
String updateSql = "UPDATE `cloud`.`user_ip_address` SET forsystemvms = ? WHERE public_ip_address = ? AND vlan_db_id = ?";
|
||||
|
||||
Vector<String> problemIPs = new Vector<String>();
|
||||
Connection conn = null;
|
||||
@ -323,25 +322,55 @@ public class IPRangeConfig {
|
||||
conn = txn.getConnection();
|
||||
}
|
||||
catch (SQLException e) {
|
||||
System.out.println("deletePublicIPRange. Exception: " +e.getMessage());
|
||||
System.out.println("updatePublicIPRange. Exception: " + e.getMessage());
|
||||
return null;
|
||||
}
|
||||
try(PreparedStatement stmt = conn.prepareStatement(deleteSql);
|
||||
try (PreparedStatement stmt = conn.prepareStatement(updateSql);) {
|
||||
while (startIP <= endIP) {
|
||||
stmt.clearParameters();
|
||||
stmt.setBoolean(1, forSystemvms);
|
||||
stmt.setString(2, NetUtils.long2Ip(startIP));
|
||||
stmt.setLong(3, vlanDbId);
|
||||
stmt.executeUpdate();
|
||||
startIP += 1;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
System.out.println("updatePublicIPRange. Exception: " + ex.getMessage());
|
||||
return null;
|
||||
}
|
||||
|
||||
return problemIPs;
|
||||
}
|
||||
|
||||
public Vector<String> deletePublicIPRange(TransactionLegacy txn, long startIP, long endIP, long vlanDbId) {
|
||||
String deleteSql = "DELETE FROM `cloud`.`user_ip_address` WHERE public_ip_address = ? AND vlan_db_id = ?";
|
||||
String isPublicIPAllocatedSelectSql = "SELECT * FROM `cloud`.`user_ip_address` WHERE public_ip_address = ? AND vlan_db_id = ?";
|
||||
|
||||
Vector<String> problemIPs = new Vector<String>();
|
||||
Connection conn = null;
|
||||
try {
|
||||
conn = txn.getConnection();
|
||||
}
|
||||
catch (SQLException e) {
|
||||
System.out.println("deletePublicIPRange. Exception: " + e.getMessage());
|
||||
return null;
|
||||
}
|
||||
try (PreparedStatement stmt = conn.prepareStatement(deleteSql);
|
||||
PreparedStatement isAllocatedStmt = conn.prepareStatement(isPublicIPAllocatedSelectSql);) {
|
||||
while (startIP <= endIP) {
|
||||
if (!isPublicIPAllocated(startIP, vlanDbId, isAllocatedStmt)) {
|
||||
if (!isPublicIPAllocated(NetUtils.long2Ip(startIP), vlanDbId, isAllocatedStmt)) {
|
||||
stmt.clearParameters();
|
||||
stmt.setLong(1, startIP);
|
||||
stmt.setString(1, NetUtils.long2Ip(startIP));
|
||||
stmt.setLong(2, vlanDbId);
|
||||
stmt.executeUpdate();
|
||||
}
|
||||
}
|
||||
else {
|
||||
problemIPs.add(NetUtils.long2Ip(startIP));
|
||||
}
|
||||
startIP += 1;
|
||||
}
|
||||
}catch (Exception ex) {
|
||||
System.out.println("deletePublicIPRange. Exception: " +ex.getMessage());
|
||||
} catch (Exception ex) {
|
||||
System.out.println("deletePublicIPRange. Exception: " + ex.getMessage());
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -372,28 +401,33 @@ public class IPRangeConfig {
|
||||
System.out.println("deletePrivateIPRange. Exception: " + e.getMessage());
|
||||
printError("deletePrivateIPRange. Exception: " + e.getMessage());
|
||||
}
|
||||
}catch (SQLException e) {
|
||||
} catch (SQLException e) {
|
||||
System.out.println("deletePrivateIPRange. Exception: " + e.getMessage());
|
||||
printError("deletePrivateIPRange. Exception: " + e.getMessage());
|
||||
}
|
||||
return problemIPs;
|
||||
}
|
||||
|
||||
private boolean isPublicIPAllocated(long ip, long vlanDbId, PreparedStatement stmt) {
|
||||
try(ResultSet rs = stmt.executeQuery();) {
|
||||
stmt.clearParameters();
|
||||
stmt.setLong(1, ip);
|
||||
stmt.setLong(2, vlanDbId);
|
||||
if (rs.next()) {
|
||||
return (rs.getString("allocated") != null);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (SQLException ex) {
|
||||
System.out.println(ex.getMessage());
|
||||
return true;
|
||||
}
|
||||
private boolean isPublicIPAllocated(String ip, long vlanDbId, PreparedStatement stmt) {
|
||||
try {
|
||||
stmt.clearParameters();
|
||||
stmt.setString(1, ip);
|
||||
stmt.setLong(2, vlanDbId);
|
||||
try (ResultSet rs = stmt.executeQuery()) {
|
||||
if (rs.next()) {
|
||||
return (rs.getString("allocated") != null);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (SQLException ex) {
|
||||
System.out.println(ex.getMessage());
|
||||
return true;
|
||||
}
|
||||
} catch (SQLException ex) {
|
||||
System.out.println(ex.getMessage());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isPrivateIPAllocated(String ip, long podId, long zoneId, PreparedStatement stmt) {
|
||||
|
||||
@ -44,6 +44,7 @@ import org.apache.cloudstack.api.command.admin.vlan.CreateVlanIpRangeCmd;
|
||||
import org.apache.cloudstack.api.command.admin.vlan.DedicatePublicIpRangeCmd;
|
||||
import org.apache.cloudstack.api.command.admin.vlan.DeleteVlanIpRangeCmd;
|
||||
import org.apache.cloudstack.api.command.admin.vlan.ReleasePublicIpRangeCmd;
|
||||
import org.apache.cloudstack.api.command.admin.vlan.UpdateVlanIpRangeCmd;
|
||||
import org.apache.cloudstack.api.command.admin.zone.CreateZoneCmd;
|
||||
import org.apache.cloudstack.api.command.admin.zone.DeleteZoneCmd;
|
||||
import org.apache.cloudstack.api.command.admin.zone.UpdateZoneCmd;
|
||||
@ -258,6 +259,17 @@ public class MockConfigurationManagerImpl extends ManagerBase implements Configu
|
||||
return null;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.cloud.configuration.ConfigurationService#updateVlanAndPublicIpRange(org.apache.cloudstack.api
|
||||
* .commands.UpdateVlanIpRangeCmd)
|
||||
*/
|
||||
@Override
|
||||
public Vlan updateVlanAndPublicIpRange(UpdateVlanIpRangeCmd cmd) throws ConcurrentOperationException,
|
||||
ResourceUnavailableException, ResourceAllocationException{
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.cloud.configuration.ConfigurationService#markDefaultZone(java.lang.String, long, long)
|
||||
*/
|
||||
|
||||
@ -2240,6 +2240,7 @@
|
||||
"label.unmanaged.instances": "Unmanaged Instances",
|
||||
"label.untagged": "Untagged",
|
||||
"label.update.instance.group": "Update Instance Group",
|
||||
"label.update.ip.range": "Update IP range",
|
||||
"label.update.physical.network": "Update Physical Network",
|
||||
"label.update.project.resources": "Update project resources",
|
||||
"label.update.project.role": "Update project role",
|
||||
@ -3288,6 +3289,7 @@
|
||||
"message.success.scale.kubernetes": "Successfully scaled Kubernetes cluster",
|
||||
"message.success.unmanage.instance": "Successfully unmanaged instance",
|
||||
"message.success.update.ipaddress": "Successfully updated IP Address",
|
||||
"message.success.update.iprange": "Successfully updated IP range",
|
||||
"message.success.update.kubeversion": "Successfully updated Kubernetes supported version",
|
||||
"message.success.update.user": "Successfully updated user",
|
||||
"message.success.upgrade.kubernetes": "Successfully upgraded Kubernetes cluster",
|
||||
|
||||
@ -54,6 +54,13 @@
|
||||
type="danger"
|
||||
@click="() => handleRemoveAccount(record.id)"
|
||||
:disabled="!('releasePublicIpRange' in $store.getters.apis)" />
|
||||
<tooltip-button
|
||||
tooltipPlacement="bottom"
|
||||
:tooltip="$t('label.update.ip.range')"
|
||||
icon="edit"
|
||||
type="danger"
|
||||
@click="() => handleUpdateIpRangeModal(record)"
|
||||
:disabled="!('updateVlanIpRange' in $store.getters.apis)" />
|
||||
<tooltip-button
|
||||
tooltipPlacement="bottom"
|
||||
:tooltip="$t('label.remove.ip.range')"
|
||||
@ -235,6 +242,52 @@
|
||||
</a-form>
|
||||
</a-modal>
|
||||
|
||||
<a-modal
|
||||
v-model="updateIpRangeModal"
|
||||
:title="$t('label.update.ip.range')"
|
||||
v-if="selectedItem"
|
||||
:maskClosable="false"
|
||||
:footer="null"
|
||||
v-ctrl-enter="handleUpdateIpRange"
|
||||
@cancel="updateIpRangeModal = false">
|
||||
<a-form
|
||||
:form="form"
|
||||
@submit="handleAddIpRange"
|
||||
layout="vertical"
|
||||
class="form"
|
||||
>
|
||||
<a-form-item :label="$t('label.startip')" class="form__item">
|
||||
<a-input
|
||||
autoFocus
|
||||
v-decorator="['startip', { initialValue: selectedItem.startip || '', rules: [{ required: true, message: `${$t('label.required')}` }] }]">
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
<a-form-item :label="$t('label.endip')" class="form__item">
|
||||
<a-input
|
||||
v-decorator="['endip', { initialValue: selectedItem.endip || '', rules: [{ required: true, message: `${$t('label.required')}` }] }]">
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
<a-form-item :label="$t('label.gateway')" class="form__item">
|
||||
<a-input
|
||||
v-decorator="['gateway', { initialValue: selectedItem.gateway || '', rules: [{ required: true, message: `${$t('label.required')}` }] }]">
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
<a-form-item :label="$t('label.netmask')" class="form__item">
|
||||
<a-input
|
||||
v-decorator="['netmask', { initialValue: selectedItem.netmask || '', rules: [{ required: true, message: `${$t('label.required')}` }] }]">
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
<a-form-item :label="$t('label.system.vms')" class="form__item">
|
||||
<a-switch v-decorator="['forsystemvms', { initialValue: selectedItem.forsystemvms }]"></a-switch>
|
||||
</a-form-item>
|
||||
|
||||
<div :span="24" class="action-button">
|
||||
<a-button @click="updateIpRangeModal = false">{{ $t('label.cancel') }}</a-button>
|
||||
<a-button type="primary" ref="submit" @click="handleUpdateIpRange">{{ $t('label.ok') }}</a-button>
|
||||
</div>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
|
||||
</a-spin>
|
||||
</template>
|
||||
|
||||
@ -280,6 +333,7 @@ export default {
|
||||
domains: [],
|
||||
domainsLoading: false,
|
||||
addIpRangeModal: false,
|
||||
updateIpRangeModal: false,
|
||||
showAccountFields: false,
|
||||
podsLoading: false,
|
||||
pods: [],
|
||||
@ -443,6 +497,10 @@ export default {
|
||||
handleOpenAddIpRangeModal () {
|
||||
this.addIpRangeModal = true
|
||||
},
|
||||
handleUpdateIpRangeModal (item) {
|
||||
this.selectedItem = item
|
||||
this.updateIpRangeModal = true
|
||||
},
|
||||
handleDeleteIpRange (id) {
|
||||
this.componentLoading = true
|
||||
api('deleteVlanIpRange', { id }).then(() => {
|
||||
@ -498,6 +556,38 @@ export default {
|
||||
})
|
||||
})
|
||||
},
|
||||
handleUpdateIpRange (e) {
|
||||
if (this.componentLoading) return
|
||||
this.form.validateFields((error, values) => {
|
||||
if (error) return
|
||||
|
||||
this.componentLoading = true
|
||||
this.updateIpRangeModal = false
|
||||
var params = {
|
||||
id: this.selectedItem.id,
|
||||
gateway: values.gateway,
|
||||
netmask: values.netmask,
|
||||
startip: values.startip,
|
||||
endip: values.endip,
|
||||
forsystemvms: values.forsystemvms
|
||||
}
|
||||
api('updateVlanIpRange', params).then(() => {
|
||||
this.$notification.success({
|
||||
message: this.$t('message.success.update.iprange')
|
||||
})
|
||||
}).catch(error => {
|
||||
this.$notification.error({
|
||||
message: `${this.$t('label.error')} ${error.response.status}`,
|
||||
description: error.response.data.updatevlaniprangeresponse
|
||||
? error.response.data.updatevlaniprangeresponse.errortext : error.response.data.errorresponse.errortext,
|
||||
duration: 0
|
||||
})
|
||||
}).finally(() => {
|
||||
this.componentLoading = false
|
||||
this.fetchData()
|
||||
})
|
||||
})
|
||||
},
|
||||
changePage (page, pageSize) {
|
||||
this.page = page
|
||||
this.pageSize = pageSize
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user