Skip to content

Commit 6ff500d

Browse files
author
Glover, Rene (rg9975)
committed
fiberchannel and various small fixes for 4.19.2
1 parent 018e556 commit 6ff500d

File tree

17 files changed

+184
-38
lines changed

17 files changed

+184
-38
lines changed

engine/api/src/main/java/org/apache/cloudstack/engine/subsystem/api/storage/PrimaryDataStoreDriver.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,4 +157,20 @@ default boolean volumesRequireGrantAccessWhenUsed() {
157157
default boolean zoneWideVolumesAvailableWithoutClusterMotion() {
158158
return false;
159159
}
160+
161+
/**
162+
* This method returns the actual size required on the pool for a volume.
163+
*
164+
* @param volumeSize
165+
* Size of volume to be created on the store
166+
* @param templateSize
167+
* Size of template, if any, which will be used to create the volume
168+
* @param isEncryptionRequired
169+
* true if volume is encrypted
170+
*
171+
* @return the size required on the pool for the volume
172+
*/
173+
default long getVolumeSizeRequiredOnPool(long volumeSize, Long templateSize, boolean isEncryptionRequired) {
174+
return volumeSize;
175+
}
160176
}

engine/storage/datamotion/src/main/java/org/apache/cloudstack/storage/motion/StorageSystemDataMotionStrategy.java

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
4040
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
4141
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreCapabilities;
42+
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreDriver;
4243
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
4344
import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint;
4445
import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector;
@@ -104,6 +105,7 @@
104105
import com.cloud.storage.DataStoreRole;
105106
import com.cloud.storage.DiskOfferingVO;
106107
import com.cloud.storage.MigrationOptions;
108+
import com.cloud.storage.ScopeType;
107109
import com.cloud.storage.Snapshot;
108110
import com.cloud.storage.SnapshotVO;
109111
import com.cloud.storage.Storage;
@@ -919,11 +921,17 @@ private HostVO getHostOnWhichToExecuteMigrationCommand(VolumeInfo srcVolumeInfo,
919921

920922
HostVO hostVO;
921923

922-
if (srcStoragePoolVO.getClusterId() != null) {
923-
hostVO = getHostInCluster(srcStoragePoolVO.getClusterId());
924-
}
925-
else {
926-
hostVO = getHost(destVolumeInfo.getDataCenterId(), HypervisorType.KVM, false);
924+
// if either source or destination is a local storage pool, the migration MUST be performed on that host
925+
if (ScopeType.HOST.equals(srcVolumeInfo.getDataStore().getScope().getScopeType())) {
926+
hostVO = _hostDao.findById(srcVolumeInfo.getDataStore().getScope().getScopeId());
927+
} else if (ScopeType.HOST.equals(destVolumeInfo.getDataStore().getScope().getScopeType())) {
928+
hostVO = _hostDao.findById(destVolumeInfo.getDataStore().getScope().getScopeId());
929+
} else {
930+
if (srcStoragePoolVO.getClusterId() != null) {
931+
hostVO = getHostInCluster(srcStoragePoolVO.getClusterId());
932+
} else {
933+
hostVO = getHost(destVolumeInfo.getDataCenterId(), HypervisorType.KVM, false);
934+
}
927935
}
928936

929937
return hostVO;
@@ -1524,6 +1532,16 @@ private void handleCreateVolumeFromTemplateBothOnStorageSystem(TemplateInfo temp
15241532
verifyFormat(templateInfo.getFormat());
15251533
}
15261534

1535+
// this blurb handles the case where the storage system can clone a volume from a template
1536+
String canCloneVolumeFromTemplate = templateInfo.getDataStore().getDriver().getCapabilities().get("CAN_CLONE_VOLUME_FROM_TEMPLATE");
1537+
if (canCloneVolumeFromTemplate != null && canCloneVolumeFromTemplate.toLowerCase().equals("true")) {
1538+
DataStoreDriver driver = templateInfo.getDataStore().getDriver();
1539+
driver.createAsync(volumeInfo.getDataStore(), volumeInfo, null);
1540+
volumeInfo = _volumeDataFactory.getVolume(volumeInfo.getId(), volumeInfo.getDataStore());
1541+
driver.copyAsync(templateInfo, volumeInfo, null);
1542+
return;
1543+
}
1544+
15271545
HostVO hostVO = null;
15281546

15291547
final boolean computeClusterSupportsVolumeClone;
@@ -1559,6 +1577,8 @@ else if (volumeInfo.getFormat() == ImageFormat.OVA) {
15591577
}
15601578
}
15611579

1580+
1581+
15621582
VolumeDetailVO volumeDetail = new VolumeDetailVO(volumeInfo.getId(),
15631583
"cloneOfTemplate",
15641584
String.valueOf(templateInfo.getId()),
@@ -1631,7 +1651,7 @@ else if (volumeInfo.getFormat() == ImageFormat.OVA) {
16311651
errMsg = "Create volume from template failed: " + ex.getMessage();
16321652
}
16331653

1634-
throw new CloudRuntimeException(errMsg);
1654+
throw new CloudRuntimeException(errMsg, ex);
16351655
}
16361656
finally {
16371657
if (copyCmdAnswer == null) {
@@ -1902,7 +1922,7 @@ private void deleteVolumeFromSnapshot(SnapshotInfo snapshotInfo) {
19021922
}
19031923

19041924
} catch (Throwable e) {
1905-
LOGGER.warn("Failed to clean up temporary volume created for copy from a snapshot, transction will not be failed but an adminstrator should clean this up: " + snapshotInfo.getUuid() + " - " + snapshotInfo.getPath(), e);
1925+
LOGGER.warn("Failed to clean up temporary volume created for copy from a snapshot, transaction will not be failed but an administrator should clean this up: " + snapshotInfo.getUuid() + " - " + snapshotInfo.getPath(), e);
19061926
}
19071927
}
19081928

@@ -2651,7 +2671,7 @@ private void handleCreateTemplateFromManagedVolume(VolumeInfo volumeInfo, Templa
26512671
catch (Exception ex) {
26522672
errMsg = ex.getMessage();
26532673

2654-
throw new CloudRuntimeException(errMsg);
2674+
throw new CloudRuntimeException(errMsg, ex);
26552675
}
26562676
finally {
26572677
if (copyCmdAnswer == null) {

engine/storage/volume/src/main/java/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1033,7 +1033,9 @@ private void copyTemplateToManagedTemplateVolume(TemplateInfo srcTemplateInfo, T
10331033
try {
10341034
grantAccess(templateOnPrimary, destHost, destPrimaryDataStore);
10351035
} catch (Exception e) {
1036-
throw new StorageAccessException("Unable to grant access to template: " + templateOnPrimary.getId() + " on host: " + destHost.getId());
1036+
StorageAccessException e2 = new StorageAccessException("Unable to grant access to template: " + templateOnPrimary.getId() + " on host: " + destHost.getId());
1037+
e2.initCause(e);
1038+
throw e;
10371039
}
10381040

10391041
templateOnPrimary.processEvent(Event.CopyingRequested);

framework/spring/lifecycle/src/main/java/org/apache/cloudstack/spring/lifecycle/CloudStackExtendedLifeCycle.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,11 @@ public void startBeans() {
7171
with(new WithComponentLifeCycle() {
7272
@Override
7373
public void with(ComponentLifecycle lifecycle) {
74-
lifecycle.start();
74+
try {
75+
lifecycle.start();
76+
} catch (Throwable e) {
77+
log.warn("Unable to start component: " + lifecycle.getName(), e);
78+
}
7579

7680
if (lifecycle instanceof ManagementBean) {
7781
ManagementBean mbean = (ManagementBean)lifecycle;
@@ -115,6 +119,9 @@ public void with(ComponentLifecycle lifecycle) {
115119
} catch (ConfigurationException e) {
116120
log.error("Failed to configure " + lifecycle.getName(), e);
117121
throw new CloudRuntimeException(e);
122+
} catch (Throwable e) {
123+
log.error("Failed to configure " + lifecycle.getName(), e);
124+
throw new CloudRuntimeException(e);
118125
}
119126
}
120127
});

framework/spring/lifecycle/src/main/java/org/apache/cloudstack/spring/lifecycle/registry/RegistryLifecycle.java

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -108,10 +108,15 @@ public void start() {
108108

109109
while (iter.hasNext()) {
110110
Object next = iter.next();
111-
if (registry.register(next)) {
112-
log.debug("Registered " + next);
113-
} else {
114-
iter.remove();
111+
try {
112+
if (registry.register(next)) {
113+
log.debug("Registered " + next);
114+
} else {
115+
log.warn("Bean registration failed for " + next.toString());
116+
iter.remove();
117+
}
118+
} catch (Throwable e) {
119+
log.warn("Bean registration attempt resulted in an exception for " + next.toString(), e);
115120
}
116121
}
117122
}

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ public String toString() {
184184
guestDef.append("<entry name='manufacturer'>Apache Software Foundation</entry>\n");
185185
guestDef.append("<entry name='product'>CloudStack " + _type.toString() + " Hypervisor</entry>\n");
186186
guestDef.append("<entry name='uuid'>" + _uuid + "</entry>\n");
187+
guestDef.append("<entry name='serial'>" + _uuid + "</entry>\n");
187188
guestDef.append("</system>\n");
188189
guestDef.append("</sysinfo>\n");
189190

@@ -222,7 +223,9 @@ public String toString() {
222223
guestDef.append("<boot dev='" + bo + "'/>\n");
223224
}
224225
}
225-
guestDef.append("<smbios mode='sysinfo'/>\n");
226+
if (_arch == null || !_arch.equals("aarch64")) {
227+
guestDef.append("<smbios mode='sysinfo'/>\n");
228+
}
226229
guestDef.append("</os>\n");
227230
if (iothreads) {
228231
guestDef.append(String.format("<iothreads>%s</iothreads>", NUMBER_OF_IOTHREADS));

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtGetUnmanagedInstancesCommandWrapper.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,10 @@ private UnmanagedInstanceTO getUnmanagedInstance(LibvirtComputingResource libvir
124124
instance.setName(domain.getName());
125125

126126
instance.setCpuCores((int) LibvirtComputingResource.countDomainRunningVcpus(domain));
127-
instance.setCpuSpeed(parser.getCpuTuneDef().getShares()/instance.getCpuCores());
127+
128+
if (parser.getCpuTuneDef() != null && instance.getCpuCores() != null) {
129+
instance.setCpuSpeed(parser.getCpuTuneDef().getShares()/instance.getCpuCores());
130+
}
128131

129132
if (parser.getCpuModeDef() != null) {
130133
instance.setCpuCoresPerSocket(parser.getCpuModeDef().getCoresPerSocket());

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

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,7 @@ public Answer copyTemplateToPrimaryStorage(final CopyCommand cmd) {
270270

271271
if (!storagePoolMgr.connectPhysicalDisk(primaryStore.getPoolType(), primaryStore.getUuid(), path, details)) {
272272
s_logger.warn("Failed to connect physical disk at path: " + path + ", in storage pool id: " + primaryStore.getUuid());
273+
return new PrimaryStorageDownloadAnswer("Failed to spool template disk at path: " + path + ", in storage pool id: " + primaryStore.getUuid());
273274
}
274275

275276
primaryVol = storagePoolMgr.copyPhysicalDisk(tmplVol, path != null ? path : destTempl.getUuid(), primaryPool, cmd.getWaitInMillSeconds());
@@ -413,7 +414,7 @@ public Answer cloneVolumeFromBaseTemplate(final CopyCommand cmd) {
413414
if (primaryPool.getType() == StoragePoolType.CLVM) {
414415
templatePath = ((NfsTO)imageStore).getUrl() + File.separator + templatePath;
415416
vol = templateToPrimaryDownload(templatePath, primaryPool, volume.getUuid(), volume.getSize(), cmd.getWaitInMillSeconds());
416-
} if (primaryPool.getType() == StoragePoolType.PowerFlex) {
417+
} if (primaryPool.getType() == StoragePoolType.PowerFlex || primaryPool.getType() == StoragePoolType.FiberChannel) {
417418
Map<String, String> details = primaryStore.getDetails();
418419
String path = derivePath(primaryStore, destData, details);
419420

@@ -764,15 +765,19 @@ else if (srcData instanceof SnapshotObjectTO) {
764765

765766
KVMStoragePool secondaryStorage = null;
766767

768+
String path = null;
767769
try {
768770
// look for options indicating an overridden path or IQN. Used when snapshots have to be
769771
// temporarily copied on the manaaged storage device before the actual copy to target object
770772
Map<String, String> details = cmd.getOptions();
771-
String path = details != null ? details.get(DiskTO.PATH) : null;
773+
path = details != null ? details.get(DiskTO.PATH) : null;
772774
if (path == null) {
773775
path = details != null ? details.get(DiskTO.IQN) : null;
774776
if (path == null) {
775-
new CloudRuntimeException("The 'path' or 'iqn' field must be specified.");
777+
path = srcData.getPath();
778+
if (path == null) {
779+
new CloudRuntimeException("The 'path' or 'iqn' field must be specified.");
780+
}
776781
}
777782
}
778783

@@ -835,8 +840,6 @@ else if (srcData instanceof SnapshotObjectTO) {
835840
loc.addFormat(info);
836841
loc.save();
837842

838-
storagePoolMgr.disconnectPhysicalDisk(primaryStore.getPoolType(), primaryStore.getUuid(), path);
839-
840843
TemplateObjectTO newTemplate = new TemplateObjectTO();
841844

842845
newTemplate.setPath(templateFolder + File.separator + templateName + ".qcow2");
@@ -856,6 +859,10 @@ else if (srcData instanceof SnapshotObjectTO) {
856859

857860
return new CopyCmdAnswer(ex.toString());
858861
} finally {
862+
if (path != null) {
863+
storagePoolMgr.disconnectPhysicalDisk(primaryStore.getPoolType(), primaryStore.getUuid(), path);
864+
}
865+
859866
if (secondaryStorage != null) {
860867
secondaryStorage.delete();
861868
}
@@ -1031,7 +1038,9 @@ public Answer backupSnapshot(final CopyCommand cmd) {
10311038
command.add(NAME_OPTION, snapshotName);
10321039
command.add("-p", snapshotDestPath);
10331040

1034-
descName = UUID.randomUUID().toString();
1041+
if (isCreatedFromVmSnapshot) {
1042+
descName = UUID.randomUUID().toString();
1043+
}
10351044

10361045
command.add("-t", descName);
10371046
final String result = command.execute();

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/MultipathSCSIAdapterBase.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,13 @@ private KVMPhysicalDisk getPhysicalDisk(AddressInfo address, KVMStoragePool pool
160160
KVMPhysicalDisk disk = new KVMPhysicalDisk(address.getPath(), address.toString(), pool);
161161
disk.setFormat(QemuImg.PhysicalDiskFormat.RAW);
162162

163+
// validate we have a connection, if not we need to connect first.
164+
if (!isConnected(address.getPath())) {
165+
if (!connectPhysicalDisk(address, pool, null)) {
166+
throw new CloudRuntimeException("Unable to connect to volume " + address.getPath());
167+
}
168+
}
169+
163170
long diskSize = getPhysicalDiskSize(address.getPath());
164171
disk.setSize(diskSize);
165172
disk.setVirtualSize(diskSize);
@@ -197,6 +204,10 @@ public boolean connectPhysicalDisk(String volumePath, KVMStoragePool pool, Map<S
197204
// we expect WWN values in the volumePath so need to convert it to an actual physical path
198205
AddressInfo address = this.parseAndValidatePath(volumePath);
199206

207+
return connectPhysicalDisk(address, pool, details);
208+
}
209+
210+
private boolean connectPhysicalDisk(AddressInfo address, KVMStoragePool pool, Map<String, String> details) {
200211
// validate we have a connection id - we can't proceed without that
201212
if (address.getConnectionId() == null) {
202213
LOGGER.error("Unable to connect volume with address [" + address.getPath() + "] of the storage pool: " + pool.getUuid() + " - connection id is not set in provided path");
@@ -508,6 +519,19 @@ boolean waitForDiskToBecomeAvailable(AddressInfo address, KVMStoragePool pool, l
508519
return false;
509520
}
510521

522+
boolean isConnected(String path) {
523+
// run a command to test if this is a binary device at this path
524+
Script blockTest = new Script("/bin/test", LOGGER);
525+
blockTest.add("-b", path);
526+
blockTest.execute();
527+
int rc = blockTest.getExitValue();
528+
if (rc == 0) {
529+
return true;
530+
}
531+
return false;
532+
}
533+
534+
511535
long getPhysicalDiskSize(String diskPath) {
512536
if (StringUtils.isEmpty(diskPath)) {
513537
return 0;

plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterActionWorker.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,11 @@ protected IpAddress getVpcTierKubernetesPublicIp(Network network) {
362362
IpAddress address = ipAddressDao.findByUuid(detailsVO.getValue());
363363
if (address == null || network.getVpcId() != address.getVpcId()) {
364364
LOGGER.warn(String.format("Public IP with ID: %s linked to the Kubernetes cluster: %s is not usable", detailsVO.getValue(), kubernetesCluster.getName()));
365+
if (address == null) {
366+
LOGGER.warn(String.format("Public IP with ID: %s was not found by uuid", detailsVO.getValue()));
367+
} else {
368+
LOGGER.warn(String.format("Public IP with ID: %s was associated with vpc %d instead of %d", detailsVO.getValue(), address.getVpcId().longValue(), network.getVpcId().longValue()));
369+
}
365370
return null;
366371
}
367372
return address;

0 commit comments

Comments
 (0)