Skip to content

Commit 9ea3364

Browse files
committed
fix for preserving nic mac and ip
Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
1 parent e8cf62a commit 9ea3364

9 files changed

Lines changed: 767 additions & 27 deletions

File tree

api/src/main/java/com/cloud/user/AccountService.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@ User createUser(String userName, String password, String firstName, String lastN
9292

9393
Account getAccount(long accountId);
9494

95+
Account getAccountByUuid(String accountUuid);
96+
9597
User getActiveUser(long userId);
9698

9799
User getOneActiveUserForAccount(Account account);

plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/adapter/ServerAdapter.java

Lines changed: 72 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@
127127
import org.apache.cloudstack.veeam.api.dto.VnicProfile;
128128
import org.apache.commons.collections.CollectionUtils;
129129
import org.apache.commons.collections.MapUtils;
130+
import org.apache.commons.lang3.ObjectUtils;
130131
import org.apache.commons.lang3.StringUtils;
131132
import org.jetbrains.annotations.NotNull;
132133

@@ -192,6 +193,7 @@
192193
import com.cloud.vm.NicVO;
193194
import com.cloud.vm.UserVmManager;
194195
import com.cloud.vm.UserVmVO;
196+
import com.cloud.vm.VMInstanceDetailVO;
195197
import com.cloud.vm.VmDetailConstants;
196198
import com.cloud.vm.dao.NicDao;
197199
import com.cloud.vm.dao.UserVmDao;
@@ -207,6 +209,7 @@ public class ServerAdapter extends ManagerBase {
207209
);
208210
private static final String VM_TA_KEY = "veeam_tag";
209211
private static final String WORKER_VM_GUEST_CPU_MODE = "host-passthrough";
212+
private static final String RESTORE_CONFIG = "restore.config";
210213

211214
@Inject
212215
AccountService accountService;
@@ -512,7 +515,7 @@ protected VMTemplateVO getTemplateForInstanceCreation(String templateUuid) {
512515
return template;
513516
}
514517

515-
protected Vm createInstance(com.cloud.dc.DataCenter zone, Long clusterId, Account owner, Long domainId,
518+
protected Pair<Vm, UserVm> createInstance(com.cloud.dc.DataCenter zone, Long clusterId, Account owner, Long domainId,
516519
String accountName, Long projectId, String name, String displayName, String serviceOfferingUuid,
517520
int cpu, int memory, String templateUuid, String userdata, ApiConstants.BootType bootType,
518521
ApiConstants.BootMode bootMode, String affinityGroupId, String userDataId, Map<String, String> details) {
@@ -582,8 +585,10 @@ protected Vm createInstance(com.cloud.dc.DataCenter zone, Long clusterId, Accoun
582585
UserVm vm = userVmManager.createVirtualMachine(cmd);
583586
vm = userVmManager.finalizeCreateVirtualMachine(vm.getId());
584587
UserVmJoinVO vo = userVmJoinDao.findById(vm.getId());
585-
return UserVmJoinVOToVmConverter.toVm(vo, this::getHostById, this::getDetailsByInstanceId,
586-
this::listTagsByInstanceId, this::listDiskAttachmentsByInstanceId, this::listNicsByInstance, false);
588+
Vm vmObj = UserVmJoinVOToVmConverter.toVm(vo, this::getHostById, this::getDetailsByInstanceId,
589+
this::listTagsByInstanceId, this::listDiskAttachmentsByInstanceId, this::listNicsByInstance,
590+
false);
591+
return new Pair<>(vmObj, vm);
587592
} catch (InsufficientCapacityException | ResourceUnavailableException | ResourceAllocationException | CloudRuntimeException e) {
588593
throw new CloudRuntimeException("Failed to create VM: " + e.getMessage(), e);
589594
}
@@ -618,6 +623,63 @@ protected static Map<String, String> getDetailsForInstanceCreation(String userda
618623
return details;
619624
}
620625

626+
protected void saveInstanceRestoreConfig(Vm request, UserVm vm) {
627+
if (StringUtils.isBlank(request.getAccountId())) {
628+
return;
629+
}
630+
if (accountService.getAccountByUuid(request.getAccountId()) == null) {
631+
return;
632+
}
633+
String restoreConfig = OvfXmlUtil.getConfigMetadataXml(request, logger);
634+
if (StringUtils.isBlank(restoreConfig)) {
635+
return;
636+
}
637+
vmInstanceDetailsDao.addDetail(vm.getId(), RESTORE_CONFIG, restoreConfig, false);
638+
}
639+
640+
protected void removeInstanceRestoreConfig(UserVm vm) {
641+
vmInstanceDetailsDao.removeDetail(vm.getId(), RESTORE_CONFIG);
642+
}
643+
644+
protected Pair<String, String> getValidatedInstanceNicDetails(final UserVmVO vm, final NetworkVO network) {
645+
if (ObjectUtils.anyNull(vm, network)) {
646+
return new Pair<>(null, null);
647+
}
648+
VMInstanceDetailVO detail = vmInstanceDetailsDao.findDetail(vm.getId(), RESTORE_CONFIG);
649+
if (detail == null || StringUtils.isBlank(detail.getValue())) {
650+
return new Pair<>(null, null);
651+
}
652+
Pair<String, String> result = OvfXmlUtil.getVmNicDetailFromStoredConfig(detail.getValue(), network.getUuid(), logger);
653+
String mac = StringUtils.trimToNull(result.first());
654+
String ip4Address = StringUtils.trimToNull(result.second());
655+
NicVO nic = null;
656+
if (mac != null) {
657+
nic = nicDao.findByNetworkIdAndMacAddress(network.getId(), mac);
658+
if (nic != null) {
659+
logger.warn("MAC address {} specified in the restore config for {} is already in use by {}, ignoring it",
660+
mac, network, nic);
661+
mac = null;
662+
if (!Objects.equals(ip4Address, nic.getIPv4Address())) {
663+
nic = null;
664+
}
665+
}
666+
}
667+
if (ip4Address != null) {
668+
if (nic == null) {
669+
nic = nicDao.findNonPlaceHolderByIp4AddressAndNetworkId(ip4Address, network.getId());
670+
}
671+
if (nic != null) {
672+
logger.warn("IPv4 address {} specified in the restore config for {} is already in use by {}, ignoring it",
673+
ip4Address, network, nic);
674+
mac = null;
675+
if (Objects.equals(ip4Address, nic.getIPv4Address())) {
676+
ip4Address = null;
677+
}
678+
}
679+
}
680+
return new Pair<>(mac, ip4Address);
681+
}
682+
621683
protected static long getProvisionedSizeInGb(String sizeStr) {
622684
long provisionedSizeInGb;
623685
try {
@@ -968,10 +1030,12 @@ public Vm createInstance(Vm request) {
9681030
if (request.getTemplate() != null && StringUtils.isNotEmpty(request.getTemplate().getId())) {
9691031
templateUuid = request.getTemplate().getId();
9701032
}
971-
return createInstance(zone, clusterId, owner, ownerDetails.first(), ownerDetails.second(),
1033+
Pair<Vm, UserVm> result = createInstance(zone, clusterId, owner, ownerDetails.first(), ownerDetails.second(),
9721034
ownerDetails.third(), name, displayName, serviceOfferingUuid, cpu, memoryMB, templateUuid,
9731035
userdata, bootOptions.first(), bootOptions.second(), request.getAffinityGroupId(),
9741036
request.getUserDataId(), request.getDetails());
1037+
saveInstanceRestoreConfig(request, result.second());
1038+
return result.first();
9751039
}
9761040

9771041
@ApiAccess(command = UpdateVMCmd.class)
@@ -1175,6 +1239,7 @@ public DiskAttachment attachInstanceDisk(final String vmUuid, final DiskAttachme
11751239
}
11761240
accountService.checkAccess(CallContext.current().getCallingAccount(), SecurityChecker.AccessType.OperateEntry,
11771241
false, vmVo);
1242+
removeInstanceRestoreConfig(vmVo);
11781243
if (vmVo.getAccountId() != volumeVO.getAccountId()) {
11791244
if (VeeamControlService.InstanceRestoreAssignOwner.value()) {
11801245
assignVolumeToAccount(volumeVO, vmVo.getAccountId());
@@ -1296,10 +1361,13 @@ public Nic attachInstanceNic(final String vmUuid, final Nic request) {
12961361
accountCannotAccessNetwork(networkVO, vmVo.getAccountId())) {
12971362
assignVmToAccount(vmVo, networkVO.getAccountId());
12981363
}
1364+
Pair<String, String> nicDetails = getValidatedInstanceNicDetails(vmVo, networkVO);
12991365
AddNicToVMCmd cmd = new AddNicToVMCmd();
13001366
ComponentContext.inject(cmd);
13011367
cmd.setVmId(vmVo.getId());
13021368
cmd.setNetworkId(networkVO.getId());
1369+
cmd.setMacAddress(nicDetails.first());
1370+
cmd.setIpaddr(nicDetails.second());
13031371
if (request.getMac() != null && StringUtils.isNotBlank(request.getMac().getAddress())) {
13041372
cmd.setMacAddress(request.getMac().getAddress());
13051373
}

plugins/integrations/veeam-control-service/src/main/java/org/apache/cloudstack/veeam/api/converter/NicVOToNicConverter.java

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
package org.apache.cloudstack.veeam.api.converter;
1919

20+
import java.util.ArrayList;
2021
import java.util.List;
2122
import java.util.function.Function;
2223
import java.util.stream.Collectors;
@@ -79,23 +80,34 @@ private static ReportedDevice getReportedDevice(NicVO vo, Mac mac, Vm vm) {
7980
device.setDescription(String.format("%s device", vo.getReserver()));
8081
device.setMac(mac);
8182
if (ObjectUtils.anyNotNull(vo.getIPv4Address(), vo.getIPv6Address())) {
82-
Ip ip = new Ip();
83-
if (vo.getIPv4Address() != null) {
84-
ip.setAddress(vo.getIPv4Address());
85-
ip.setGateway(vo.getIPv4Gateway());
86-
ip.setVersion("v4");
87-
} else if (vo.getIPv6Address() != null) {
88-
ip.setAddress(vo.getIPv6Address());
89-
ip.setGateway(vo.getIPv6Gateway());
90-
ip.setVersion("v6");
91-
}
92-
device.setIps(NamedList.of("ip", List.of(ip)));
83+
List<Ip> ips = getIps(vo);
84+
device.setIps(NamedList.of("ip", ips));
9385
}
9486
device.setHref(vm.getHref() + "/reporteddevices/" + vo.getUuid());
9587
device.setVm(vm);
9688
return device;
9789
}
9890

91+
@NotNull
92+
private static List<Ip> getIps(NicVO vo) {
93+
List<Ip> ips = new ArrayList<>();
94+
if (vo.getIPv4Address() != null) {
95+
Ip ip = new Ip();
96+
ip.setAddress(vo.getIPv4Address());
97+
ip.setGateway(vo.getIPv4Gateway());
98+
ip.setVersion("v4");
99+
ips.add(ip);
100+
}
101+
if (vo.getIPv6Address() != null) {
102+
Ip ip6 = new Ip();
103+
ip6.setAddress(vo.getIPv6Address());
104+
ip6.setGateway(vo.getIPv6Gateway());
105+
ip6.setVersion("v6");
106+
ips.add(ip6);
107+
}
108+
return ips;
109+
}
110+
99111
public static List<Nic> toNicList(final List<NicVO> vos, final String vmUuid, final Function<Long, NetworkVO> networkResolver) {
100112
return vos.stream()
101113
.map(vo -> toNic(vo, vmUuid, networkResolver))

0 commit comments

Comments
 (0)