From 9cf57d2568764cd42d21bc53e5ffaf97f3380732 Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Thu, 25 Oct 2018 09:20:39 +0530 Subject: [PATCH 1/6] network: on rolling restart force stop old routers (#2926) This force stops old VRs when performing rolling restart with cleanup=true. This will ensure that VRs are powered off quickly than wait longer for the normal ACPI shutdown. During testing, it was found on VMware where VM stops are slow compared to XenServer and KVM. Signed-off-by: Rohit Yadav --- .../cloudstack/engine/orchestration/NetworkOrchestrator.java | 1 + server/src/com/cloud/network/vpc/VpcManagerImpl.java | 1 + 2 files changed, 2 insertions(+) diff --git a/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java b/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java index 55015ce68af..9f4778e6d22 100644 --- a/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java +++ b/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java @@ -2959,6 +2959,7 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra // Destroy old routers for (final DomainRouterVO oldRouter : oldRouters) { + _routerService.stopRouter(oldRouter.getId(), true); _routerService.destroyRouter(oldRouter.getId(), context.getAccount(), context.getCaller().getId()); } diff --git a/server/src/com/cloud/network/vpc/VpcManagerImpl.java b/server/src/com/cloud/network/vpc/VpcManagerImpl.java index b8a797b44bc..548fb4de35e 100644 --- a/server/src/com/cloud/network/vpc/VpcManagerImpl.java +++ b/server/src/com/cloud/network/vpc/VpcManagerImpl.java @@ -2490,6 +2490,7 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis // Destroy old routers for (final DomainRouterVO oldRouter : oldRouters) { + _routerService.stopRouter(oldRouter.getId(), true); _routerService.destroyRouter(oldRouter.getId(), context.getAccount(), context.getCaller().getId()); } From a87acf93d8705cccf91fda3c702da04c365d9e9d Mon Sep 17 00:00:00 2001 From: alexanderbazhenoff Date: Thu, 25 Oct 2018 13:58:13 +0300 Subject: [PATCH 2/6] kvm: improved performance on creating VM (#2923) Improved performance on creating VM for KVM virtualization. On a huge hosts every "ifconfig | grep" takes a lot of time (about 2.5-3 minutes on hosts with 500 machines). For example: ip link show dev $vlanDev > /dev/null is faster than ifconfig |grep -w $vlanDev > /dev/null. But using ip command is much better. Using this patch you can create 500s machine in 10 seconds. You don't need slow ifconfig prints anymore. --- scripts/vm/network/vnet/modifyvlan.sh | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/scripts/vm/network/vnet/modifyvlan.sh b/scripts/vm/network/vnet/modifyvlan.sh index 24a38a18050..affa7780a9f 100755 --- a/scripts/vm/network/vnet/modifyvlan.sh +++ b/scripts/vm/network/vnet/modifyvlan.sh @@ -48,11 +48,7 @@ addVlan() { fi # is up? - ifconfig |grep -w $vlanDev > /dev/null - if [ $? -gt 0 ] - then - ifconfig $vlanDev up > /dev/null - fi + ip link set $vlanDev up > /dev/null 2>/dev/null if [ ! -d /sys/class/net/$vlanBr ] then @@ -86,11 +82,7 @@ addVlan() { fi fi # is vlanBr up? - ifconfig |grep -w $vlanBr > /dev/null - if [ $? -gt 0 ] - then - ifconfig $vlanBr up - fi + ip link set $vlanBr up > /dev/null 2>/dev/null return 0 } @@ -109,7 +101,7 @@ deleteVlan() { return 1 fi - ifconfig $vlanBr down + ip link set $vlanBr down if [ $? -gt 0 ] then From e2ba934c1957f087af83fd57a632f53b5ea4ac09 Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Mon, 29 Oct 2018 02:49:54 +0530 Subject: [PATCH 3/6] server: fix unwanted txn commit warning messages (#2927) This fixes unwanted transaction commit warning messages such: Signed-off-by: Rohit Yadav --- .../ResourceLimitManagerImpl.java | 101 +++++++++--------- 1 file changed, 52 insertions(+), 49 deletions(-) diff --git a/server/src/com/cloud/resourcelimit/ResourceLimitManagerImpl.java b/server/src/com/cloud/resourcelimit/ResourceLimitManagerImpl.java index c3fef57e9f1..f4f5f895923 100644 --- a/server/src/com/cloud/resourcelimit/ResourceLimitManagerImpl.java +++ b/server/src/com/cloud/resourcelimit/ResourceLimitManagerImpl.java @@ -96,6 +96,7 @@ import com.cloud.utils.db.SearchCriteria.Func; import com.cloud.utils.db.SearchCriteria.Op; import com.cloud.utils.db.Transaction; import com.cloud.utils.db.TransactionCallback; +import com.cloud.utils.db.TransactionCallbackNoReturn; import com.cloud.utils.db.TransactionCallbackWithExceptionNoReturn; import com.cloud.utils.db.TransactionStatus; import com.cloud.utils.exception.CloudRuntimeException; @@ -886,60 +887,62 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim @DB protected long recalculateAccountResourceCount(final long accountId, final ResourceType type) { - Long newCount = Transaction.execute(new TransactionCallback() { + final Long newCount; + if (type == Resource.ResourceType.user_vm) { + newCount = _userVmDao.countAllocatedVMsForAccount(accountId); + } else if (type == Resource.ResourceType.volume) { + long virtualRouterCount = _vmDao.findIdsOfAllocatedVirtualRoutersForAccount(accountId).size(); + newCount = _volumeDao.countAllocatedVolumesForAccount(accountId) - virtualRouterCount; // don't count the volumes of virtual router + } else if (type == Resource.ResourceType.snapshot) { + newCount = _snapshotDao.countSnapshotsForAccount(accountId); + } else if (type == Resource.ResourceType.public_ip) { + newCount = calculatePublicIpForAccount(accountId); + } else if (type == Resource.ResourceType.template) { + newCount = _vmTemplateDao.countTemplatesForAccount(accountId); + } else if (type == Resource.ResourceType.project) { + newCount = _projectAccountDao.countByAccountIdAndRole(accountId, Role.Admin); + } else if (type == Resource.ResourceType.network) { + newCount = _networkDao.countNetworksUserCanCreate(accountId); + } else if (type == Resource.ResourceType.vpc) { + newCount = _vpcDao.countByAccountId(accountId); + } else if (type == Resource.ResourceType.cpu) { + newCount = countCpusForAccount(accountId); + } else if (type == Resource.ResourceType.memory) { + newCount = calculateMemoryForAccount(accountId); + } else if (type == Resource.ResourceType.primary_storage) { + List virtualRouters = _vmDao.findIdsOfAllocatedVirtualRoutersForAccount(accountId); + newCount = _volumeDao.primaryStorageUsedForAccount(accountId, virtualRouters); + } else if (type == Resource.ResourceType.secondary_storage) { + newCount = calculateSecondaryStorageForAccount(accountId); + } else { + throw new InvalidParameterValueException("Unsupported resource type " + type); + } + + long oldCount = 0; + final ResourceCountVO accountRC = _resourceCountDao.findByOwnerAndType(accountId, ResourceOwnerType.Account, type); + if (accountRC != null) { + oldCount = accountRC.getCount(); + } + + if (newCount == null || !newCount.equals(oldCount)) { + Transaction.execute(new TransactionCallbackNoReturn() { @Override - public Long doInTransaction(TransactionStatus status) { - Long newCount = null; + public void doInTransactionWithoutResult(TransactionStatus status) { lockAccountAndOwnerDomainRows(accountId, type); - ResourceCountVO accountRC = _resourceCountDao.findByOwnerAndType(accountId, ResourceOwnerType.Account, type); - long oldCount = 0; - if (accountRC != null) - oldCount = accountRC.getCount(); - - if (type == Resource.ResourceType.user_vm) { - newCount = _userVmDao.countAllocatedVMsForAccount(accountId); - } else if (type == Resource.ResourceType.volume) { - newCount = _volumeDao.countAllocatedVolumesForAccount(accountId); - long virtualRouterCount = _vmDao.findIdsOfAllocatedVirtualRoutersForAccount(accountId).size(); - newCount = newCount - virtualRouterCount; // don't count the volumes of virtual router - } else if (type == Resource.ResourceType.snapshot) { - newCount = _snapshotDao.countSnapshotsForAccount(accountId); - } else if (type == Resource.ResourceType.public_ip) { - newCount = calculatePublicIpForAccount(accountId); - } else if (type == Resource.ResourceType.template) { - newCount = _vmTemplateDao.countTemplatesForAccount(accountId); - } else if (type == Resource.ResourceType.project) { - newCount = _projectAccountDao.countByAccountIdAndRole(accountId, Role.Admin); - } else if (type == Resource.ResourceType.network) { - newCount = _networkDao.countNetworksUserCanCreate(accountId); - } else if (type == Resource.ResourceType.vpc) { - newCount = _vpcDao.countByAccountId(accountId); - } else if (type == Resource.ResourceType.cpu) { - newCount = countCpusForAccount(accountId); - } else if (type == Resource.ResourceType.memory) { - newCount = calculateMemoryForAccount(accountId); - } else if (type == Resource.ResourceType.primary_storage) { - List virtualRouters = _vmDao.findIdsOfAllocatedVirtualRoutersForAccount(accountId); - newCount = _volumeDao.primaryStorageUsedForAccount(accountId, virtualRouters); - } else if (type == Resource.ResourceType.secondary_storage) { - newCount = calculateSecondaryStorageForAccount(accountId); - } else { - throw new InvalidParameterValueException("Unsupported resource type " + type); - } - _resourceCountDao.setResourceCount(accountId, ResourceOwnerType.Account, type, (newCount == null) ? 0 : newCount.longValue()); - - // No need to log message for primary and secondary storage because both are recalculating the - // resource count which will not lead to any discrepancy. - if (!Long.valueOf(oldCount).equals(newCount) && - (type != Resource.ResourceType.primary_storage && type != Resource.ResourceType.secondary_storage)) { - s_logger.warn("Discrepency in the resource count " + "(original count=" + oldCount + " correct count = " + newCount + ") for type " + type + - " for account ID " + accountId + " is fixed during resource count recalculation."); - } - return newCount; + _resourceCountDao.setResourceCount(accountId, ResourceOwnerType.Account, type, (newCount == null) ? 0 : newCount); } }); + } - return (newCount == null) ? 0 : newCount.longValue(); + // No need to log message for primary and secondary storage because both are recalculating the + // resource count which will not lead to any discrepancy. + if (newCount != null && !newCount.equals(oldCount) && + type != Resource.ResourceType.primary_storage && type != Resource.ResourceType.secondary_storage) { + s_logger.warn("Discrepancy in the resource count " + "(original count=" + oldCount + " correct count = " + newCount + ") for type " + type + + " for account ID " + accountId + " is fixed during resource count recalculation."); + } + + return (newCount == null) ? 0 : newCount; } public long countCpusForAccount(long accountId) { From f0491d5c72c3161777ca49ae809606a6704df5ff Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Mon, 29 Oct 2018 16:11:43 +0530 Subject: [PATCH 4/6] vr: defer was broken in VR because of json name change (#2979) After upgrade from CS 4.10 to CS 4.11, multiple VRs did not start through. It did not properly defer the finalize config in update_config.py. Apparently, the json files are now called differently: where it used to be vm_dhcp_entry.json it now has a uuid added, for example vm_metadata.json.4d727b6e-2b48-49df-81c3-b8532f3d6745. The if statement that checks if the finalize can be safely deferred therefore no longer matches. This PR contains a fix so finalize is defered again. Signed-off-by: Rohit Yadav --- systemvm/debian/opt/cloud/bin/update_config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/systemvm/debian/opt/cloud/bin/update_config.py b/systemvm/debian/opt/cloud/bin/update_config.py index 02161b662e5..77008afb794 100755 --- a/systemvm/debian/opt/cloud/bin/update_config.py +++ b/systemvm/debian/opt/cloud/bin/update_config.py @@ -52,7 +52,7 @@ def process_file(): qf.setFile(sys.argv[1]) qf.load(None) # These can be safely deferred, dramatically speeding up loading times - if not (os.environ.get('DEFER_CONFIG', False) and sys.argv[1] in ('vm_dhcp_entry.json', 'vm_metadata.json')): + if not (os.environ.get('DEFER_CONFIG', False) and ('vm_dhcp_entry.json' in sys.argv[1] or 'vm_metadata.json' in sys.argv[1])): # Converge finish_config() From dffb4309750517ced063008ccee7907cb85f86ba Mon Sep 17 00:00:00 2001 From: Nicolas Vazquez Date: Mon, 29 Oct 2018 07:44:20 -0300 Subject: [PATCH 5/6] kvm: Fix migrating VM from ISO failures (#2928) Prevents errors while migrating VM from ISO: Test 1: Deploy VM from ISO -> Live migrate VM to another host -> ERROR Test 2: Register ISO using Direct Download on KVM -> Deploy VM from ISO -> Live migrate VM to another host -> ERROR - Prevent NullPointerException migrating VM from ISO - Prevent mount secondary storage on ISO direct downloads on KVM --- .../cloudstack/storage/to/TemplateObjectTO.java | 9 +++++++++ .../kvm/resource/LibvirtComputingResource.java | 4 +++- .../src/com/cloud/template/TemplateManagerImpl.java | 12 ++++++++---- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/core/src/org/apache/cloudstack/storage/to/TemplateObjectTO.java b/core/src/org/apache/cloudstack/storage/to/TemplateObjectTO.java index 4a3d058176c..cc2eaadea07 100644 --- a/core/src/org/apache/cloudstack/storage/to/TemplateObjectTO.java +++ b/core/src/org/apache/cloudstack/storage/to/TemplateObjectTO.java @@ -46,6 +46,7 @@ public class TemplateObjectTO implements DataTO { private Hypervisor.HypervisorType hypervisorType; private boolean bootable; private String uniqueName; + private boolean directDownload; public TemplateObjectTO() { @@ -235,6 +236,14 @@ public class TemplateObjectTO implements DataTO { this.uniqueName = uniqueName; } + public boolean isDirectDownload() { + return directDownload; + } + + public void setDirectDownload(boolean directDownload) { + this.directDownload = directDownload; + } + @Override public String toString() { return new StringBuilder("TemplateTO[id=").append(id).append("|origUrl=").append(origUrl).append("|name").append(name).append("]").toString(); diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java index 8a94b058655..652f6431f0e 100644 --- a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java +++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java @@ -49,6 +49,7 @@ import javax.xml.parsers.ParserConfigurationException; import com.cloud.resource.RequestWrapper; import org.apache.cloudstack.storage.to.PrimaryDataStoreTO; +import org.apache.cloudstack.storage.to.TemplateObjectTO; import org.apache.cloudstack.storage.to.VolumeObjectTO; import org.apache.cloudstack.utils.hypervisor.HypervisorUtils; import org.apache.cloudstack.utils.linux.CPUStat; @@ -2209,7 +2210,8 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv final DataTO data = volume.getData(); final DataStoreTO store = data.getDataStore(); - if (volume.getType() == Volume.Type.ISO && data.getPath() != null && (store instanceof NfsTO || store instanceof PrimaryDataStoreTO)) { + if (volume.getType() == Volume.Type.ISO && data.getPath() != null && (store instanceof NfsTO || + store instanceof PrimaryDataStoreTO && data instanceof TemplateObjectTO && !((TemplateObjectTO) data).isDirectDownload())) { final String isoPath = store.getUrl().split("\\?")[0] + File.separator + data.getPath(); final int index = isoPath.lastIndexOf("/"); final String path = isoPath.substring(0, index); diff --git a/server/src/com/cloud/template/TemplateManagerImpl.java b/server/src/com/cloud/template/TemplateManagerImpl.java index 42bdd72af63..48cc6f43a95 100755 --- a/server/src/com/cloud/template/TemplateManagerImpl.java +++ b/server/src/com/cloud/template/TemplateManagerImpl.java @@ -50,6 +50,7 @@ import org.apache.cloudstack.storage.datastore.db.ImageStoreDao; import org.apache.cloudstack.storage.datastore.db.ImageStoreVO; import org.apache.cloudstack.utils.imagestore.ImageStoreUtil; import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.MapUtils; import org.apache.log4j.Logger; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ApiConstants; @@ -557,11 +558,13 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, if (vm.getIsoId() != null) { Map storageForDisks = dest.getStorageForDisks(); Long poolId = null; - for (StoragePool storagePool : storageForDisks.values()) { - if (poolId != null && storagePool.getId() != poolId) { - throw new CloudRuntimeException("Cannot determine where to download iso"); + if (MapUtils.isNotEmpty(storageForDisks)) { + for (StoragePool storagePool : storageForDisks.values()) { + if (poolId != null && storagePool.getId() != poolId) { + throw new CloudRuntimeException("Cannot determine where to download iso"); + } + poolId = storagePool.getId(); } - poolId = storagePool.getId(); } TemplateInfo template = prepareIso(vm.getIsoId(), vm.getDataCenterId(), dest.getHost().getId(), poolId); if (template == null){ @@ -579,6 +582,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, } TemplateObjectTO iso = (TemplateObjectTO)template.getTO(); + iso.setDirectDownload(template.isDirectDownload()); iso.setGuestOsType(displayName); DiskTO disk = new DiskTO(iso, 3L, null, Volume.Type.ISO); profile.addDisk(disk);