Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
e55d016
various fixes for fiberchannel and autoscale prefix option
Jun 23, 2025
1bf169b
Update scripts/storage/multipath/startConnectVolume.sh
Jun 23, 2025
7be9beb
Update scripts/storage/multipath/finishConnectVolume.sh
Jun 23, 2025
6353507
Update scripts/storage/multipath/connectVolume.sh
Jun 23, 2025
2a80c96
Update plugins/storage/volume/adaptive/src/main/java/org/apache/cloud…
Jun 23, 2025
f83481e
Update plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm…
Jun 23, 2025
6a97d69
end of line resizeVolume.sh
Jun 23, 2025
86eff0e
Merge branch '4.20' into 4.20-fiberchannel-patches
rg9975 Sep 3, 2025
017a332
Update plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm…
rg9975 Sep 9, 2025
fdfc051
Merge branch '4.20' into 4.20-fiberchannel-patches
rg9975 Nov 13, 2025
5cfbb8b
Update scripts/storage/multipath/connectVolume.sh
rg9975 Nov 14, 2025
e620868
Update plugins/storage/volume/adaptive/src/main/java/org/apache/cloud…
rg9975 Nov 14, 2025
cd69e1a
Update server/src/main/java/com/cloud/network/as/AutoScaleManagerImpl…
rg9975 Nov 14, 2025
6105c2f
Update engine/schema/pom.xml
rg9975 Nov 14, 2025
705ef8f
Update plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm…
rg9975 Nov 14, 2025
7256bde
Update scripts/storage/multipath/startConnectVolume.sh
rg9975 Nov 14, 2025
e041639
Update plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm…
rg9975 Nov 14, 2025
36396e4
Update plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm…
rg9975 Nov 14, 2025
9c2d927
Update plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm…
rg9975 Nov 14, 2025
8e9316a
fix absolute path for md5sum.txt in pom.xml
Nov 14, 2025
f962978
update to multipath scripts and code/error logging
Nov 14, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion engine/schema/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
</dependencies>
<executions>
<execution>
<?m2e execute onConfiguration,onIncremental?>
<id>setproperty</id>
<phase>validate</phase>
<goals>
Expand All @@ -90,6 +91,7 @@
</configuration>
</execution>
<execution>
<?m2e execute onConfiguration,onIncremental?>
<id>set-properties</id>
<phase>generate-sources</phase>
<goals>
Expand All @@ -106,7 +108,7 @@
templateList.add("systemvmtemplate-${csVersion}.${patch}-x86_64-xen")
templateList.add("systemvmtemplate-${csVersion}.${patch}-x86_64-ovm")
templateList.add("systemvmtemplate-${csVersion}.${patch}-x86_64-hyperv")
File file = new File("./engine/schema/dist/systemvm-templates/md5sum.txt")
File file = new File("${basedir}/../../engine/schema/dist/systemvm-templates/md5sum.txt")
def lines = file.readLines()
for (template in templateList) {
def data = lines.findAll { it.contains(template) }
Expand All @@ -128,6 +130,7 @@
<artifactId>download-maven-plugin</artifactId>
<version>1.6.3</version>
<executions>
<?m2e execute onConfiguration,onIncremental?>
<execution>
<id>download-checksums</id>
<phase>validate</phase>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// 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 com.cloud.hypervisor.kvm.storage;

import java.util.Map;

/**
* Decorator for StorageAdapters that implement asynchronous physical disk connections to improve
* performance on VM starts with large numbers of disks.
*/
public interface AsyncPhysicalDiskConnectorDecorator {
/**
* Initiates a connection attempt (may or may not complete it depending on implementation)
* @param path
* @param pool
* @param details
* @return
*/
public boolean startConnectPhysicalDisk(String path, KVMStoragePool pool, Map<String,String> details);

/**
* Tests if the physical disk is connected
* @param path
* @param pool
* @param details
* @return
*/
public boolean isConnected(String path, KVMStoragePool pool, Map<String,String> details);

/**
* Completes a connection attempt after isConnected returns true;
* @param path
* @param pool
* @param details
* @return
* @throws Exception
*/
public boolean finishConnectPhysicalDisk(String path, KVMStoragePool pool, Map<String,String> details) throws Exception;
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import java.lang.reflect.Modifier;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
Expand All @@ -42,9 +43,11 @@
import com.cloud.hypervisor.kvm.resource.KVMHABase.PoolType;
import com.cloud.hypervisor.kvm.resource.KVMHAMonitor;
import com.cloud.storage.Storage;
import com.cloud.storage.StorageManager;
import com.cloud.storage.Storage.StoragePoolType;
import com.cloud.storage.StorageLayer;
import com.cloud.storage.Volume;
import com.cloud.utils.StringUtils;
import com.cloud.utils.Pair;
import com.cloud.utils.Ternary;
import com.cloud.utils.exception.CloudRuntimeException;
Expand Down Expand Up @@ -164,13 +167,30 @@
return adaptor.connectPhysicalDisk(volPath, pool, details, false);
}

private static class ConnectingDiskInfo {
ConnectingDiskInfo(VolumeObjectTO volume, StorageAdaptor adaptor, KVMStoragePool pool, Map<String, String> details) {
this.volume = volume;
this.adapter = adaptor;
this.pool = pool;
this.details = details;
}

Check warning on line 176 in plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStoragePoolManager.java

View check run for this annotation

Codecov / codecov/patch

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStoragePoolManager.java#L171-L176

Added lines #L171 - L176 were not covered by tests
VolumeObjectTO volume;
KVMStoragePool pool = null;
StorageAdaptor adapter = null;
Map<String,String> details = null;

Check warning on line 180 in plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStoragePoolManager.java

View check run for this annotation

Codecov / codecov/patch

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStoragePoolManager.java#L178-L180

Added lines #L178 - L180 were not covered by tests
}

public boolean connectPhysicalDisksViaVmSpec(VirtualMachineTO vmSpec, boolean isVMMigrate) {
boolean result = false;

final String vmName = vmSpec.getName();

List<DiskTO> disks = Arrays.asList(vmSpec.getDisks());


// disks that connect in background
List<ConnectingDiskInfo> connectingDisks = new ArrayList<>();

Check warning on line 192 in plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStoragePoolManager.java

View check run for this annotation

Codecov / codecov/patch

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStoragePoolManager.java#L192

Added line #L192 was not covered by tests

for (DiskTO disk : disks) {
if (disk.getType() == Volume.Type.ISO) {
result = true;
Expand All @@ -187,17 +207,79 @@
KVMStoragePool pool = getStoragePool(store.getPoolType(), store.getUuid());
StorageAdaptor adaptor = getStorageAdaptor(pool.getType());

result = adaptor.connectPhysicalDisk(vol.getPath(), pool, disk.getDetails(), isVMMigrate);
if (adaptor instanceof AsyncPhysicalDiskConnectorDecorator) {
// If the adaptor supports async disk connection, we can start the connection
// and return immediately, allowing the connection to complete in the background.
result = ((AsyncPhysicalDiskConnectorDecorator) adaptor).startConnectPhysicalDisk(vol.getPath(), pool, disk.getDetails());

Check warning on line 213 in plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStoragePoolManager.java

View check run for this annotation

Codecov / codecov/patch

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStoragePoolManager.java#L213

Added line #L213 was not covered by tests
if (!result) {
logger.error("Failed to start connecting disks via vm spec for vm: " + vmName + " volume:" + vol.toString());
return false;

Check warning on line 216 in plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStoragePoolManager.java

View check run for this annotation

Codecov / codecov/patch

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStoragePoolManager.java#L215-L216

Added lines #L215 - L216 were not covered by tests
}

if (!result) {
logger.error("Failed to connect disks via vm spec for vm: " + vmName + " volume:" + vol.toString());
return result;
// add disk to list of disks to check later
connectingDisks.add(new ConnectingDiskInfo(vol, adaptor, pool, disk.getDetails()));

Check warning on line 220 in plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStoragePoolManager.java

View check run for this annotation

Codecov / codecov/patch

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStoragePoolManager.java#L220

Added line #L220 was not covered by tests
} else {
result = adaptor.connectPhysicalDisk(vol.getPath(), pool, disk.getDetails(), isVMMigrate);

Check warning on line 222 in plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStoragePoolManager.java

View check run for this annotation

Codecov / codecov/patch

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStoragePoolManager.java#L222

Added line #L222 was not covered by tests

if (!result) {
logger.error("Failed to connect disks via vm spec for vm: " + vmName + " volume:" + vol.toString());
return result;

Check warning on line 226 in plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStoragePoolManager.java

View check run for this annotation

Codecov / codecov/patch

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStoragePoolManager.java#L225-L226

Added lines #L225 - L226 were not covered by tests
}
}
}

Check warning on line 229 in plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStoragePoolManager.java

View check run for this annotation

Codecov / codecov/patch

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStoragePoolManager.java#L229

Added line #L229 was not covered by tests

// if we have any connecting disks to check, wait for them to connect or timeout
if (!connectingDisks.isEmpty()) {
for (ConnectingDiskInfo connectingDisk : connectingDisks) {
StorageAdaptor adaptor = connectingDisk.adapter;
KVMStoragePool pool = connectingDisk.pool;
VolumeObjectTO volume = connectingDisk.volume;
Map<String, String> details = connectingDisk.details;
long diskWaitTimeMillis = getDiskWaitTimeMillis(details);

Check warning on line 238 in plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStoragePoolManager.java

View check run for this annotation

Codecov / codecov/patch

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStoragePoolManager.java#L234-L238

Added lines #L234 - L238 were not covered by tests

// wait for the disk to connect
long startTime = System.currentTimeMillis();

Check warning on line 241 in plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStoragePoolManager.java

View check run for this annotation

Codecov / codecov/patch

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStoragePoolManager.java#L241

Added line #L241 was not covered by tests
while (System.currentTimeMillis() - startTime < diskWaitTimeMillis) {
if (((AsyncPhysicalDiskConnectorDecorator) adaptor).isConnected(volume.getPath(), pool, details)) {
logger.debug(String.format("Disk %s connected successfully for VM %s", volume.getPath(), vmName));
break;

Check warning on line 245 in plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStoragePoolManager.java

View check run for this annotation

Codecov / codecov/patch

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStoragePoolManager.java#L244-L245

Added lines #L244 - L245 were not covered by tests
}

sleep(1000); // wait for 1 second before checking again

Check warning on line 248 in plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStoragePoolManager.java

View check run for this annotation

Codecov / codecov/patch

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStoragePoolManager.java#L248

Added line #L248 was not covered by tests
}
}
}

return result;
}

private long getDiskWaitTimeMillis(Map<String,String> details) {
int waitTimeInSec = 60; // default wait time in seconds

Check warning on line 257 in plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStoragePoolManager.java

View check run for this annotation

Codecov / codecov/patch

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStoragePoolManager.java#L256-L257

Added lines #L256 - L257 were not covered by tests
if (details != null && details.containsKey(StorageManager.STORAGE_POOL_DISK_WAIT.toString())) {
String waitTime = details.get(StorageManager.STORAGE_POOL_DISK_WAIT.toString());

Check warning on line 259 in plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStoragePoolManager.java

View check run for this annotation

Codecov / codecov/patch

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStoragePoolManager.java#L259

Added line #L259 was not covered by tests
if (StringUtils.isNotEmpty(waitTime)) {
waitTimeInSec = Integer.valueOf(waitTime).intValue();
logger.debug(String.format("%s set to %s", waitTimeInSec, StorageManager.STORAGE_POOL_DISK_WAIT.toString()));

Check warning on line 262 in plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStoragePoolManager.java

View check run for this annotation

Codecov / codecov/patch

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStoragePoolManager.java#L261-L262

Added lines #L261 - L262 were not covered by tests
}
} else {

Check warning on line 264 in plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStoragePoolManager.java

View check run for this annotation

Codecov / codecov/patch

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStoragePoolManager.java#L264

Added line #L264 was not covered by tests
// wait at least 60 seconds even if input was lower
if (waitTimeInSec < 60) {
logger.debug(String.format("%s was less than 60s. Increasing to 60s default.", StorageManager.STORAGE_POOL_DISK_WAIT.toString()));
waitTimeInSec = 60;

Check warning on line 268 in plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStoragePoolManager.java

View check run for this annotation

Codecov / codecov/patch

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStoragePoolManager.java#L267-L268

Added lines #L267 - L268 were not covered by tests
}
}
return waitTimeInSec * 1000; // convert to milliseconds
}

Check warning on line 272 in plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStoragePoolManager.java

View check run for this annotation

Codecov / codecov/patch

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStoragePoolManager.java#L271-L272

Added lines #L271 - L272 were not covered by tests

private boolean sleep(long millis) {
try {
Thread.sleep(millis);
return true;
} catch (InterruptedException e) {
return false;

Check warning on line 279 in plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStoragePoolManager.java

View check run for this annotation

Codecov / codecov/patch

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStoragePoolManager.java#L274-L279

Added lines #L274 - L279 were not covered by tests
}
}

Check warning on line 281 in plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStoragePoolManager.java

View check run for this annotation

Codecov / codecov/patch

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStoragePoolManager.java#L281

Added line #L281 was not covered by tests

public boolean disconnectPhysicalDisk(Map<String, String> volumeToDisconnect) {
logger.debug(String.format("Disconnect physical disks using volume map: %s", volumeToDisconnect.toString()));
if (MapUtils.isEmpty(volumeToDisconnect)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1608,8 +1608,20 @@
storagePoolMgr.disconnectPhysicalDisk(primaryStore.getPoolType(), primaryStore.getUuid(), vol.getPath());

return new DettachAnswer(disk);
} catch (final LibvirtException | InternalErrorException | CloudRuntimeException e) {
logger.debug(String.format("Failed to detach volume [id: %d, uuid: %s, name: %s, path: %s], due to ", vol.getId(), vol.getUuid(), vol.getName(), vol.getPath()), e);
} catch (final LibvirtException e) {

Check warning on line 1611 in plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java

View check run for this annotation

Codecov / codecov/patch

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java#L1611

Added line #L1611 was not covered by tests
// check if the error was related to an already unplugged event - we can safely ignore
if (e.getMessage() != null && e.getMessage().contains("is already in the process of unplug")) {
logger.debug("Volume: " + vol.getPath() + " is already unplugged, ignoring the error");
return new DettachAnswer(disk);

Check warning on line 1615 in plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java

View check run for this annotation

Codecov / codecov/patch

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java#L1614-L1615

Added lines #L1614 - L1615 were not covered by tests
} else {
logger.debug("Failed to detach volume: " + vol.getPath() + ", due to ", e);
return new DettachAnswer(e.toString());

Check warning on line 1618 in plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java

View check run for this annotation

Codecov / codecov/patch

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java#L1617-L1618

Added lines #L1617 - L1618 were not covered by tests
}
} catch (final InternalErrorException e) {
logger.debug("Failed to detach volume: " + vol.getPath() + ", due to ", e);
return new DettachAnswer(e.toString());
} catch (final CloudRuntimeException e) {
logger.debug("Failed to detach volume: " + vol.getPath() + ", due to ", e);

Check warning on line 1624 in plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java

View check run for this annotation

Codecov / codecov/patch

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java#L1620-L1624

Added lines #L1620 - L1624 were not covered by tests
return new DettachAnswer(e.toString());
} finally {
vol.clearPassphrase();
Expand Down
Loading
Loading