Skip to content

Commit 2ebdb34

Browse files
author
committed
Support requesting a specific IPv4 address in Basic Networking during
instance creation.
1 parent c43c69a commit 2ebdb34

5 files changed

Lines changed: 363 additions & 17 deletions

File tree

‎engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java‎

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -872,6 +872,8 @@ public Pair<NicProfile, Integer> allocateNic(final NicProfile requested, final N
872872

873873
NicVO vo = new NicVO(guru.getName(), vm.getId(), network.getId(), vm.getType());
874874

875+
configureNicProfileBasedOnRequestedIp(requested, profile, network);
876+
875877
deviceId = applyProfileToNic(vo, profile, deviceId);
876878

877879
vo = _nicDao.persist(vo);
@@ -883,6 +885,78 @@ public Pair<NicProfile, Integer> allocateNic(final NicProfile requested, final N
883885
return new Pair<NicProfile, Integer>(vmNic, Integer.valueOf(deviceId));
884886
}
885887

888+
/**
889+
* If the requested IPv4 address from the NicProfile was configured then it configures the IPv4 address, Netmask and Gateway to deploy the VM with the requested IP.
890+
*/
891+
protected void configureNicProfileBasedOnRequestedIp(NicProfile requestedNicProfile, NicProfile nicProfile, Network network) {
892+
if (requestedNicProfile == null) {
893+
return;
894+
}
895+
String requestedIpv4Address = requestedNicProfile.getRequestedIPv4();
896+
if (requestedIpv4Address == null) {
897+
return;
898+
}
899+
if (!NetUtils.isValidIp4(requestedIpv4Address)) {
900+
throw new InvalidParameterValueException(String.format("The requested [IPv4 address='%s'] is not a valid IP address", requestedIpv4Address));
901+
}
902+
903+
VlanVO vlanVo = _vlanDao.findByNetworkId(network.getId());
904+
if (vlanVo == null) {
905+
throw new CloudRuntimeException(String.format("Trying to configure a Nic with the requested [IPv4='%s'] but cannot find a Vlan for the [network id='%s']",
906+
requestedIpv4Address, network.getId()));
907+
}
908+
909+
String ipv4Gateway = vlanVo.getVlanGateway();
910+
String ipv4Netmask = vlanVo.getVlanNetmask();
911+
912+
if (!NetUtils.isValidIp4(ipv4Gateway)) {
913+
throw new CloudRuntimeException(String.format("The [IPv4Gateway='%s'] from [VlanId='%s'] is not valid", ipv4Gateway, vlanVo.getId()));
914+
}
915+
if (!NetUtils.isValidIp4Netmask(ipv4Netmask)) {
916+
throw new CloudRuntimeException(String.format("The [IPv4Netmask='%s'] from [VlanId='%s'] is not valid", ipv4Netmask, vlanVo.getId()));
917+
}
918+
919+
acquireLockAndCheckIfIpv4IsFree(network, requestedIpv4Address);
920+
921+
nicProfile.setIPv4Address(requestedIpv4Address);
922+
nicProfile.setIPv4Gateway(ipv4Gateway);
923+
nicProfile.setIPv4Netmask(ipv4Netmask);
924+
925+
if (nicProfile.getMacAddress() == null) {
926+
try {
927+
String macAddress = _networkModel.getNextAvailableMacAddressInNetwork(network.getId());
928+
nicProfile.setMacAddress(macAddress);
929+
} catch (InsufficientAddressCapacityException e) {
930+
throw new CloudRuntimeException(String.format("Cannot get next available mac address in [network id='%s']", network.getId()), e);
931+
}
932+
}
933+
}
934+
935+
/**
936+
* Acquires lock of in table "user_ip_address" and checks if the requested IPv4 address is Free.
937+
*/
938+
protected void acquireLockAndCheckIfIpv4IsFree(Network network, String requestedIpv4Address) {
939+
IPAddressVO ipVO = _ipAddressDao.findByIpAndSourceNetworkId(network.getId(), requestedIpv4Address);
940+
if (ipVO == null) {
941+
throw new CloudRuntimeException(String.format("Cannot find IPAddressVO for guest [IPv4 address='%s'] and [network id='%s']", requestedIpv4Address, network.getId()));
942+
}
943+
try {
944+
IPAddressVO lockedIpVO = _ipAddressDao.acquireInLockTable(ipVO.getId());
945+
if (lockedIpVO == null) {
946+
_ipAddressDao.releaseFromLockTable(ipVO.getId());
947+
}
948+
if (lockedIpVO.getState() != IPAddressVO.State.Free) {
949+
String ipState = lockedIpVO.getState().toString();
950+
_ipAddressDao.releaseFromLockTable(lockedIpVO.getId());
951+
throw new CloudRuntimeException(String.format("Cannot acquire guest [IPv4 address='%s']; The Ip address is in [state='%s']", requestedIpv4Address, ipState));
952+
}
953+
lockedIpVO.setState(IPAddressVO.State.Allocated);
954+
_ipAddressDao.update(lockedIpVO.getId(), lockedIpVO);
955+
} catch (Exception e) {
956+
_ipAddressDao.releaseFromLockTable(ipVO.getId());
957+
}
958+
}
959+
886960
protected Integer applyProfileToNic(final NicVO vo, final NicProfile profile, Integer deviceId) {
887961
if (profile.getDeviceId() != null) {
888962
vo.setDeviceId(profile.getDeviceId());

0 commit comments

Comments
 (0)