From 5a52ca78ae5e165211c618525613c3d62cfd1b28 Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Sat, 20 Apr 2024 00:53:49 +0530 Subject: [PATCH 1/3] kvm: export sysinfo for arm64 domains for cloud-init to work (#8940) This fixes a limitation for arm64/aarch64 KVM hosts to correctly export the product name via sysconfig attribute. Without this `cloud-init` doesn't function correctly on arm64 platforms. Signed-off-by: Rohit Yadav --- .../java/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java index db179f98642..6d69b2f9664 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java @@ -222,9 +222,7 @@ public class LibvirtVMDef { guestDef.append("\n"); } } - if (_arch == null || !_arch.equals("aarch64")) { - guestDef.append("\n"); - } + guestDef.append("\n"); guestDef.append("\n"); if (iothreads) { guestDef.append(String.format("%s", NUMBER_OF_IOTHREADS)); From 405aac38bc949db8467cc789a0ecfc9b4c55cd15 Mon Sep 17 00:00:00 2001 From: Rene Peinthor Date: Mon, 22 Apr 2024 10:04:05 +0200 Subject: [PATCH 2/3] linstor: Only set allow-two-primaries if resource is already in use (#8802) For live migrate we need the allow-two-primaries option, but we don't know exactly if we are called for a migration operation. Now also check if at least any of the resources is in use somewhere and only then set the option. --- .../kvm/storage/LinstorStorageAdaptor.java | 33 +++++++++++++------ .../storage/datastore/util/LinstorUtil.java | 19 +++++++++++ 2 files changed, 42 insertions(+), 10 deletions(-) diff --git a/plugins/storage/volume/linstor/src/main/java/com/cloud/hypervisor/kvm/storage/LinstorStorageAdaptor.java b/plugins/storage/volume/linstor/src/main/java/com/cloud/hypervisor/kvm/storage/LinstorStorageAdaptor.java index 9ad8332d0e1..66278f827f7 100644 --- a/plugins/storage/volume/linstor/src/main/java/com/cloud/hypervisor/kvm/storage/LinstorStorageAdaptor.java +++ b/plugins/storage/volume/linstor/src/main/java/com/cloud/hypervisor/kvm/storage/LinstorStorageAdaptor.java @@ -260,6 +260,28 @@ public class LinstorStorageAdaptor implements StorageAdaptor { } } + /** + * Checks if the given resource is in use by drbd on any host and + * if so set the drbd option allow-two-primaries + * @param api linstor api object + * @param rscName resource name to set allow-two-primaries if in use + * @throws ApiException if any problem connecting to the Linstor controller + */ + private void allow2PrimariesIfInUse(DevelopersApi api, String rscName) throws ApiException { + if (LinstorUtil.isResourceInUse(api, rscName)) { + // allow 2 primaries for live migration, should be removed by disconnect on the other end + ResourceDefinitionModify rdm = new ResourceDefinitionModify(); + Properties props = new Properties(); + props.put("DrbdOptions/Net/allow-two-primaries", "yes"); + rdm.setOverrideProps(props); + ApiCallRcList answers = api.resourceDefinitionModify(rscName, rdm); + if (answers.hasError()) { + s_logger.error("Unable to set 'allow-two-primaries' on " + rscName); + // do not fail here as adding allow-two-primaries property is only a problem while live migrating + } + } + } + @Override public boolean connectPhysicalDisk(String volumePath, KVMStoragePool pool, Map details) { @@ -286,16 +308,7 @@ public class LinstorStorageAdaptor implements StorageAdaptor { try { - // allow 2 primaries for live migration, should be removed by disconnect on the other end - ResourceDefinitionModify rdm = new ResourceDefinitionModify(); - Properties props = new Properties(); - props.put("DrbdOptions/Net/allow-two-primaries", "yes"); - rdm.setOverrideProps(props); - ApiCallRcList answers = api.resourceDefinitionModify(rscName, rdm); - if (answers.hasError()) { - s_logger.error("Unable to set 'allow-two-primaries' on " + rscName); - // do not fail here as adding allow-two-primaries property is only a problem while live migrating - } + allow2PrimariesIfInUse(api, rscName); } catch (ApiException apiEx) { s_logger.error(apiEx); // do not fail here as adding allow-two-primaries property is only a problem while live migrating diff --git a/plugins/storage/volume/linstor/src/main/java/org/apache/cloudstack/storage/datastore/util/LinstorUtil.java b/plugins/storage/volume/linstor/src/main/java/org/apache/cloudstack/storage/datastore/util/LinstorUtil.java index cc85c9834eb..c8544fd3e3e 100644 --- a/plugins/storage/volume/linstor/src/main/java/org/apache/cloudstack/storage/datastore/util/LinstorUtil.java +++ b/plugins/storage/volume/linstor/src/main/java/org/apache/cloudstack/storage/datastore/util/LinstorUtil.java @@ -23,6 +23,7 @@ import com.linbit.linstor.api.DevelopersApi; import com.linbit.linstor.api.model.ApiCallRc; import com.linbit.linstor.api.model.ApiCallRcList; import com.linbit.linstor.api.model.ProviderKind; +import com.linbit.linstor.api.model.Resource; import com.linbit.linstor.api.model.ResourceGroup; import com.linbit.linstor.api.model.StoragePool; @@ -90,4 +91,22 @@ public class LinstorUtil { throw new CloudRuntimeException(apiEx); } } + + /** + * Check if any resource of the given name is InUse on any host. + * + * @param api developer api object to use + * @param rscName resource name to check in use state. + * @return True if a resource found that is in use(primary) state, else false. + * @throws ApiException forwards api errors + */ + public static boolean isResourceInUse(DevelopersApi api, String rscName) throws ApiException { + List rscs = api.resourceList(rscName, null, null); + if (rscs != null) { + return rscs.stream() + .anyMatch(rsc -> rsc.getState() != null && Boolean.TRUE.equals(rsc.getState().isInUse())); + } + s_logger.error("isResourceInUse: null returned from resourceList"); + return false; + } } From 0577b0ac8ef99c304216a0212e775f9293d06688 Mon Sep 17 00:00:00 2001 From: dahn Date: Mon, 22 Apr 2024 10:31:48 +0200 Subject: [PATCH 3/3] server: add logs to public ip allocation attempt (#8239) --- .../cloud/network/IpAddressManagerImpl.java | 38 ++++++++++++++----- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/server/src/main/java/com/cloud/network/IpAddressManagerImpl.java b/server/src/main/java/com/cloud/network/IpAddressManagerImpl.java index 9882ed50353..f55b03a5bf6 100644 --- a/server/src/main/java/com/cloud/network/IpAddressManagerImpl.java +++ b/server/src/main/java/com/cloud/network/IpAddressManagerImpl.java @@ -343,6 +343,9 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage if (possibleAddr.getState() != State.Free) { continue; } + if (s_logger.isDebugEnabled()) { + s_logger.debug(String.format("trying ip address %s", possibleAddr.getAddress())); + } possibleAddr.setSourceNat(sourceNat); possibleAddr.setAllocatedTime(new Date()); possibleAddr.setAllocatedInDomainId(owner.getDomainId()); @@ -357,15 +360,9 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage possibleAddr.setAssociatedWithNetworkId(guestNetworkId); possibleAddr.setVpcId(vpcId); } - if (_ipAddressDao.lockRow(possibleAddr.getId(), true) != null) { - final IPAddressVO userIp = _ipAddressDao.findById(possibleAddr.getId()); - if (userIp.getState() == State.Free) { - possibleAddr.setState(State.Allocating); - if (_ipAddressDao.update(possibleAddr.getId(), possibleAddr)) { - finalAddress = possibleAddr; - break; - } - } + finalAddress = assignIpAddressWithLock(possibleAddr); + if (finalAddress != null) { + break; } } @@ -387,6 +384,29 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage }); } + private IPAddressVO assignIpAddressWithLock(IPAddressVO possibleAddr) { + IPAddressVO finalAddress = null; + IPAddressVO userIp = _ipAddressDao.acquireInLockTable(possibleAddr.getId()); + if (userIp != null) { + if (s_logger.isDebugEnabled()) { + s_logger.debug(String.format("locked row for ip address %s (id: %s)", possibleAddr.getAddress(), possibleAddr.getUuid())); + } + if (userIp.getState() == State.Free) { + possibleAddr.setState(State.Allocating); + if (_ipAddressDao.update(possibleAddr.getId(), possibleAddr)) { + s_logger.info(String.format("successfully allocated ip address %s", possibleAddr.getAddress())); + finalAddress = possibleAddr; + } + } else { + if (s_logger.isDebugEnabled()) { + s_logger.debug(String.format("locked ip address %s is not free (%s)", possibleAddr.getAddress(), userIp.getState())); + } + } + _ipAddressDao.releaseFromLockTable(possibleAddr.getId()); + } + return finalAddress; + } + @Override public boolean configure(String name, Map params) { // populate providers