Merge branch '4.16' into main

This commit is contained in:
Suresh Kumar Anaparti 2022-02-02 17:30:21 +05:30
commit bf70566c2c
No known key found for this signature in database
GPG Key ID: D7CEAE3A9E71D0AA
19 changed files with 300 additions and 133 deletions

View File

@ -22,11 +22,13 @@ public class CopyToSecondaryStorageCommand extends StorageSubSystemCommand {
private String secondaryStorageUrl; private String secondaryStorageUrl;
private String systemVmIp; private String systemVmIp;
private String fileName; private String fileName;
private String nfsVersion;
public CopyToSecondaryStorageCommand(String secondaryStorageUrl, String systemVmIp, String fileName) { public CopyToSecondaryStorageCommand(String secondaryStorageUrl, String systemVmIp, String fileName, String nfsVersion) {
this.secondaryStorageUrl = secondaryStorageUrl; this.secondaryStorageUrl = secondaryStorageUrl;
this.systemVmIp = systemVmIp; this.systemVmIp = systemVmIp;
this.fileName = fileName; this.fileName = fileName;
this.nfsVersion = nfsVersion;
} }
public String getSecondaryStorageUrl() { public String getSecondaryStorageUrl() {
@ -41,6 +43,10 @@ public class CopyToSecondaryStorageCommand extends StorageSubSystemCommand {
return fileName; return fileName;
} }
public String getNfsVersion() {
return nfsVersion;
}
@Override @Override
public boolean executeInSequence() { public boolean executeInSequence() {
return false; return false;

View File

@ -3847,7 +3847,10 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
/** /**
* duplicated in {@see UserVmManagerImpl} for a {@see UserVmVO} * duplicated in {@see UserVmManagerImpl} for a {@see UserVmVO}
*/ */
private void checkIfNetworkExistsForVM(VirtualMachine virtualMachine, Network network) { private void checkIfNetworkExistsForUserVM(VirtualMachine virtualMachine, Network network) {
if (virtualMachine.getType() != VirtualMachine.Type.User) {
return; // others may have multiple nics in the same network
}
List<NicVO> allNics = _nicsDao.listByVmId(virtualMachine.getId()); List<NicVO> allNics = _nicsDao.listByVmId(virtualMachine.getId());
for (NicVO nic : allNics) { for (NicVO nic : allNics) {
if (nic.getNetworkId() == network.getId()) { if (nic.getNetworkId() == network.getId()) {
@ -3860,7 +3863,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
InsufficientCapacityException { InsufficientCapacityException {
final CallContext cctx = CallContext.current(); final CallContext cctx = CallContext.current();
checkIfNetworkExistsForVM(vm, network); checkIfNetworkExistsForUserVM(vm, network);
s_logger.debug("Adding vm " + vm + " to network " + network + "; requested nic profile " + requested); s_logger.debug("Adding vm " + vm + " to network " + network + "; requested nic profile " + requested);
final VMInstanceVO vmVO = _vmDao.findById(vm.getId()); final VMInstanceVO vmVO = _vmDao.findById(vm.getId());
final ReservationContext context = new ReservationContextImpl(null, null, cctx.getCallingUser(), cctx.getCallingAccount()); final ReservationContext context = new ReservationContextImpl(null, null, cctx.getCallingUser(), cctx.getCallingAccount());

View File

@ -30,4 +30,6 @@ public interface DiskOfferingDao extends GenericDao<DiskOfferingVO, Long> {
List<DiskOfferingVO> listAllBySizeAndProvisioningType(long size, Storage.ProvisioningType provisioningType); List<DiskOfferingVO> listAllBySizeAndProvisioningType(long size, Storage.ProvisioningType provisioningType);
List<DiskOfferingVO> findCustomDiskOfferings();
} }

View File

@ -140,6 +140,16 @@ public class DiskOfferingDaoImpl extends GenericDaoBase<DiskOfferingVO, Long> im
} }
} }
@Override
public List<DiskOfferingVO> findCustomDiskOfferings() {
SearchBuilder<DiskOfferingVO> sb = createSearchBuilder();
sb.and("customized", sb.entity().isCustomized(), SearchCriteria.Op.EQ);
sb.done();
SearchCriteria<DiskOfferingVO> sc = sb.create();
sc.setParameters("customized", true);
return listBy(sc);
}
@Override @Override
public boolean remove(Long id) { public boolean remove(Long id) {
DiskOfferingVO diskOffering = createForUpdate(); DiskOfferingVO diskOffering = createForUpdate();

View File

@ -18,31 +18,15 @@
*/ */
package org.apache.cloudstack.storage.image; package org.apache.cloudstack.storage.image;
import java.util.Map;
import javax.inject.Inject;
import org.apache.cloudstack.storage.datastore.db.ImageStoreDetailsDao;
import com.cloud.capacity.CapacityManager; import com.cloud.capacity.CapacityManager;
public abstract class NfsImageStoreDriverImpl extends BaseImageStoreDriverImpl { public abstract class NfsImageStoreDriverImpl extends BaseImageStoreDriverImpl {
@Inject
ImageStoreDetailsDao _imageStoreDetailsDao;
/** /**
* Retrieve NFS version to be used for imgStoreId store, if provided in image_store_details table * Retrieve the NFS version to be used for the imgStoreId store
* @param imgStoreId store id
* @return "secstorage.nfs.version" associated value for imgStoreId in image_store_details table if exists, null if not
*/ */
protected String getNfsVersion(long imgStoreId){ protected String getNfsVersion(long imgStoreId) {
Map<String, String> imgStoreDetails = _imageStoreDetailsDao.getDetails(imgStoreId); return CapacityManager.ImageStoreNFSVersion.valueIn(imgStoreId);
String nfsVersionKey = CapacityManager.ImageStoreNFSVersion.key();
if (imgStoreDetails != null && imgStoreDetails.containsKey(nfsVersionKey)){
return imgStoreDetails.get(nfsVersionKey);
}
return null;
} }
} }

View File

@ -226,6 +226,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
protected static final HashMap<VmPowerState, PowerState> s_powerStatesTable; protected static final HashMap<VmPowerState, PowerState> s_powerStatesTable;
public static final String XS_TOOLS_ISO_AFTER_70 = "guest-tools.iso"; public static final String XS_TOOLS_ISO_AFTER_70 = "guest-tools.iso";
protected static final String PLATFORM_CORES_PER_SOCKET_KEY = "cores-per-socket";
static { static {
s_powerStatesTable = new HashMap<VmPowerState, PowerState>(); s_powerStatesTable = new HashMap<VmPowerState, PowerState>();
@ -1110,8 +1111,8 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
return cdromVBD; return cdromVBD;
} }
protected boolean createSecondaryStorageFolder(final Connection conn, final String remoteMountPath, final String newFolder) { protected boolean createSecondaryStorageFolder(final Connection conn, final String remoteMountPath, final String newFolder, final String nfsVersion) {
final String result = callHostPlugin(conn, "vmopsSnapshot", "create_secondary_storage_folder", "remoteMountPath", remoteMountPath, "newFolder", newFolder); final String result = callHostPlugin(conn, "vmopsSnapshot", "create_secondary_storage_folder", "remoteMountPath", remoteMountPath, "newFolder", newFolder, "nfsVersion", nfsVersion);
return result != null; return result != null;
} }
@ -1482,8 +1483,8 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
return vm; return vm;
} }
protected boolean deleteSecondaryStorageFolder(final Connection conn, final String remoteMountPath, final String folder) { protected boolean deleteSecondaryStorageFolder(final Connection conn, final String remoteMountPath, final String folder, final String nfsVersion) {
final String details = callHostPlugin(conn, "vmopsSnapshot", "delete_secondary_storage_folder", "remoteMountPath", remoteMountPath, "folder", folder); final String details = callHostPlugin(conn, "vmopsSnapshot", "delete_secondary_storage_folder", "remoteMountPath", remoteMountPath, "folder", folder, "nfsVersion", nfsVersion);
return details != null && details.equals("1"); return details != null && details.equals("1");
} }
@ -1899,13 +1900,25 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
} }
} }
protected void syncPlatformAndCoresPerSocketSettings(String coresPerSocket, Map<String, String> platform) {
if (org.apache.commons.lang3.StringUtils.isBlank(coresPerSocket) || platform == null) {
return;
}
if (platform.containsKey(PLATFORM_CORES_PER_SOCKET_KEY)) {
s_logger.debug("Updating the cores per socket value from: " + platform.get(PLATFORM_CORES_PER_SOCKET_KEY) + " to " + coresPerSocket);
}
platform.put(PLATFORM_CORES_PER_SOCKET_KEY, coresPerSocket);
}
protected void finalizeVmMetaData(final VM vm, final VM.Record vmr, final Connection conn, final VirtualMachineTO vmSpec) throws Exception { protected void finalizeVmMetaData(final VM vm, final VM.Record vmr, final Connection conn, final VirtualMachineTO vmSpec) throws Exception {
final Map<String, String> details = vmSpec.getDetails(); final Map<String, String> details = vmSpec.getDetails();
if (details != null) { if (details != null) {
final String platformstring = details.get(VmDetailConstants.PLATFORM); final String platformstring = details.get(VmDetailConstants.PLATFORM);
final String coresPerSocket = details.get(VmDetailConstants.CPU_CORE_PER_SOCKET);
if (platformstring != null && !platformstring.isEmpty()) { if (platformstring != null && !platformstring.isEmpty()) {
final Map<String, String> platform = com.cloud.utils.StringUtils.stringToMap(platformstring); final Map<String, String> platform = com.cloud.utils.StringUtils.stringToMap(platformstring);
syncPlatformAndCoresPerSocketSettings(coresPerSocket, platform);
vm.setPlatform(conn, platform); vm.setPlatform(conn, platform);
} else { } else {
final String timeoffset = details.get(VmDetailConstants.TIME_OFFSET); final String timeoffset = details.get(VmDetailConstants.TIME_OFFSET);
@ -1914,10 +1927,9 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
platform.put(VmDetailConstants.TIME_OFFSET, timeoffset); platform.put(VmDetailConstants.TIME_OFFSET, timeoffset);
vm.setPlatform(conn, platform); vm.setPlatform(conn, platform);
} }
final String coresPerSocket = details.get(VmDetailConstants.CPU_CORE_PER_SOCKET);
if (coresPerSocket != null) { if (coresPerSocket != null) {
final Map<String, String> platform = vm.getPlatform(conn); final Map<String, String> platform = vm.getPlatform(conn);
platform.put("cores-per-socket", coresPerSocket); syncPlatformAndCoresPerSocketSettings(coresPerSocket, platform);
vm.setPlatform(conn, platform); vm.setPlatform(conn, platform);
} }
} }
@ -4102,7 +4114,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
} }
protected boolean postCreatePrivateTemplate(final Connection conn, final String templatePath, final String tmpltFilename, final String templateName, String templateDescription, String checksum, protected boolean postCreatePrivateTemplate(final Connection conn, final String templatePath, final String tmpltFilename, final String templateName, String templateDescription, String checksum,
final long size, final long virtualSize, final long templateId) { final long size, final long virtualSize, final long templateId, final String nfsVersion) {
if (templateDescription == null) { if (templateDescription == null) {
templateDescription = ""; templateDescription = "";
@ -4113,7 +4125,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
} }
final String result = callHostPlugin(conn, "vmopsSnapshot", "post_create_private_template", "templatePath", templatePath, "templateFilename", tmpltFilename, "templateName", templateName, final String result = callHostPlugin(conn, "vmopsSnapshot", "post_create_private_template", "templatePath", templatePath, "templateFilename", tmpltFilename, "templateName", templateName,
"templateDescription", templateDescription, "checksum", checksum, "size", String.valueOf(size), "virtualSize", String.valueOf(virtualSize), "templateId", String.valueOf(templateId)); "templateDescription", templateDescription, "checksum", checksum, "size", String.valueOf(size), "virtualSize", String.valueOf(virtualSize), "templateId", String.valueOf(templateId), "nfsVersion", nfsVersion);
boolean success = false; boolean success = false;
if (result != null && !result.isEmpty()) { if (result != null && !result.isEmpty()) {
@ -5661,6 +5673,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
String secondaryStorageUrl = cmd.getSecondaryStorageUrl(); String secondaryStorageUrl = cmd.getSecondaryStorageUrl();
String vmIP = cmd.getSystemVmIp(); String vmIP = cmd.getSystemVmIp();
String diagnosticsZipFile = cmd.getFileName(); String diagnosticsZipFile = cmd.getFileName();
String nfsVersion = cmd.getNfsVersion();
String localDir = null; String localDir = null;
boolean success; boolean success;
@ -5671,7 +5684,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
URI uri = new URI(secondaryStorageUrl); URI uri = new URI(secondaryStorageUrl);
secondaryStorageMountPath = uri.getHost() + ":" + uri.getPath(); secondaryStorageMountPath = uri.getHost() + ":" + uri.getPath();
localDir = BASE_MOUNT_POINT_ON_REMOTE + UUID.nameUUIDFromBytes(secondaryStorageMountPath.getBytes()); localDir = BASE_MOUNT_POINT_ON_REMOTE + UUID.nameUUIDFromBytes(secondaryStorageMountPath.getBytes());
String mountPoint = mountNfs(conn, secondaryStorageMountPath, localDir); String mountPoint = mountNfs(conn, secondaryStorageMountPath, localDir, nfsVersion);
if (StringUtils.isBlank(mountPoint)) { if (StringUtils.isBlank(mountPoint)) {
return new CopyToSecondaryStorageAnswer(cmd, false, "Could not mount secondary storage " + secondaryStorageMountPath + " on host " + localDir); return new CopyToSecondaryStorageAnswer(cmd, false, "Could not mount secondary storage " + secondaryStorageMountPath + " on host " + localDir);
} }
@ -5698,11 +5711,11 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
} }
} }
private String mountNfs(Connection conn, String remoteDir, String localDir) { private String mountNfs(Connection conn, String remoteDir, String localDir, String nfsVersion) {
if (localDir == null) { if (localDir == null) {
localDir = BASE_MOUNT_POINT_ON_REMOTE + UUID.nameUUIDFromBytes(remoteDir.getBytes()); localDir = BASE_MOUNT_POINT_ON_REMOTE + UUID.nameUUIDFromBytes(remoteDir.getBytes());
} }
return callHostPlugin(conn, "cloud-plugin-storage", "mountNfsSecondaryStorage", "localDir", localDir, "remoteDir", remoteDir); return callHostPlugin(conn, "cloud-plugin-storage", "mountNfsSecondaryStorage", "localDir", localDir, "remoteDir", remoteDir, "nfsVersion", nfsVersion);
} }
// Unmount secondary storage from host // Unmount secondary storage from host

View File

@ -916,8 +916,9 @@ public class XenServerStorageProcessor implements StorageProcessor {
try { try {
final NfsTO nfsStore = (NfsTO) destStore; final NfsTO nfsStore = (NfsTO) destStore;
final URI uri = new URI(nfsStore.getUrl()); final URI uri = new URI(nfsStore.getUrl());
final String nfsVersion = nfsStore.getNfsVersion();
// Create the volume folder // Create the volume folder
if (!hypervisorResource.createSecondaryStorageFolder(conn, uri.getHost() + ":" + uri.getPath(), destVolume.getPath())) { if (!hypervisorResource.createSecondaryStorageFolder(conn, uri.getHost() + ":" + uri.getPath(), destVolume.getPath(), nfsVersion)) {
throw new InternalErrorException("Failed to create the volume folder."); throw new InternalErrorException("Failed to create the volume folder.");
} }
@ -1179,6 +1180,7 @@ public class XenServerStorageProcessor implements StorageProcessor {
secondaryStorageUrl = cacheStore.getUrl(); secondaryStorageUrl = cacheStore.getUrl();
destPath = destData.getPath(); destPath = destData.getPath();
} }
String nfsVersion = cacheStore.getNfsVersion();
final SnapshotObjectTO snapshotTO = (SnapshotObjectTO) srcData; final SnapshotObjectTO snapshotTO = (SnapshotObjectTO) srcData;
final SnapshotObjectTO snapshotOnImage = (SnapshotObjectTO) destData; final SnapshotObjectTO snapshotOnImage = (SnapshotObjectTO) destData;
@ -1235,7 +1237,7 @@ public class XenServerStorageProcessor implements StorageProcessor {
if (fullbackup) { if (fullbackup) {
// the first snapshot is always a full snapshot // the first snapshot is always a full snapshot
if (!hypervisorResource.createSecondaryStorageFolder(conn, secondaryStorageMountPath, folder)) { if (!hypervisorResource.createSecondaryStorageFolder(conn, secondaryStorageMountPath, folder, nfsVersion)) {
details = " Filed to create folder " + folder + " in secondary storage"; details = " Filed to create folder " + folder + " in secondary storage";
s_logger.warn(details); s_logger.warn(details);
return new CopyCmdAnswer(details); return new CopyCmdAnswer(details);
@ -1349,6 +1351,7 @@ public class XenServerStorageProcessor implements StorageProcessor {
final TemplateObjectTO template = (TemplateObjectTO) cmd.getDestTO(); final TemplateObjectTO template = (TemplateObjectTO) cmd.getDestTO();
final NfsTO destStore = (NfsTO) cmd.getDestTO().getDataStore(); final NfsTO destStore = (NfsTO) cmd.getDestTO().getDataStore();
final int wait = cmd.getWait(); final int wait = cmd.getWait();
final String nfsVersion = destStore.getNfsVersion();
final String secondaryStoragePoolURL = destStore.getUrl(); final String secondaryStoragePoolURL = destStore.getUrl();
final String volumeUUID = volume.getPath(); final String volumeUUID = volume.getPath();
@ -1364,7 +1367,7 @@ public class XenServerStorageProcessor implements StorageProcessor {
final URI uri = new URI(secondaryStoragePoolURL); final URI uri = new URI(secondaryStoragePoolURL);
secondaryStorageMountPath = uri.getHost() + ":" + uri.getPath(); secondaryStorageMountPath = uri.getHost() + ":" + uri.getPath();
installPath = template.getPath(); installPath = template.getPath();
if (!hypervisorResource.createSecondaryStorageFolder(conn, secondaryStorageMountPath, installPath)) { if (!hypervisorResource.createSecondaryStorageFolder(conn, secondaryStorageMountPath, installPath, nfsVersion)) {
details = " Filed to create folder " + installPath + " in secondary storage"; details = " Filed to create folder " + installPath + " in secondary storage";
s_logger.warn(details); s_logger.warn(details);
return new CopyCmdAnswer(details); return new CopyCmdAnswer(details);
@ -1391,7 +1394,7 @@ public class XenServerStorageProcessor implements StorageProcessor {
final String templatePath = secondaryStorageMountPath + "/" + installPath; final String templatePath = secondaryStorageMountPath + "/" + installPath;
result = result =
hypervisorResource.postCreatePrivateTemplate(conn, templatePath, tmpltFilename, tmpltUUID, userSpecifiedName, null, physicalSize, virtualSize, hypervisorResource.postCreatePrivateTemplate(conn, templatePath, tmpltFilename, tmpltUUID, userSpecifiedName, null, physicalSize, virtualSize,
template.getId()); template.getId(), nfsVersion);
if (!result) { if (!result) {
throw new CloudRuntimeException("Could not create the template.properties file on secondary storage dir: " + tmpltURI); throw new CloudRuntimeException("Could not create the template.properties file on secondary storage dir: " + tmpltURI);
} }
@ -1411,7 +1414,7 @@ public class XenServerStorageProcessor implements StorageProcessor {
hypervisorResource.removeSR(conn, tmpltSR); hypervisorResource.removeSR(conn, tmpltSR);
} }
if (secondaryStorageMountPath != null) { if (secondaryStorageMountPath != null) {
hypervisorResource.deleteSecondaryStorageFolder(conn, secondaryStorageMountPath, installPath); hypervisorResource.deleteSecondaryStorageFolder(conn, secondaryStorageMountPath, installPath, nfsVersion);
} }
details = "Creating template from volume " + volumeUUID + " failed due to " + e.toString(); details = "Creating template from volume " + volumeUUID + " failed due to " + e.toString();
s_logger.error(details, e); s_logger.error(details, e);
@ -1465,7 +1468,8 @@ public class XenServerStorageProcessor implements StorageProcessor {
final String destNfsPath = destUri.getHost() + ":" + destUri.getPath(); final String destNfsPath = destUri.getHost() + ":" + destUri.getPath();
if (!hypervisorResource.createSecondaryStorageFolder(conn, destNfsPath, destDir)) { String destNfsVersion = destStore.getNfsVersion();
if (!hypervisorResource.createSecondaryStorageFolder(conn, destNfsPath, destDir, destNfsVersion)) {
final String details = " Failed to create folder " + destDir + " in secondary storage"; final String details = " Failed to create folder " + destDir + " in secondary storage";
s_logger.warn(details); s_logger.warn(details);
@ -1500,7 +1504,7 @@ public class XenServerStorageProcessor implements StorageProcessor {
templatePath = templatePath.replaceAll("//", "/"); templatePath = templatePath.replaceAll("//", "/");
result = hypervisorResource.postCreatePrivateTemplate(conn, templatePath, templateFilename, templateUuid, userSpecifiedTemplateName, null, result = hypervisorResource.postCreatePrivateTemplate(conn, templatePath, templateFilename, templateUuid, userSpecifiedTemplateName, null,
physicalSize, virtualSize, templateObjTO.getId()); physicalSize, virtualSize, templateObjTO.getId(), destNfsVersion);
if (!result) { if (!result) {
throw new CloudRuntimeException("Could not create the template.properties file on secondary storage dir: " + templateUri); throw new CloudRuntimeException("Could not create the template.properties file on secondary storage dir: " + templateUri);

View File

@ -73,11 +73,11 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor {
super(resource); super(resource);
} }
private void mountNfs(Connection conn, String remoteDir, String localDir) { private void mountNfs(Connection conn, String remoteDir, String localDir, String nfsVersion) {
if (localDir == null) { if (localDir == null) {
localDir = BASE_MOUNT_POINT_ON_REMOTE + UUID.nameUUIDFromBytes(remoteDir.getBytes()); localDir = BASE_MOUNT_POINT_ON_REMOTE + UUID.nameUUIDFromBytes(remoteDir.getBytes());
} }
String result = hypervisorResource.callHostPluginAsync(conn, "cloud-plugin-storage", "mountNfsSecondaryStorage", 100 * 1000, "localDir", localDir, "remoteDir", remoteDir); String result = hypervisorResource.callHostPluginAsync(conn, "cloud-plugin-storage", "mountNfsSecondaryStorage", 100 * 1000, "localDir", localDir, "remoteDir", remoteDir, "nfsVersion", nfsVersion);
if (StringUtils.isBlank(result)) { if (StringUtils.isBlank(result)) {
String errMsg = "Could not mount secondary storage " + remoteDir + " on host " + localDir; String errMsg = "Could not mount secondary storage " + remoteDir + " on host " + localDir;
s_logger.warn(errMsg); s_logger.warn(errMsg);
@ -244,9 +244,9 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor {
} }
} }
protected SR createFileSr(Connection conn, String remotePath, String dir) { protected SR createFileSr(Connection conn, String remotePath, String dir, String nfsVersion) {
String localDir = BASE_MOUNT_POINT_ON_REMOTE + UUID.nameUUIDFromBytes(remotePath.getBytes()); String localDir = BASE_MOUNT_POINT_ON_REMOTE + UUID.nameUUIDFromBytes(remotePath.getBytes());
mountNfs(conn, remotePath, localDir); mountNfs(conn, remotePath, localDir, nfsVersion);
return createFileSR(conn, localDir + "/" + dir); return createFileSR(conn, localDir + "/" + dir);
} }
@ -269,6 +269,7 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor {
final String storeUrl = srcImageStore.getUrl(); final String storeUrl = srcImageStore.getUrl();
final URI uri = new URI(storeUrl); final URI uri = new URI(storeUrl);
String volumePath = srcData.getPath(); String volumePath = srcData.getPath();
String nfsVersion = srcImageStore.getNfsVersion();
volumePath = StringUtils.stripEnd(volumePath, "/"); volumePath = StringUtils.stripEnd(volumePath, "/");
@ -282,7 +283,7 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor {
volumeDirectory = volumePath.substring(0, index); volumeDirectory = volumePath.substring(0, index);
} }
srcSr = createFileSr(conn, uri.getHost() + ":" + uri.getPath(), volumeDirectory); srcSr = createFileSr(conn, uri.getHost() + ":" + uri.getPath(), volumeDirectory, nfsVersion);
final Set<VDI> setVdis = srcSr.getVDIs(conn); final Set<VDI> setVdis = srcSr.getVDIs(conn);
@ -416,7 +417,7 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor {
} }
protected String backupSnapshot(final Connection conn, final String primaryStorageSRUuid, final String localMountPoint, final String path, final String secondaryStorageMountPath, protected String backupSnapshot(final Connection conn, final String primaryStorageSRUuid, final String localMountPoint, final String path, final String secondaryStorageMountPath,
final String snapshotUuid, String prevBackupUuid, final String prevSnapshotUuid, final Boolean isISCSI, int wait) { final String snapshotUuid, String prevBackupUuid, final String prevSnapshotUuid, final Boolean isISCSI, int wait, String nfsVersion) {
boolean filesrcreated = false; boolean filesrcreated = false;
// boolean copied = false; // boolean copied = false;
@ -427,7 +428,7 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor {
final String remoteDir = secondaryStorageMountPath; final String remoteDir = secondaryStorageMountPath;
try { try {
ssSR = createFileSr(conn, remoteDir, path); ssSR = createFileSr(conn, remoteDir, path, nfsVersion);
filesrcreated = true; filesrcreated = true;
final VDI snapshotvdi = VDI.getByUuid(conn, snapshotUuid); final VDI snapshotvdi = VDI.getByUuid(conn, snapshotUuid);
@ -509,6 +510,7 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor {
secondaryStorageUrl = cacheStore.getUrl(); secondaryStorageUrl = cacheStore.getUrl();
destPath = destData.getPath(); destPath = destData.getPath();
} }
String nfsVersion = cacheStore != null ? cacheStore.getNfsVersion() : null;
final SnapshotObjectTO snapshotTO = (SnapshotObjectTO)srcData; final SnapshotObjectTO snapshotTO = (SnapshotObjectTO)srcData;
final SnapshotObjectTO snapshotOnImage = (SnapshotObjectTO)destData; final SnapshotObjectTO snapshotOnImage = (SnapshotObjectTO)destData;
@ -569,7 +571,7 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor {
Task task = null; Task task = null;
try { try {
final String localDir = BASE_MOUNT_POINT_ON_REMOTE + UUID.nameUUIDFromBytes(secondaryStorageMountPath.getBytes()); final String localDir = BASE_MOUNT_POINT_ON_REMOTE + UUID.nameUUIDFromBytes(secondaryStorageMountPath.getBytes());
mountNfs(conn, secondaryStorageMountPath, localDir); mountNfs(conn, secondaryStorageMountPath, localDir, nfsVersion);
final boolean result = makeDirectory(conn, localDir + "/" + folder); final boolean result = makeDirectory(conn, localDir + "/" + folder);
if (!result) { if (!result) {
details = " Failed to create folder " + folder + " in secondary storage"; details = " Failed to create folder " + folder + " in secondary storage";
@ -577,7 +579,7 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor {
return new CopyCmdAnswer(details); return new CopyCmdAnswer(details);
} }
snapshotSr = createFileSr(conn, secondaryStorageMountPath, folder); snapshotSr = createFileSr(conn, secondaryStorageMountPath, folder, nfsVersion);
task = snapshotVdi.copyAsync(conn, snapshotSr, null, null); task = snapshotVdi.copyAsync(conn, snapshotSr, null, null);
// poll every 1 seconds , // poll every 1 seconds ,
@ -649,7 +651,7 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor {
throw new CloudRuntimeException("S3 upload of snapshots " + snapshotPaUuid + " failed"); throw new CloudRuntimeException("S3 upload of snapshots " + snapshotPaUuid + " failed");
} }
} else { } else {
final String result = backupSnapshot(conn, primaryStorageSRUuid, localMountPoint, folder, secondaryStorageMountPath, snapshotUuid, prevBackupUuid, prevSnapshotUuid, isISCSI, wait); final String result = backupSnapshot(conn, primaryStorageSRUuid, localMountPoint, folder, secondaryStorageMountPath, snapshotUuid, prevBackupUuid, prevSnapshotUuid, isISCSI, wait, nfsVersion);
final String[] tmp = result.split("#"); final String[] tmp = result.split("#");
snapshotBackupUuid = tmp[0]; snapshotBackupUuid = tmp[0];
physicalSize = Long.parseLong(tmp[1]); physicalSize = Long.parseLong(tmp[1]);
@ -695,6 +697,7 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor {
final String secondaryStoragePoolURL = destStore.getUrl(); final String secondaryStoragePoolURL = destStore.getUrl();
final String volumeUUID = volume.getPath(); final String volumeUUID = volume.getPath();
final String nfsVersion = destStore.getNfsVersion();
final String userSpecifiedName = template.getName(); final String userSpecifiedName = template.getName();
@ -708,7 +711,7 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor {
final URI uri = new URI(secondaryStoragePoolURL); final URI uri = new URI(secondaryStoragePoolURL);
secondaryStorageMountPath = uri.getHost() + ":" + uri.getPath(); secondaryStorageMountPath = uri.getHost() + ":" + uri.getPath();
installPath = template.getPath(); installPath = template.getPath();
if (!hypervisorResource.createSecondaryStorageFolder(conn, secondaryStorageMountPath, installPath)) { if (!hypervisorResource.createSecondaryStorageFolder(conn, secondaryStorageMountPath, installPath, nfsVersion)) {
details = " Filed to create folder " + installPath + " in secondary storage"; details = " Filed to create folder " + installPath + " in secondary storage";
s_logger.warn(details); s_logger.warn(details);
return new CopyCmdAnswer(details); return new CopyCmdAnswer(details);
@ -716,7 +719,7 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor {
final VDI vol = getVDIbyUuid(conn, volumeUUID); final VDI vol = getVDIbyUuid(conn, volumeUUID);
// create template SR // create template SR
tmpltSR = createFileSr(conn, uri.getHost() + ":" + uri.getPath(), installPath); tmpltSR = createFileSr(conn, uri.getHost() + ":" + uri.getPath(), installPath, nfsVersion);
// copy volume to template SR // copy volume to template SR
task = vol.copyAsync(conn, tmpltSR, null, null); task = vol.copyAsync(conn, tmpltSR, null, null);
@ -736,7 +739,7 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor {
final long physicalSize = tmpltVDI.getPhysicalUtilisation(conn); final long physicalSize = tmpltVDI.getPhysicalUtilisation(conn);
// create the template.properties file // create the template.properties file
final String templatePath = secondaryStorageMountPath + "/" + installPath; final String templatePath = secondaryStorageMountPath + "/" + installPath;
result = hypervisorResource.postCreatePrivateTemplate(conn, templatePath, tmpltFilename, tmpltUUID, userSpecifiedName, null, physicalSize, virtualSize, template.getId()); result = hypervisorResource.postCreatePrivateTemplate(conn, templatePath, tmpltFilename, tmpltUUID, userSpecifiedName, null, physicalSize, virtualSize, template.getId(), nfsVersion);
if (!result) { if (!result) {
throw new CloudRuntimeException("Could not create the template.properties file on secondary storage dir"); throw new CloudRuntimeException("Could not create the template.properties file on secondary storage dir");
} }
@ -756,7 +759,7 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor {
hypervisorResource.removeSR(conn, tmpltSR); hypervisorResource.removeSR(conn, tmpltSR);
} }
if (secondaryStorageMountPath != null) { if (secondaryStorageMountPath != null) {
hypervisorResource.deleteSecondaryStorageFolder(conn, secondaryStorageMountPath, installPath); hypervisorResource.deleteSecondaryStorageFolder(conn, secondaryStorageMountPath, installPath, nfsVersion);
} }
details = "Creating template from volume " + volumeUUID + " failed due to " + e.toString(); details = "Creating template from volume " + volumeUUID + " failed due to " + e.toString();
s_logger.error(details, e); s_logger.error(details, e);
@ -805,6 +808,7 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor {
} }
final NfsTO nfsImageStore = (NfsTO)imageStore; final NfsTO nfsImageStore = (NfsTO)imageStore;
final String nfsVersion = nfsImageStore.getNfsVersion();
final String primaryStorageNameLabel = pool.getUuid(); final String primaryStorageNameLabel = pool.getUuid();
final String secondaryStorageUrl = nfsImageStore.getUrl(); final String secondaryStorageUrl = nfsImageStore.getUrl();
final int wait = cmd.getWait(); final int wait = cmd.getWait();
@ -851,7 +855,7 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor {
final String snapshotUuid = getSnapshotUuid(snapshotInstallPath); final String snapshotUuid = getSnapshotUuid(snapshotInstallPath);
final URI uri = new URI(secondaryStorageUrl); final URI uri = new URI(secondaryStorageUrl);
srcSr = createFileSr(conn, uri.getHost() + ":" + uri.getPath(), snapshotDirectory); srcSr = createFileSr(conn, uri.getHost() + ":" + uri.getPath(), snapshotDirectory, nfsVersion);
final String[] parents = snapshot.getParents(); final String[] parents = snapshot.getParents();
final List<VDI> snapshotChains = new ArrayList<VDI>(); final List<VDI> snapshotChains = new ArrayList<VDI>();
@ -940,14 +944,15 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor {
Task task = null; Task task = null;
try { try {
final NfsTO nfsStore = (NfsTO)destStore; final NfsTO nfsStore = (NfsTO)destStore;
final String nfsVersion = nfsStore.getNfsVersion();
final URI uri = new URI(nfsStore.getUrl()); final URI uri = new URI(nfsStore.getUrl());
// Create the volume folder // Create the volume folder
if (!hypervisorResource.createSecondaryStorageFolder(conn, uri.getHost() + ":" + uri.getPath(), destVolume.getPath())) { if (!hypervisorResource.createSecondaryStorageFolder(conn, uri.getHost() + ":" + uri.getPath(), destVolume.getPath(), nfsVersion)) {
throw new InternalErrorException("Failed to create the volume folder."); throw new InternalErrorException("Failed to create the volume folder.");
} }
// Create a SR for the volume UUID folder // Create a SR for the volume UUID folder
secondaryStorage = createFileSr(conn, uri.getHost() + ":" + uri.getPath(), destVolume.getPath()); secondaryStorage = createFileSr(conn, uri.getHost() + ":" + uri.getPath(), destVolume.getPath(), nfsVersion);
// Look up the volume on the source primary storage pool // Look up the volume on the source primary storage pool
final VDI srcVdi = getVDIbyUuid(conn, srcVolume.getPath()); final VDI srcVdi = getVDIbyUuid(conn, srcVolume.getPath());
// Copy the volume to secondary storage // Copy the volume to secondary storage
@ -992,6 +997,7 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor {
if (srcStore instanceof NfsTO) { if (srcStore instanceof NfsTO) {
final NfsTO nfsStore = (NfsTO)srcStore; final NfsTO nfsStore = (NfsTO)srcStore;
final String nfsVersion = nfsStore.getNfsVersion();
final String volumePath = srcVolume.getPath(); final String volumePath = srcVolume.getPath();
int index = volumePath.lastIndexOf("/"); int index = volumePath.lastIndexOf("/");
final String volumeDirectory = volumePath.substring(0, index); final String volumeDirectory = volumePath.substring(0, index);
@ -1006,7 +1012,7 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor {
} catch (final Exception e) { } catch (final Exception e) {
return new CopyCmdAnswer(e.toString()); return new CopyCmdAnswer(e.toString());
} }
final SR srcSr = createFileSr(conn, uri.getHost() + ":" + uri.getPath(), volumeDirectory); final SR srcSr = createFileSr(conn, uri.getHost() + ":" + uri.getPath(), volumeDirectory, nfsVersion);
Task task = null; Task task = null;
try { try {
final SR primaryStoragePool = hypervisorResource.getStorageRepository(conn, final SR primaryStoragePool = hypervisorResource.getStorageRepository(conn,
@ -1089,12 +1095,14 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor {
boolean result = false; boolean result = false;
try { try {
srcSr = createFileSr(conn, srcUri.getHost() + ":" + srcUri.getPath(), srcDir); String srcNfsVersion = srcStore.getNfsVersion();
srcSr = createFileSr(conn, srcUri.getHost() + ":" + srcUri.getPath(), srcDir, srcNfsVersion);
final String destNfsPath = destUri.getHost() + ":" + destUri.getPath(); final String destNfsPath = destUri.getHost() + ":" + destUri.getPath();
final String localDir = BASE_MOUNT_POINT_ON_REMOTE + UUID.nameUUIDFromBytes(destNfsPath.getBytes()); final String localDir = BASE_MOUNT_POINT_ON_REMOTE + UUID.nameUUIDFromBytes(destNfsPath.getBytes());
mountNfs(conn, destUri.getHost() + ":" + destUri.getPath(), localDir); String destNfsVersion = destStore.getNfsVersion();
mountNfs(conn, destUri.getHost() + ":" + destUri.getPath(), localDir, destNfsVersion);
makeDirectory(conn, localDir + "/" + destDir); makeDirectory(conn, localDir + "/" + destDir);
destSr = createFileSR(conn, localDir + "/" + destDir); destSr = createFileSR(conn, localDir + "/" + destDir);
@ -1148,7 +1156,7 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor {
templatePath = templatePath.replaceAll("//", "/"); templatePath = templatePath.replaceAll("//", "/");
result = hypervisorResource.postCreatePrivateTemplate(conn, templatePath, templateFilename, templateUuid, nameLabel, null, physicalSize, virtualSize, destObj.getId()); result = hypervisorResource.postCreatePrivateTemplate(conn, templatePath, templateFilename, templateUuid, nameLabel, null, physicalSize, virtualSize, destObj.getId(), destNfsVersion);
if (!result) { if (!result) {
throw new CloudRuntimeException("Could not create the template.properties file on secondary storage dir"); throw new CloudRuntimeException("Could not create the template.properties file on secondary storage dir");
@ -1236,7 +1244,8 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor {
final String destNfsPath = destUri.getHost() + ":" + destUri.getPath(); final String destNfsPath = destUri.getHost() + ":" + destUri.getPath();
final String localDir = BASE_MOUNT_POINT_ON_REMOTE + UUID.nameUUIDFromBytes(destNfsPath.getBytes()); final String localDir = BASE_MOUNT_POINT_ON_REMOTE + UUID.nameUUIDFromBytes(destNfsPath.getBytes());
mountNfs(conn, destNfsPath, localDir); String nfsVersion = destStore.getNfsVersion();
mountNfs(conn, destNfsPath, localDir, nfsVersion);
makeDirectory(conn, localDir + "/" + destDir); makeDirectory(conn, localDir + "/" + destDir);
destSr = createFileSR(conn, localDir + "/" + destDir); destSr = createFileSR(conn, localDir + "/" + destDir);
@ -1263,7 +1272,7 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor {
templatePath = templatePath.replaceAll("//", "/"); templatePath = templatePath.replaceAll("//", "/");
result = hypervisorResource.postCreatePrivateTemplate(conn, templatePath, templateFilename, templateUuid, nameLabel, null, physicalSize, virtualSize, templateObjTO.getId()); result = hypervisorResource.postCreatePrivateTemplate(conn, templatePath, templateFilename, templateUuid, nameLabel, null, physicalSize, virtualSize, templateObjTO.getId(), nfsVersion);
if (!result) { if (!result) {
throw new CloudRuntimeException("Could not create the template.properties file on secondary storage dir"); throw new CloudRuntimeException("Could not create the template.properties file on secondary storage dir");

View File

@ -23,6 +23,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import com.cloud.utils.StringUtils;
import org.apache.xmlrpc.XmlRpcException; import org.apache.xmlrpc.XmlRpcException;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Before; import org.junit.Before;
@ -51,6 +52,8 @@ import com.xensource.xenapi.PBD;
import com.xensource.xenapi.SR; import com.xensource.xenapi.SR;
import com.xensource.xenapi.Types.XenAPIException; import com.xensource.xenapi.Types.XenAPIException;
import static com.cloud.hypervisor.xenserver.resource.CitrixResourceBase.PLATFORM_CORES_PER_SOCKET_KEY;
@RunWith(PowerMockRunner.class) @RunWith(PowerMockRunner.class)
@PrepareForTest({Host.class, Script.class, SR.class}) @PrepareForTest({Host.class, Script.class, SR.class})
public class CitrixResourceBaseTest { public class CitrixResourceBaseTest {
@ -72,6 +75,8 @@ public class CitrixResourceBaseTest {
private String hostUuidMock = "hostUuidMock"; private String hostUuidMock = "hostUuidMock";
private static final String platformString = "device-model:qemu-upstream-compat;vga:std;videoram:8;apic:true;viridian:false;timeoffset:0;pae:true;acpi:1;hpet:true;secureboot:false;nx:true";
@Before @Before
public void beforeTest() throws XenAPIException, XmlRpcException { public void beforeTest() throws XenAPIException, XmlRpcException {
citrixResourceBase._host.setUuid(hostUuidMock); citrixResourceBase._host.setUuid(hostUuidMock);
@ -369,4 +374,32 @@ public class CitrixResourceBaseTest {
Assert.assertEquals(1, startUpCommandsForLocalStorage.size()); Assert.assertEquals(1, startUpCommandsForLocalStorage.size());
} }
@Test
public void syncPlatformAndCoresPerSocketSettingsEmptyCoresPerSocket() {
String coresPerSocket = null;
Map<String, String> platform = Mockito.mock(Map.class);
citrixResourceBase.syncPlatformAndCoresPerSocketSettings(coresPerSocket, platform);
Mockito.verify(platform, Mockito.never()).put(Mockito.any(), Mockito.any());
Mockito.verify(platform, Mockito.never()).remove(Mockito.any());
}
@Test
public void syncPlatformAndCoresPerSocketSettingsEmptyCoresPerSocketOnPlatform() {
String coresPerSocket = "2";
Map<String, String> platform = StringUtils.stringToMap(platformString);
citrixResourceBase.syncPlatformAndCoresPerSocketSettings(coresPerSocket, platform);
Assert.assertTrue(platform.containsKey(PLATFORM_CORES_PER_SOCKET_KEY));
Assert.assertEquals(coresPerSocket, platform.get(PLATFORM_CORES_PER_SOCKET_KEY));
}
@Test
public void syncPlatformAndCoresPerSocketSettingsUpdateCoresPerSocketOnPlatform() {
String coresPerSocket = "2";
String platformStr = platformString + "," + PLATFORM_CORES_PER_SOCKET_KEY + ":3";
Map<String, String> platform = StringUtils.stringToMap(platformStr);
citrixResourceBase.syncPlatformAndCoresPerSocketSettings(coresPerSocket, platform);
Assert.assertTrue(platform.containsKey(PLATFORM_CORES_PER_SOCKET_KEY));
Assert.assertEquals(coresPerSocket, platform.get(PLATFORM_CORES_PER_SOCKET_KEY));
}
} }

View File

@ -238,6 +238,8 @@ def umount(localDir):
def mountNfsSecondaryStorage(session, args): def mountNfsSecondaryStorage(session, args):
remoteDir = args['remoteDir'] remoteDir = args['remoteDir']
localDir = args['localDir'] localDir = args['localDir']
nfsVersion = args['nfsVersion']
logging.debug("mountNfsSecondaryStorage with params: " + str(args))
mounted = False mounted = False
f = open("/proc/mounts", 'r') f = open("/proc/mounts", 'r')
for line in f: for line in f:
@ -250,6 +252,8 @@ def mountNfsSecondaryStorage(session, args):
makedirs(localDir) makedirs(localDir)
options = "soft,tcp,timeo=133,retrans=1" options = "soft,tcp,timeo=133,retrans=1"
if nfsVersion:
options += ",vers=" + nfsVersion
try: try:
cmd = ['mount', '-o', options, remoteDir, localDir] cmd = ['mount', '-o', options, remoteDir, localDir]
txt = util.pread2(cmd) txt = util.pread2(cmd)

View File

@ -68,7 +68,8 @@ def create_secondary_storage_folder(session, args):
# Mount the remote resource folder locally # Mount the remote resource folder locally
remote_mount_path = args["remoteMountPath"] remote_mount_path = args["remoteMountPath"]
local_mount_path = os.path.join(CLOUD_DIR, util.gen_uuid()) local_mount_path = os.path.join(CLOUD_DIR, util.gen_uuid())
mount(remote_mount_path, local_mount_path) nfsVersion = args["nfsVersion"]
mount(remote_mount_path, local_mount_path, nfsVersion)
# Create the new folder # Create the new folder
new_folder = local_mount_path + "/" + args["newFolder"] new_folder = local_mount_path + "/" + args["newFolder"]
@ -104,7 +105,8 @@ def delete_secondary_storage_folder(session, args):
# Mount the remote resource folder locally # Mount the remote resource folder locally
remote_mount_path = args["remoteMountPath"] remote_mount_path = args["remoteMountPath"]
local_mount_path = os.path.join(CLOUD_DIR, util.gen_uuid()) local_mount_path = os.path.join(CLOUD_DIR, util.gen_uuid())
mount(remote_mount_path, local_mount_path) nfsVersion = args["nfsVersion"]
mount(remote_mount_path, local_mount_path, nfsVersion)
# Delete the specified folder # Delete the specified folder
folder = local_mount_path + "/" + args["folder"] folder = local_mount_path + "/" + args["folder"]
@ -136,7 +138,8 @@ def post_create_private_template(session, args):
# get local template folder # get local template folder
templatePath = args["templatePath"] templatePath = args["templatePath"]
local_mount_path = os.path.join(CLOUD_DIR, util.gen_uuid()) local_mount_path = os.path.join(CLOUD_DIR, util.gen_uuid())
mount(templatePath, local_mount_path) nfsVersion = args["nfsVersion"]
mount(templatePath, local_mount_path, nfsVersion)
# Retrieve args # Retrieve args
filename = args["templateFilename"] filename = args["templateFilename"]
name = args["templateName"] name = args["templateName"]
@ -307,9 +310,11 @@ def makedirs(path):
raise xs_errors.XenError(errMsg) raise xs_errors.XenError(errMsg)
return return
def mount(remoteDir, localDir): def mount(remoteDir, localDir, nfsVersion=None):
makedirs(localDir) makedirs(localDir)
options = "soft,tcp,timeo=133,retrans=1" options = "soft,tcp,timeo=133,retrans=1"
if nfsVersion:
options += ",vers=" + nfsVersion
try: try:
cmd = ['mount', '-o', options, remoteDir, localDir] cmd = ['mount', '-o', options, remoteDir, localDir]
txt = util.pread2(cmd) txt = util.pread2(cmd)

View File

@ -19,11 +19,8 @@ package com.cloud.api.query.dao;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import com.cloud.api.ApiDBUtils; import javax.inject.Inject;
import com.cloud.dc.VsphereStoragePolicyVO;
import com.cloud.dc.dao.VsphereStoragePolicyDao;
import com.cloud.server.ResourceTag;
import com.cloud.user.AccountManager;
import org.apache.cloudstack.annotation.AnnotationService; import org.apache.cloudstack.annotation.AnnotationService;
import org.apache.cloudstack.annotation.dao.AnnotationDao; import org.apache.cloudstack.annotation.dao.AnnotationDao;
import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiConstants;
@ -32,16 +29,19 @@ import org.apache.cloudstack.context.CallContext;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import com.cloud.api.ApiDBUtils;
import com.cloud.api.query.vo.DiskOfferingJoinVO; import com.cloud.api.query.vo.DiskOfferingJoinVO;
import com.cloud.dc.VsphereStoragePolicyVO;
import com.cloud.dc.dao.VsphereStoragePolicyDao;
import com.cloud.offering.DiskOffering; import com.cloud.offering.DiskOffering;
import com.cloud.offering.ServiceOffering; import com.cloud.offering.ServiceOffering;
import com.cloud.server.ResourceTag;
import com.cloud.user.AccountManager;
import com.cloud.utils.db.Attribute; import com.cloud.utils.db.Attribute;
import com.cloud.utils.db.GenericDaoBase; import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.db.SearchCriteria;
import javax.inject.Inject;
@Component @Component
public class DiskOfferingJoinDaoImpl extends GenericDaoBase<DiskOfferingJoinVO, Long> implements DiskOfferingJoinDao { public class DiskOfferingJoinDaoImpl extends GenericDaoBase<DiskOfferingJoinVO, Long> implements DiskOfferingJoinDao {
public static final Logger s_logger = Logger.getLogger(DiskOfferingJoinDaoImpl.class); public static final Logger s_logger = Logger.getLogger(DiskOfferingJoinDaoImpl.class);

View File

@ -1997,12 +1997,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
Account caller = CallContext.current().getCallingAccount(); Account caller = CallContext.current().getCallingAccount();
// Verify network id // Verify network id
NetworkVO network = _networksDao.findById(networkId); NetworkVO network = getNetworkVO(networkId, "Unable to find a network with the specified ID.");
if (network == null) {
// see NetworkVO.java
throwInvalidIdException("unable to find network with specified id", String.valueOf(networkId), "networkId");
}
// don't allow to delete system network // don't allow to delete system network
if (isNetworkSystem(network)) { if (isNetworkSystem(network)) {
@ -2032,10 +2027,20 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
@Override @Override
@ActionEvent(eventType = EventTypes.EVENT_NETWORK_RESTART, eventDescription = "restarting network", async = true) @ActionEvent(eventType = EventTypes.EVENT_NETWORK_RESTART, eventDescription = "restarting network", async = true)
public boolean restartNetwork(Long networkId, boolean cleanup, boolean makeRedundant, User user) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { public boolean restartNetwork(Long networkId, boolean cleanup, boolean makeRedundant, User user) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException {
NetworkVO network = getNetworkVO(networkId, "Network with specified id doesn't exist");
return restartNetwork(network, cleanup, makeRedundant, user);
}
private NetworkVO getNetworkVO(Long networkId, String errMsgFormat) {
NetworkVO network = _networksDao.findById(networkId); NetworkVO network = _networksDao.findById(networkId);
if (network == null) { if (network == null) {
throwInvalidIdException("Network with specified id doesn't exist", networkId.toString(), "networkId"); throwInvalidIdException(errMsgFormat, networkId.toString(), "networkId");
} }
return network;
}
@ActionEvent(eventType = EventTypes.EVENT_NETWORK_RESTART, eventDescription = "restarting network", async = true)
public boolean restartNetwork(NetworkVO network, boolean cleanup, boolean makeRedundant, User user) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException {
// Don't allow to restart network if it's not in Implemented/Setup state // Don't allow to restart network if it's not in Implemented/Setup state
if (!(network.getState() == Network.State.Implemented || network.getState() == Network.State.Setup)) { if (!(network.getState() == Network.State.Implemented || network.getState() == Network.State.Setup)) {
@ -2061,11 +2066,12 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
cleanup = true; cleanup = true;
} }
boolean success = _networkMgr.restartNetwork(networkId, callerAccount, user, cleanup); long id = network.getId();
boolean success = _networkMgr.restartNetwork(id, callerAccount, user, cleanup);
if (success) { if (success) {
s_logger.debug("Network id=" + networkId + " is restarted successfully."); s_logger.debug(String.format("Network id=%d is restarted successfully.",id));
} else { } else {
s_logger.warn("Network id=" + networkId + " failed to restart."); s_logger.warn(String.format("Network id=%d failed to restart.",id));
} }
return success; return success;
@ -2075,11 +2081,14 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
@ActionEvent(eventType = EventTypes.EVENT_NETWORK_RESTART, eventDescription = "restarting network", async = true) @ActionEvent(eventType = EventTypes.EVENT_NETWORK_RESTART, eventDescription = "restarting network", async = true)
public boolean restartNetwork(RestartNetworkCmd cmd) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { public boolean restartNetwork(RestartNetworkCmd cmd) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException {
// This method restarts all network elements belonging to the network and re-applies all the rules // This method restarts all network elements belonging to the network and re-applies all the rules
Long networkId = cmd.getNetworkId(); NetworkVO network = getNetworkVO(cmd.getNetworkId(), "Network [%s] to restart was not found.");
boolean cleanup = cmd.getCleanup(); boolean cleanup = cmd.getCleanup();
if (network.getVpcId() != null && cleanup) {
throwInvalidIdException("Cannot restart a VPC tier with cleanup, please restart the whole VPC.", network.getUuid(), "network tier");
}
boolean makeRedundant = cmd.getMakeRedundant(); boolean makeRedundant = cmd.getMakeRedundant();
User callerUser = _accountMgr.getActiveUser(CallContext.current().getCallingUserId()); User callerUser = _accountMgr.getActiveUser(CallContext.current().getCallingUserId());
return restartNetwork(networkId, cleanup, makeRedundant, callerUser); return restartNetwork(network, cleanup, makeRedundant, callerUser);
} }
@Override @Override
@ -2216,11 +2225,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
boolean restartNetwork = false; boolean restartNetwork = false;
// verify input parameters // verify input parameters
final NetworkVO network = _networksDao.findById(networkId); final NetworkVO network = getNetworkVO(networkId, "Specified network id doesn't exist in the system");
if (network == null) {
// see NetworkVO.java
throwInvalidIdException("Specified network id doesn't exist in the system", String.valueOf(networkId), "networkId");
}
//perform below validation if the network is vpc network //perform below validation if the network is vpc network
if (network.getVpcId() != null && networkOfferingId != null) { if (network.getVpcId() != null && networkOfferingId != null) {

View File

@ -133,6 +133,7 @@ import com.cloud.host.dao.HostDao;
import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.hypervisor.HypervisorCapabilitiesVO; import com.cloud.hypervisor.HypervisorCapabilitiesVO;
import com.cloud.hypervisor.dao.HypervisorCapabilitiesDao; import com.cloud.hypervisor.dao.HypervisorCapabilitiesDao;
import com.cloud.offering.DiskOffering;
import com.cloud.org.Grouping; import com.cloud.org.Grouping;
import com.cloud.resource.ResourceState; import com.cloud.resource.ResourceState;
import com.cloud.serializer.GsonHelper; import com.cloud.serializer.GsonHelper;
@ -330,6 +331,8 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
private static final Set<Volume.State> STATES_VOLUME_CANNOT_BE_DESTROYED = new HashSet<>(Arrays.asList(Volume.State.Destroy, Volume.State.Expunging, Volume.State.Expunged, Volume.State.Allocated)); private static final Set<Volume.State> STATES_VOLUME_CANNOT_BE_DESTROYED = new HashSet<>(Arrays.asList(Volume.State.Destroy, Volume.State.Expunging, Volume.State.Expunged, Volume.State.Allocated));
private static final long GiB_TO_BYTES = 1024 * 1024 * 1024; private static final long GiB_TO_BYTES = 1024 * 1024 * 1024;
private static final String CUSTOM_DISK_OFFERING_UNIQUE_NAME = "Cloud.com-Custom";
protected VolumeApiServiceImpl() { protected VolumeApiServiceImpl() {
_volStateMachine = Volume.State.getStateMachine(); _volStateMachine = Volume.State.getStateMachine();
_gson = GsonHelper.getGsonLogger(); _gson = GsonHelper.getGsonLogger();
@ -493,7 +496,6 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
if (!diskOffering.isCustomized()) { if (!diskOffering.isCustomized()) {
throw new InvalidParameterValueException("Please specify a custom sized disk offering."); throw new InvalidParameterValueException("Please specify a custom sized disk offering.");
} }
_configMgr.checkDiskOfferingAccess(volumeOwner, diskOffering, zone); _configMgr.checkDiskOfferingAccess(volumeOwner, diskOffering, zone);
} }
@ -504,12 +506,41 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
return UUID.randomUUID().toString(); return UUID.randomUUID().toString();
} }
private Long getDefaultCustomOfferingId(Account owner, DataCenter zone) {
DiskOfferingVO diskOfferingVO = _diskOfferingDao.findByUniqueName(CUSTOM_DISK_OFFERING_UNIQUE_NAME);
if (diskOfferingVO == null || !DiskOffering.State.Active.equals(diskOfferingVO.getState())) {
return null;
}
try {
_configMgr.checkDiskOfferingAccess(owner, diskOfferingVO, zone);
return diskOfferingVO.getId();
} catch (PermissionDeniedException ignored) {
}
return null;
}
private Long getCustomDiskOfferingIdForVolumeUpload(Account owner, DataCenter zone) {
Long offeringId = getDefaultCustomOfferingId(owner, zone);
if (offeringId != null) {
return offeringId;
}
List<DiskOfferingVO> offerings = _diskOfferingDao.findCustomDiskOfferings();
for (DiskOfferingVO offering : offerings) {
try {
_configMgr.checkDiskOfferingAccess(owner, offering, zone);
return offering.getId();
} catch (PermissionDeniedException ignored) {}
}
return null;
}
@DB @DB
protected VolumeVO persistVolume(final Account owner, final Long zoneId, final String volumeName, final String url, final String format, final Long diskOfferingId, final Volume.State state) { protected VolumeVO persistVolume(final Account owner, final Long zoneId, final String volumeName, final String url, final String format, final Long diskOfferingId, final Volume.State state) {
return Transaction.execute(new TransactionCallback<VolumeVO>() { return Transaction.execute(new TransactionCallbackWithException<VolumeVO, CloudRuntimeException>() {
@Override @Override
public VolumeVO doInTransaction(TransactionStatus status) { public VolumeVO doInTransaction(TransactionStatus status) {
VolumeVO volume = new VolumeVO(volumeName, zoneId, -1, -1, -1, new Long(-1), null, null, Storage.ProvisioningType.THIN, 0, Volume.Type.DATADISK); VolumeVO volume = new VolumeVO(volumeName, zoneId, -1, -1, -1, new Long(-1), null, null, Storage.ProvisioningType.THIN, 0, Volume.Type.DATADISK);
DataCenter zone = _dcDao.findById(zoneId);
volume.setPoolId(null); volume.setPoolId(null);
volume.setDataCenterId(zoneId); volume.setDataCenterId(zoneId);
volume.setPodId(null); volume.setPodId(null);
@ -519,23 +550,22 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
volume.setAccountId((owner == null) ? Account.ACCOUNT_ID_SYSTEM : owner.getAccountId()); volume.setAccountId((owner == null) ? Account.ACCOUNT_ID_SYSTEM : owner.getAccountId());
volume.setDomainId((owner == null) ? Domain.ROOT_DOMAIN : owner.getDomainId()); volume.setDomainId((owner == null) ? Domain.ROOT_DOMAIN : owner.getDomainId());
if (diskOfferingId == null) { Long volumeDiskOfferingId = diskOfferingId;
DiskOfferingVO diskOfferingVO = _diskOfferingDao.findByUniqueName("Cloud.com-Custom"); if (volumeDiskOfferingId == null) {
if (diskOfferingVO != null) { volumeDiskOfferingId = getCustomDiskOfferingIdForVolumeUpload(owner, zone);
long defaultDiskOfferingId = diskOfferingVO.getId(); if (volumeDiskOfferingId == null) {
volume.setDiskOfferingId(defaultDiskOfferingId); throw new CloudRuntimeException(String.format("Unable to find custom disk offering in zone: %s for volume upload", zone.getUuid()));
} }
} else { }
volume.setDiskOfferingId(diskOfferingId);
DiskOfferingVO diskOfferingVO = _diskOfferingDao.findById(diskOfferingId); volume.setDiskOfferingId(volumeDiskOfferingId);
DiskOfferingVO diskOfferingVO = _diskOfferingDao.findById(volumeDiskOfferingId);
Boolean isCustomizedIops = diskOfferingVO != null && diskOfferingVO.isCustomizedIops() != null ? diskOfferingVO.isCustomizedIops() : false; Boolean isCustomizedIops = diskOfferingVO != null && diskOfferingVO.isCustomizedIops() != null ? diskOfferingVO.isCustomizedIops() : false;
if (isCustomizedIops == null || !isCustomizedIops) { if (isCustomizedIops == null || !isCustomizedIops) {
volume.setMinIops(diskOfferingVO.getMinIops()); volume.setMinIops(diskOfferingVO.getMinIops());
volume.setMaxIops(diskOfferingVO.getMaxIops()); volume.setMaxIops(diskOfferingVO.getMaxIops());
}
} }
// volume.setSize(size); // volume.setSize(size);

View File

@ -30,6 +30,7 @@ import java.util.regex.Pattern;
import javax.inject.Inject; import javax.inject.Inject;
import javax.naming.ConfigurationException; import javax.naming.ConfigurationException;
import com.cloud.capacity.CapacityManager;
import org.apache.cloudstack.api.command.admin.diagnostics.GetDiagnosticsDataCmd; import org.apache.cloudstack.api.command.admin.diagnostics.GetDiagnosticsDataCmd;
import org.apache.cloudstack.api.command.admin.diagnostics.RunDiagnosticsCmd; import org.apache.cloudstack.api.command.admin.diagnostics.RunDiagnosticsCmd;
import org.apache.cloudstack.diagnostics.fileprocessor.DiagnosticsFilesList; import org.apache.cloudstack.diagnostics.fileprocessor.DiagnosticsFilesList;
@ -312,7 +313,8 @@ public class DiagnosticsServiceImpl extends ManagerBase implements PluggableServ
} }
private Pair<Boolean, String> copyToSecondaryStorageNonVMware(final DataStore store, final String vmControlIp, String fileToCopy, Long vmHostId) { private Pair<Boolean, String> copyToSecondaryStorageNonVMware(final DataStore store, final String vmControlIp, String fileToCopy, Long vmHostId) {
CopyToSecondaryStorageCommand toSecondaryStorageCommand = new CopyToSecondaryStorageCommand(store.getUri(), vmControlIp, fileToCopy); String nfsVersion = CapacityManager.ImageStoreNFSVersion.valueIn(store.getId());
CopyToSecondaryStorageCommand toSecondaryStorageCommand = new CopyToSecondaryStorageCommand(store.getUri(), vmControlIp, fileToCopy, nfsVersion);
Answer copyToSecondaryAnswer = agentManager.easySend(vmHostId, toSecondaryStorageCommand); Answer copyToSecondaryAnswer = agentManager.easySend(vmHostId, toSecondaryStorageCommand);
Pair<Boolean, String> copyAnswer; Pair<Boolean, String> copyAnswer;
if (copyToSecondaryAnswer != null) { if (copyToSecondaryAnswer != null) {

View File

@ -1036,12 +1036,10 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar
if (host != null) { if (host != null) {
s_logger.debug(String.format("Removing host entry for secondary storage VM [%s].", vmId)); s_logger.debug(String.format("Removing host entry for secondary storage VM [%s].", vmId));
_hostDao.remove(host.getId()); _hostDao.remove(host.getId());
_tmplStoreDao.expireDnldUrlsForZone(host.getDataCenterId()); _tmplStoreDao.expireDnldUrlsForZone(host.getDataCenterId());
_volumeStoreDao.expireDnldUrlsForZone(host.getDataCenterId()); _volumeStoreDao.expireDnldUrlsForZone(host.getDataCenterId());
return true;
} }
return false; return true;
} catch (ResourceUnavailableException e) { } catch (ResourceUnavailableException e) {
s_logger.error(String.format("Unable to expunge secondary storage [%s] due to [%s].", ssvm.toString(), e.getMessage()), e); s_logger.error(String.format("Unable to expunge secondary storage [%s] due to [%s].", ssvm.toString(), e.getMessage()), e);
return false; return false;

View File

@ -173,13 +173,6 @@ export default {
this.deployasistemplate = json.listtemplatesresponse.template[0].deployasis this.deployasistemplate = json.listtemplatesresponse.template[0].deployasis
}) })
}, },
filterOrReadOnlyDetails () {
for (var i = 0; i < this.details.length; i++) {
if (!this.allowEditOfDetail(this.details[i].name)) {
this.details.splice(i, 1)
}
}
},
allowEditOfDetail (name) { allowEditOfDetail (name) {
if (this.resource.readonlydetails) { if (this.resource.readonlydetails) {
if (this.resource.readonlydetails.split(',').map(item => item.trim()).includes(name)) { if (this.resource.readonlydetails.split(',').map(item => item.trim()).includes(name)) {
@ -211,6 +204,27 @@ export default {
(this.resource.domainid === this.$store.getters.userInfo.domainid && this.resource.account === this.$store.getters.userInfo.account) || (this.resource.domainid === this.$store.getters.userInfo.domainid && this.resource.account === this.$store.getters.userInfo.account) ||
this.resource.project && this.resource.projectid === this.$store.getters.project.id this.resource.project && this.resource.projectid === this.$store.getters.project.id
}, },
getDetailsParam (details) {
var params = {}
var filteredDetails = details
if (this.resource.readonlydetails && filteredDetails) {
filteredDetails = []
var readOnlyDetailNames = this.resource.readonlydetails.split(',').map(item => item.trim())
for (var detail of this.details) {
if (!readOnlyDetailNames.includes(detail.name)) {
filteredDetails.push(detail)
}
}
}
if (filteredDetails.length === 0) {
params.cleanupdetails = true
} else {
filteredDetails.forEach(function (item, index) {
params['details[0].' + item.name] = item.value
})
}
return params
},
runApi () { runApi () {
var apiName = '' var apiName = ''
if (this.resourceType === 'UserVm') { if (this.resourceType === 'UserVm') {
@ -226,14 +240,8 @@ export default {
return return
} }
const params = { id: this.resource.id } var params = { id: this.resource.id }
if (this.details.length === 0) { params = Object.assign(params, this.getDetailsParam(this.details))
params.cleanupdetails = true
} else {
this.details.forEach(function (item, index) {
params['details[0].' + item.name] = item.value
})
}
this.loading = true this.loading = true
api(apiName, params).then(json => { api(apiName, params).then(json => {
var details = {} var details = {}
@ -259,18 +267,19 @@ export default {
this.error = this.$t('message.error.provide.setting') this.error = this.$t('message.error.provide.setting')
return return
} }
if (!this.allowEditOfDetail(this.newKey)) {
this.error = this.$t('error.unable.to.proceed')
return
}
this.error = false this.error = false
this.details.push({ name: this.newKey, value: this.newValue }) this.details.push({ name: this.newKey, value: this.newValue })
this.filterOrReadOnlyDetails()
this.runApi() this.runApi()
}, },
updateDetail (index) { updateDetail (index) {
this.filterOrReadOnlyDetails()
this.runApi() this.runApi()
}, },
deleteDetail (index) { deleteDetail (index) {
this.details.splice(index, 1) this.details.splice(index, 1)
this.filterOrReadOnlyDetails()
this.runApi() this.runApi()
}, },
onShowAddDetail () { onShowAddDetail () {

View File

@ -99,7 +99,7 @@ export default {
label: 'label.restart.network', label: 'label.restart.network',
message: 'message.restart.network', message: 'message.restart.network',
dataView: true, dataView: true,
args: ['cleanup'], args: (record) => record.vpcid == null ? ['cleanup'] : [], // if it is a tier in a VPC and so it has a vpc do not allow "cleanup
show: (record) => record.type !== 'L2', show: (record) => record.type !== 'L2',
groupAction: true, groupAction: true,
popup: true, popup: true,

View File

@ -69,7 +69,8 @@
optionFilterProp="children" optionFilterProp="children"
:filterOption="(input, option) => { :filterOption="(input, option) => {
return option.componentOptions.propsData.label.toLowerCase().indexOf(input.toLowerCase()) >= 0 return option.componentOptions.propsData.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
}" > }"
@change="onZoneChange" >
<a-select-option :value="zone.id" v-for="zone in zones" :key="zone.id" :label="zone.name || zone.description"> <a-select-option :value="zone.id" v-for="zone in zones" :key="zone.id" :label="zone.name || zone.description">
<span> <span>
<resource-icon v-if="zone.icon" :image="zone.icon.base64image" size="1x" style="margin-right: 5px"/> <resource-icon v-if="zone.icon" :image="zone.icon.base64image" size="1x" style="margin-right: 5px"/>
@ -79,6 +80,22 @@
</a-select-option> </a-select-option>
</a-select> </a-select>
</a-form-item> </a-form-item>
<a-form-item>
<tooltip-label slot="label" :title="$t('label.diskofferingid')" :tooltip="apiParams.diskofferingid.description"/>
<a-select
v-decorator="['diskofferingid', {}]"
:loading="offeringLoading"
:placeholder="apiParams.diskofferingid.description"
showSearch
optionFilterProp="children"
:filterOption="(input, option) => {
return option.componentOptions.propsData.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
}" >
<a-select-option v-for="opt in offerings" :key="opt.id">
{{ opt.name || opt.displaytext }}
</a-select-option>
</a-select>
</a-form-item>
<a-form-item> <a-form-item>
<tooltip-label slot="label" :title="$t('label.format')" :tooltip="apiParams.format.description"/> <tooltip-label slot="label" :title="$t('label.format')" :tooltip="apiParams.format.description"/>
<a-select <a-select
@ -133,6 +150,8 @@ export default {
return { return {
fileList: [], fileList: [],
zones: [], zones: [],
offerings: [],
offeringLoading: false,
formats: ['RAW', 'VHD', 'VHDX', 'OVA', 'QCOW2'], formats: ['RAW', 'VHD', 'VHDX', 'OVA', 'QCOW2'],
zoneSelected: '', zoneSelected: '',
uploadParams: null, uploadParams: null,
@ -153,11 +172,34 @@ export default {
if (json && json.listzonesresponse && json.listzonesresponse.zone) { if (json && json.listzonesresponse && json.listzonesresponse.zone) {
this.zones = json.listzonesresponse.zone this.zones = json.listzonesresponse.zone
if (this.zones.length > 0) { if (this.zones.length > 0) {
this.zoneSelected = this.zones[0].id this.onZoneChange(this.zones[0].id)
} }
} }
}) })
}, },
onZoneChange (zoneId) {
this.zoneSelected = this.zones[0].id
this.fetchDiskOfferings(zoneId)
},
fetchDiskOfferings (zoneId) {
this.offeringLoading = true
this.offerings = [{ id: -1, name: '' }]
this.form.setFieldsValue({
diskofferingid: undefined
})
api('listDiskOfferings', {
zoneid: zoneId,
listall: true
}).then(json => {
for (var offering of json.listdiskofferingsresponse.diskoffering) {
if (offering.iscustomized) {
this.offerings.push(offering)
}
}
}).finally(() => {
this.offeringLoading = false
})
},
handleRemove (file) { handleRemove (file) {
const index = this.fileList.indexOf(file) const index = this.fileList.indexOf(file)
const newFileList = this.fileList.slice() const newFileList = this.fileList.slice()
@ -188,7 +230,7 @@ export default {
} }
this.loading = true this.loading = true
api('getUploadParamsForVolume', params).then(json => { api('getUploadParamsForVolume', params).then(json => {
this.uploadParams = (json.postuploadvolumeresponse && json.postuploadvolumeresponse.getuploadparams) ? json.postuploadvolumeresponse.getuploadparams : '' this.uploadParams = json.postuploadvolumeresponse?.getuploadparams || ''
const { fileList } = this const { fileList } = this
if (this.fileList.length > 1) { if (this.fileList.length > 1) {
this.$notification.error({ this.$notification.error({
@ -224,12 +266,20 @@ export default {
}).catch(e => { }).catch(e => {
this.$notification.error({ this.$notification.error({
message: this.$t('message.upload.failed'), message: this.$t('message.upload.failed'),
description: `${this.$t('message.upload.iso.failed.description')} - ${e}`, description: `${this.$t('message.upload.volume.failed')} - ${e}`,
duration: 0 duration: 0
}) })
}).finally(() => { }).finally(() => {
this.loading = false this.loading = false
}) })
}).catch(e => {
this.$notification.error({
message: this.$t('message.upload.failed'),
description: `${this.$t('message.upload.volume.failed')} - ${e?.response?.data?.postuploadvolumeresponse?.errortext || e}`,
duration: 0
})
}).finally(() => {
this.loading = false
}) })
}) })
}, },