mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 01:32:18 +02:00
NAS BnR: Create Instance from Backup issues (#11754)
* add createCrossZoneInstnaceEnabled to BackupOfferingResponse * show use IP Address from Backup button when orignal instance is expunged * Fix NPE in takeBackup if the vm template is deleted. * Add since to Cross zone instance creation in BackupOfferingResponse.java Co-authored-by: Suresh Kumar Anaparti <sureshkumar.anaparti@gmail.com> * Store and show Guest os type in the backup metadata * show warning in create instance from backup form if guest os type is different * show warning in create instance from backup form if guest os type is different * backupvmexpunged -> isbackupvmexpunged * review comments * fix npe * improve err msg * err msg --------- Co-authored-by: Suresh Kumar Anaparti <sureshkumar.anaparti@gmail.com>
This commit is contained in:
parent
c0a4392b05
commit
046014b4c5
@ -64,6 +64,7 @@ public class ApiConstants {
|
|||||||
public static final String BACKUP_STORAGE_LIMIT = "backupstoragelimit";
|
public static final String BACKUP_STORAGE_LIMIT = "backupstoragelimit";
|
||||||
public static final String BACKUP_STORAGE_TOTAL = "backupstoragetotal";
|
public static final String BACKUP_STORAGE_TOTAL = "backupstoragetotal";
|
||||||
public static final String BACKUP_VM_OFFERING_REMOVED = "vmbackupofferingremoved";
|
public static final String BACKUP_VM_OFFERING_REMOVED = "vmbackupofferingremoved";
|
||||||
|
public static final String IS_BACKUP_VM_EXPUNGED = "isbackupvmexpunged";
|
||||||
public static final String BACKUP_TOTAL = "backuptotal";
|
public static final String BACKUP_TOTAL = "backuptotal";
|
||||||
public static final String BASE64_IMAGE = "base64image";
|
public static final String BASE64_IMAGE = "base64image";
|
||||||
public static final String BGP_PEERS = "bgppeers";
|
public static final String BGP_PEERS = "bgppeers";
|
||||||
|
|||||||
@ -61,6 +61,10 @@ public class BackupOfferingResponse extends BaseResponse {
|
|||||||
@Param(description = "zone name")
|
@Param(description = "zone name")
|
||||||
private String zoneName;
|
private String zoneName;
|
||||||
|
|
||||||
|
@SerializedName(ApiConstants.CROSS_ZONE_INSTANCE_CREATION)
|
||||||
|
@Param(description = "the backups with this offering can be used to create Instances on all Zones", since = "4.22.0")
|
||||||
|
private Boolean crossZoneInstanceCreation;
|
||||||
|
|
||||||
@SerializedName(ApiConstants.CREATED)
|
@SerializedName(ApiConstants.CREATED)
|
||||||
@Param(description = "the date this backup offering was created")
|
@Param(description = "the date this backup offering was created")
|
||||||
private Date created;
|
private Date created;
|
||||||
@ -97,6 +101,10 @@ public class BackupOfferingResponse extends BaseResponse {
|
|||||||
this.zoneName = zoneName;
|
this.zoneName = zoneName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setCrossZoneInstanceCreation(Boolean crossZoneInstanceCreation) {
|
||||||
|
this.crossZoneInstanceCreation = crossZoneInstanceCreation;
|
||||||
|
}
|
||||||
|
|
||||||
public void setCreated(Date created) {
|
public void setCreated(Date created) {
|
||||||
this.created = created;
|
this.created = created;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -123,6 +123,10 @@ public class BackupResponse extends BaseResponse {
|
|||||||
@Param(description = "The backup offering corresponding to this backup was removed from the VM", since = "4.21.0")
|
@Param(description = "The backup offering corresponding to this backup was removed from the VM", since = "4.21.0")
|
||||||
private Boolean vmOfferingRemoved;
|
private Boolean vmOfferingRemoved;
|
||||||
|
|
||||||
|
@SerializedName(ApiConstants.IS_BACKUP_VM_EXPUNGED)
|
||||||
|
@Param(description = "Indicates whether the VM from which the backup was taken is expunged or not", since = "4.22.0")
|
||||||
|
private Boolean isVmExpunged;
|
||||||
|
|
||||||
public String getId() {
|
public String getId() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
@ -306,4 +310,8 @@ public class BackupResponse extends BaseResponse {
|
|||||||
public void setVmOfferingRemoved(Boolean vmOfferingRemoved) {
|
public void setVmOfferingRemoved(Boolean vmOfferingRemoved) {
|
||||||
this.vmOfferingRemoved = vmOfferingRemoved;
|
this.vmOfferingRemoved = vmOfferingRemoved;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setVmExpunged(Boolean isVmExpunged) {
|
||||||
|
this.isVmExpunged = isVmExpunged;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,7 +24,7 @@ import org.apache.cloudstack.backup.BackupOfferingVO;
|
|||||||
import com.cloud.utils.db.GenericDao;
|
import com.cloud.utils.db.GenericDao;
|
||||||
|
|
||||||
public interface BackupOfferingDao extends GenericDao<BackupOfferingVO, Long> {
|
public interface BackupOfferingDao extends GenericDao<BackupOfferingVO, Long> {
|
||||||
BackupOfferingResponse newBackupOfferingResponse(BackupOffering policy);
|
BackupOfferingResponse newBackupOfferingResponse(BackupOffering policy, Boolean crossZoneInstanceCreation);
|
||||||
BackupOffering findByExternalId(String externalId, Long zoneId);
|
BackupOffering findByExternalId(String externalId, Long zoneId);
|
||||||
BackupOffering findByName(String name, Long zoneId);
|
BackupOffering findByName(String name, Long zoneId);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -50,7 +50,7 @@ public class BackupOfferingDaoImpl extends GenericDaoBase<BackupOfferingVO, Long
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BackupOfferingResponse newBackupOfferingResponse(BackupOffering offering) {
|
public BackupOfferingResponse newBackupOfferingResponse(BackupOffering offering, Boolean crossZoneInstanceCreation) {
|
||||||
DataCenterVO zone = dataCenterDao.findById(offering.getZoneId());
|
DataCenterVO zone = dataCenterDao.findById(offering.getZoneId());
|
||||||
|
|
||||||
BackupOfferingResponse response = new BackupOfferingResponse();
|
BackupOfferingResponse response = new BackupOfferingResponse();
|
||||||
@ -64,6 +64,9 @@ public class BackupOfferingDaoImpl extends GenericDaoBase<BackupOfferingVO, Long
|
|||||||
response.setZoneId(zone.getUuid());
|
response.setZoneId(zone.getUuid());
|
||||||
response.setZoneName(zone.getName());
|
response.setZoneName(zone.getName());
|
||||||
}
|
}
|
||||||
|
if (crossZoneInstanceCreation) {
|
||||||
|
response.setCrossZoneInstanceCreation(true);
|
||||||
|
}
|
||||||
response.setCreated(offering.getCreated());
|
response.setCreated(offering.getCreated());
|
||||||
response.setObjectName("backupoffering");
|
response.setObjectName("backupoffering");
|
||||||
return response;
|
return response;
|
||||||
|
|||||||
@ -75,9 +75,11 @@ import org.apache.cloudstack.api.response.VolumeResponse;
|
|||||||
import org.apache.cloudstack.api.response.VpcOfferingResponse;
|
import org.apache.cloudstack.api.response.VpcOfferingResponse;
|
||||||
import org.apache.cloudstack.api.response.ZoneResponse;
|
import org.apache.cloudstack.api.response.ZoneResponse;
|
||||||
import org.apache.cloudstack.backup.BackupOffering;
|
import org.apache.cloudstack.backup.BackupOffering;
|
||||||
|
import org.apache.cloudstack.backup.BackupRepository;
|
||||||
import org.apache.cloudstack.backup.BackupSchedule;
|
import org.apache.cloudstack.backup.BackupSchedule;
|
||||||
import org.apache.cloudstack.backup.dao.BackupDao;
|
import org.apache.cloudstack.backup.dao.BackupDao;
|
||||||
import org.apache.cloudstack.backup.dao.BackupOfferingDao;
|
import org.apache.cloudstack.backup.dao.BackupOfferingDao;
|
||||||
|
import org.apache.cloudstack.backup.dao.BackupRepositoryDao;
|
||||||
import org.apache.cloudstack.backup.dao.BackupScheduleDao;
|
import org.apache.cloudstack.backup.dao.BackupScheduleDao;
|
||||||
import org.apache.cloudstack.context.CallContext;
|
import org.apache.cloudstack.context.CallContext;
|
||||||
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
|
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
|
||||||
@ -493,6 +495,7 @@ public class ApiDBUtils {
|
|||||||
static BackupDao s_backupDao;
|
static BackupDao s_backupDao;
|
||||||
static BackupScheduleDao s_backupScheduleDao;
|
static BackupScheduleDao s_backupScheduleDao;
|
||||||
static BackupOfferingDao s_backupOfferingDao;
|
static BackupOfferingDao s_backupOfferingDao;
|
||||||
|
static BackupRepositoryDao s_backupRepositoryDao;
|
||||||
static NicDao s_nicDao;
|
static NicDao s_nicDao;
|
||||||
static ResourceManagerUtil s_resourceManagerUtil;
|
static ResourceManagerUtil s_resourceManagerUtil;
|
||||||
static SnapshotPolicyDetailsDao s_snapshotPolicyDetailsDao;
|
static SnapshotPolicyDetailsDao s_snapshotPolicyDetailsDao;
|
||||||
@ -751,6 +754,8 @@ public class ApiDBUtils {
|
|||||||
@Inject
|
@Inject
|
||||||
private BackupOfferingDao backupOfferingDao;
|
private BackupOfferingDao backupOfferingDao;
|
||||||
@Inject
|
@Inject
|
||||||
|
private BackupRepositoryDao backupRepositoryDao;
|
||||||
|
@Inject
|
||||||
private BackupScheduleDao backupScheduleDao;
|
private BackupScheduleDao backupScheduleDao;
|
||||||
@Inject
|
@Inject
|
||||||
private NicDao nicDao;
|
private NicDao nicDao;
|
||||||
@ -899,6 +904,7 @@ public class ApiDBUtils {
|
|||||||
s_backupDao = backupDao;
|
s_backupDao = backupDao;
|
||||||
s_backupScheduleDao = backupScheduleDao;
|
s_backupScheduleDao = backupScheduleDao;
|
||||||
s_backupOfferingDao = backupOfferingDao;
|
s_backupOfferingDao = backupOfferingDao;
|
||||||
|
s_backupRepositoryDao = backupRepositoryDao;
|
||||||
s_resourceIconDao = resourceIconDao;
|
s_resourceIconDao = resourceIconDao;
|
||||||
s_resourceManagerUtil = resourceManagerUtil;
|
s_resourceManagerUtil = resourceManagerUtil;
|
||||||
s_objectStoreDao = objectStoreDao;
|
s_objectStoreDao = objectStoreDao;
|
||||||
@ -2297,8 +2303,10 @@ public class ApiDBUtils {
|
|||||||
return s_backupScheduleDao.newBackupScheduleResponse(schedule);
|
return s_backupScheduleDao.newBackupScheduleResponse(schedule);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BackupOfferingResponse newBackupOfferingResponse(BackupOffering policy) {
|
public static BackupOfferingResponse newBackupOfferingResponse(BackupOffering offering) {
|
||||||
return s_backupOfferingDao.newBackupOfferingResponse(policy);
|
BackupRepository repository = s_backupRepositoryDao.findByUuid(offering.getExternalId());
|
||||||
|
Boolean crossZoneInstanceCreationEnabled = repository != null ? Boolean.TRUE.equals(repository.crossZoneInstanceCreationEnabled()) : false;
|
||||||
|
return s_backupOfferingDao.newBackupOfferingResponse(offering, crossZoneInstanceCreationEnabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static NicVO findByIp4AddressAndNetworkId(String ip4Address, long networkId) {
|
public static NicVO findByIp4AddressAndNetworkId(String ip4Address, long networkId) {
|
||||||
|
|||||||
@ -5040,8 +5040,8 @@ public class ApiResponseHelper implements ResponseGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BackupOfferingResponse createBackupOfferingResponse(BackupOffering policy) {
|
public BackupOfferingResponse createBackupOfferingResponse(BackupOffering offering) {
|
||||||
return ApiDBUtils.newBackupOfferingResponse(policy);
|
return ApiDBUtils.newBackupOfferingResponse(offering);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ManagementServerResponse createManagementResponse(ManagementServerHost mgmt) {
|
public ManagementServerResponse createManagementResponse(ManagementServerHost mgmt) {
|
||||||
|
|||||||
@ -9606,11 +9606,11 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||||||
} else {
|
} else {
|
||||||
String serviceOfferingUuid = backup.getDetail(ApiConstants.SERVICE_OFFERING_ID);
|
String serviceOfferingUuid = backup.getDetail(ApiConstants.SERVICE_OFFERING_ID);
|
||||||
if (serviceOfferingUuid == null) {
|
if (serviceOfferingUuid == null) {
|
||||||
throw new CloudRuntimeException("Backup doesn't contain service offering uuid. Please specify a valid service offering id while creating the instance");
|
throw new CloudRuntimeException("Backup doesn't contain a Service Offering UUID. Please specify a valid Service Offering while creating the Instance");
|
||||||
}
|
}
|
||||||
serviceOffering = serviceOfferingDao.findByUuid(serviceOfferingUuid);
|
serviceOffering = serviceOfferingDao.findByUuid(serviceOfferingUuid);
|
||||||
if (serviceOffering == null) {
|
if (serviceOffering == null) {
|
||||||
throw new CloudRuntimeException("Unable to find service offering with the uuid stored in backup. Please specify a valid service offering id while creating instance");
|
throw new CloudRuntimeException("Unable to find Service Offering with the UUID stored in the Backup. Please specify a valid Service Offering while creating the Instance");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
verifyServiceOffering(cmd, serviceOffering);
|
verifyServiceOffering(cmd, serviceOffering);
|
||||||
@ -9625,11 +9625,11 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||||||
} else {
|
} else {
|
||||||
String templateUuid = backup.getDetail(ApiConstants.TEMPLATE_ID);
|
String templateUuid = backup.getDetail(ApiConstants.TEMPLATE_ID);
|
||||||
if (templateUuid == null) {
|
if (templateUuid == null) {
|
||||||
throw new CloudRuntimeException("Backup doesn't contain Template uuid. Please specify a valid Template/ISO while creating the instance");
|
throw new CloudRuntimeException("Backup doesn't contain a Template UUID. Please specify a valid Template/ISO while creating the Instance");
|
||||||
}
|
}
|
||||||
template = _templateDao.findByUuid(templateUuid);
|
template = _templateDao.findByUuid(templateUuid);
|
||||||
if (template == null) {
|
if (template == null) {
|
||||||
throw new CloudRuntimeException("Unable to find template associated with the backup. Please specify a valid Template/ISO while creating instance");
|
throw new CloudRuntimeException("Unable to find Template with the UUID stored in the Backup. Please specify a valid Template/ISO while creating the Instance");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
verifyTemplate(cmd, template, serviceOffering.getId());
|
verifyTemplate(cmd, template, serviceOffering.getId());
|
||||||
|
|||||||
@ -122,12 +122,14 @@ import com.cloud.projects.Project;
|
|||||||
import com.cloud.serializer.GsonHelper;
|
import com.cloud.serializer.GsonHelper;
|
||||||
import com.cloud.service.dao.ServiceOfferingDao;
|
import com.cloud.service.dao.ServiceOfferingDao;
|
||||||
import com.cloud.storage.DiskOfferingVO;
|
import com.cloud.storage.DiskOfferingVO;
|
||||||
|
import com.cloud.storage.GuestOSVO;
|
||||||
import com.cloud.storage.ScopeType;
|
import com.cloud.storage.ScopeType;
|
||||||
import com.cloud.storage.Storage;
|
import com.cloud.storage.Storage;
|
||||||
import com.cloud.storage.Volume;
|
import com.cloud.storage.Volume;
|
||||||
import com.cloud.storage.VolumeApiService;
|
import com.cloud.storage.VolumeApiService;
|
||||||
import com.cloud.storage.VolumeVO;
|
import com.cloud.storage.VolumeVO;
|
||||||
import com.cloud.storage.dao.DiskOfferingDao;
|
import com.cloud.storage.dao.DiskOfferingDao;
|
||||||
|
import com.cloud.storage.dao.GuestOSDao;
|
||||||
import com.cloud.storage.dao.VMTemplateDao;
|
import com.cloud.storage.dao.VMTemplateDao;
|
||||||
import com.cloud.storage.dao.VolumeDao;
|
import com.cloud.storage.dao.VolumeDao;
|
||||||
import com.cloud.template.VirtualMachineTemplate;
|
import com.cloud.template.VirtualMachineTemplate;
|
||||||
@ -232,6 +234,8 @@ public class BackupManagerImpl extends ManagerBase implements BackupManager {
|
|||||||
private ResourceLimitService resourceLimitMgr;
|
private ResourceLimitService resourceLimitMgr;
|
||||||
@Inject
|
@Inject
|
||||||
private AlertManager alertManager;
|
private AlertManager alertManager;
|
||||||
|
@Inject
|
||||||
|
private GuestOSDao _guestOSDao;
|
||||||
|
|
||||||
private AsyncJobDispatcher asyncJobDispatcher;
|
private AsyncJobDispatcher asyncJobDispatcher;
|
||||||
private Timer backupTimer;
|
private Timer backupTimer;
|
||||||
@ -379,7 +383,15 @@ public class BackupManagerImpl extends ManagerBase implements BackupManager {
|
|||||||
ServiceOffering serviceOffering = serviceOfferingDao.findById(vm.getServiceOfferingId());
|
ServiceOffering serviceOffering = serviceOfferingDao.findById(vm.getServiceOfferingId());
|
||||||
details.put(ApiConstants.SERVICE_OFFERING_ID, serviceOffering.getUuid());
|
details.put(ApiConstants.SERVICE_OFFERING_ID, serviceOffering.getUuid());
|
||||||
VirtualMachineTemplate template = vmTemplateDao.findById(vm.getTemplateId());
|
VirtualMachineTemplate template = vmTemplateDao.findById(vm.getTemplateId());
|
||||||
details.put(ApiConstants.TEMPLATE_ID, template.getUuid());
|
if (template != null) {
|
||||||
|
long guestOSId = template.getGuestOSId();
|
||||||
|
details.put(ApiConstants.TEMPLATE_ID, template.getUuid());
|
||||||
|
GuestOSVO guestOS = _guestOSDao.findById(guestOSId);
|
||||||
|
if (guestOS != null) {
|
||||||
|
details.put(ApiConstants.OS_TYPE_ID, guestOS.getUuid());
|
||||||
|
details.put(ApiConstants.OS_NAME, guestOS.getDisplayName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
List<VMInstanceDetailVO> vmDetails = vmInstanceDetailsDao.listDetails(vm.getId());
|
List<VMInstanceDetailVO> vmDetails = vmInstanceDetailsDao.listDetails(vm.getId());
|
||||||
HashMap<String, String> settings = new HashMap<>();
|
HashMap<String, String> settings = new HashMap<>();
|
||||||
@ -2143,7 +2155,6 @@ public class BackupManagerImpl extends ManagerBase implements BackupManager {
|
|||||||
if (details.containsKey(ApiConstants.TEMPLATE_ID)) {
|
if (details.containsKey(ApiConstants.TEMPLATE_ID)) {
|
||||||
VirtualMachineTemplate template = vmTemplateDao.findByUuid(details.get(ApiConstants.TEMPLATE_ID));
|
VirtualMachineTemplate template = vmTemplateDao.findByUuid(details.get(ApiConstants.TEMPLATE_ID));
|
||||||
if (template != null) {
|
if (template != null) {
|
||||||
details.put(ApiConstants.TEMPLATE_ID, template.getUuid());
|
|
||||||
details.put(ApiConstants.TEMPLATE_NAME, template.getName());
|
details.put(ApiConstants.TEMPLATE_NAME, template.getName());
|
||||||
details.put(ApiConstants.IS_ISO, String.valueOf(template.getFormat().equals(Storage.ImageFormat.ISO)));
|
details.put(ApiConstants.IS_ISO, String.valueOf(template.getFormat().equals(Storage.ImageFormat.ISO)));
|
||||||
}
|
}
|
||||||
@ -2151,7 +2162,6 @@ public class BackupManagerImpl extends ManagerBase implements BackupManager {
|
|||||||
if (details.containsKey(ApiConstants.SERVICE_OFFERING_ID)) {
|
if (details.containsKey(ApiConstants.SERVICE_OFFERING_ID)) {
|
||||||
ServiceOffering serviceOffering = serviceOfferingDao.findByUuid(details.get(ApiConstants.SERVICE_OFFERING_ID));
|
ServiceOffering serviceOffering = serviceOfferingDao.findByUuid(details.get(ApiConstants.SERVICE_OFFERING_ID));
|
||||||
if (serviceOffering != null) {
|
if (serviceOffering != null) {
|
||||||
details.put(ApiConstants.SERVICE_OFFERING_ID, serviceOffering.getUuid());
|
|
||||||
details.put(ApiConstants.SERVICE_OFFERING_NAME, serviceOffering.getName());
|
details.put(ApiConstants.SERVICE_OFFERING_NAME, serviceOffering.getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2186,10 +2196,15 @@ public class BackupManagerImpl extends ManagerBase implements BackupManager {
|
|||||||
response.setId(backup.getUuid());
|
response.setId(backup.getUuid());
|
||||||
response.setName(backup.getName());
|
response.setName(backup.getName());
|
||||||
response.setDescription(backup.getDescription());
|
response.setDescription(backup.getDescription());
|
||||||
response.setVmName(vm.getHostName());
|
if (vm != null) {
|
||||||
response.setVmId(vm.getUuid());
|
response.setVmName(vm.getHostName());
|
||||||
if (vm.getBackupOfferingId() == null || vm.getBackupOfferingId() != backup.getBackupOfferingId()) {
|
response.setVmId(vm.getUuid());
|
||||||
response.setVmOfferingRemoved(true);
|
if (vm.getBackupOfferingId() == null || vm.getBackupOfferingId() != backup.getBackupOfferingId()) {
|
||||||
|
response.setVmOfferingRemoved(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (vm == null || VirtualMachine.State.Expunging.equals(vm.getState())) {
|
||||||
|
response.setVmExpunged(true);
|
||||||
}
|
}
|
||||||
response.setExternalId(backup.getExternalId());
|
response.setExternalId(backup.getExternalId());
|
||||||
response.setType(backup.getType());
|
response.setType(backup.getType());
|
||||||
@ -2205,9 +2220,11 @@ public class BackupManagerImpl extends ManagerBase implements BackupManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ACS 4.20: For backups taken prior this release the backup.backed_volumes column would be empty hence use vm_instance.backup_volumes
|
// ACS 4.20: For backups taken prior this release the backup.backed_volumes column would be empty hence use vm_instance.backup_volumes
|
||||||
String backedUpVolumes;
|
String backedUpVolumes = "";
|
||||||
if (Objects.isNull(backup.getBackedUpVolumes())) {
|
if (Objects.isNull(backup.getBackedUpVolumes())) {
|
||||||
backedUpVolumes = new Gson().toJson(vm.getBackupVolumeList().toArray(), Backup.VolumeInfo[].class);
|
if (vm != null) {
|
||||||
|
backedUpVolumes = new Gson().toJson(vm.getBackupVolumeList().toArray(), Backup.VolumeInfo[].class);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
backedUpVolumes = new Gson().toJson(backup.getBackedUpVolumes().toArray(), Backup.VolumeInfo[].class);
|
backedUpVolumes = new Gson().toJson(backup.getBackedUpVolumes().toArray(), Backup.VolumeInfo[].class);
|
||||||
}
|
}
|
||||||
@ -2223,7 +2240,9 @@ public class BackupManagerImpl extends ManagerBase implements BackupManager {
|
|||||||
|
|
||||||
if (Boolean.TRUE.equals(listVmDetails)) {
|
if (Boolean.TRUE.equals(listVmDetails)) {
|
||||||
Map<String, String> vmDetails = new HashMap<>();
|
Map<String, String> vmDetails = new HashMap<>();
|
||||||
vmDetails.put(ApiConstants.HYPERVISOR, vm.getHypervisorType().toString());
|
if (vm != null) {
|
||||||
|
vmDetails.put(ApiConstants.HYPERVISOR, vm.getHypervisorType().toString());
|
||||||
|
}
|
||||||
Map<String, String> details = getDetailsFromBackupDetails(backup.getId());
|
Map<String, String> details = getDetailsFromBackupDetails(backup.getId());
|
||||||
vmDetails.putAll(details);
|
vmDetails.putAll(details);
|
||||||
response.setVmDetails(vmDetails);
|
response.setVmDetails(vmDetails);
|
||||||
|
|||||||
@ -49,6 +49,7 @@ import com.cloud.storage.Volume;
|
|||||||
import com.cloud.storage.VolumeApiService;
|
import com.cloud.storage.VolumeApiService;
|
||||||
import com.cloud.storage.VolumeVO;
|
import com.cloud.storage.VolumeVO;
|
||||||
import com.cloud.storage.dao.DiskOfferingDao;
|
import com.cloud.storage.dao.DiskOfferingDao;
|
||||||
|
import com.cloud.storage.dao.GuestOSDao;
|
||||||
import com.cloud.storage.dao.VMTemplateDao;
|
import com.cloud.storage.dao.VMTemplateDao;
|
||||||
import com.cloud.storage.dao.VolumeDao;
|
import com.cloud.storage.dao.VolumeDao;
|
||||||
import com.cloud.user.Account;
|
import com.cloud.user.Account;
|
||||||
@ -237,6 +238,9 @@ public class BackupManagerTest {
|
|||||||
@Mock
|
@Mock
|
||||||
DomainDao domainDao;
|
DomainDao domainDao;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private GuestOSDao _guestOSDao;
|
||||||
|
|
||||||
private Gson gson;
|
private Gson gson;
|
||||||
|
|
||||||
private String[] hostPossibleValues = {"127.0.0.1", "hostname"};
|
private String[] hostPossibleValues = {"127.0.0.1", "hostname"};
|
||||||
@ -1572,14 +1576,12 @@ public class BackupManagerTest {
|
|||||||
|
|
||||||
VMTemplateVO template = mock(VMTemplateVO.class);
|
VMTemplateVO template = mock(VMTemplateVO.class);
|
||||||
when(template.getFormat()).thenReturn(Storage.ImageFormat.QCOW2);
|
when(template.getFormat()).thenReturn(Storage.ImageFormat.QCOW2);
|
||||||
when(template.getUuid()).thenReturn(templateUuid);
|
|
||||||
when(template.getName()).thenReturn("template1");
|
when(template.getName()).thenReturn("template1");
|
||||||
when(vmTemplateDao.findByUuid(templateUuid)).thenReturn(template);
|
when(vmTemplateDao.findByUuid(templateUuid)).thenReturn(template);
|
||||||
Map<String, String> details = new HashMap<>();
|
Map<String, String> details = new HashMap<>();
|
||||||
details.put(ApiConstants.TEMPLATE_ID, templateUuid);
|
details.put(ApiConstants.TEMPLATE_ID, templateUuid);
|
||||||
|
|
||||||
ServiceOfferingVO serviceOffering = mock(ServiceOfferingVO.class);
|
ServiceOfferingVO serviceOffering = mock(ServiceOfferingVO.class);
|
||||||
when(serviceOffering.getUuid()).thenReturn(serviceOfferingUuid);
|
|
||||||
when(serviceOffering.getName()).thenReturn("service-offering1");
|
when(serviceOffering.getName()).thenReturn("service-offering1");
|
||||||
when(serviceOfferingDao.findByUuid(serviceOfferingUuid)).thenReturn(serviceOffering);
|
when(serviceOfferingDao.findByUuid(serviceOfferingUuid)).thenReturn(serviceOffering);
|
||||||
details.put(ApiConstants.SERVICE_OFFERING_ID, serviceOfferingUuid);
|
details.put(ApiConstants.SERVICE_OFFERING_ID, serviceOfferingUuid);
|
||||||
|
|||||||
@ -2887,6 +2887,8 @@
|
|||||||
"message.action.create.snapshot.from.vmsnapshot": "Please confirm that you want to create Snapshot from Instance Snapshot",
|
"message.action.create.snapshot.from.vmsnapshot": "Please confirm that you want to create Snapshot from Instance Snapshot",
|
||||||
"message.action.create.instance.from.backup": "Please confirm that you want to create a new Instance from the given Backup.<br>Click on configure to edit the parameters for the new Instance before creation.",
|
"message.action.create.instance.from.backup": "Please confirm that you want to create a new Instance from the given Backup.<br>Click on configure to edit the parameters for the new Instance before creation.",
|
||||||
"message.create.instance.from.backup.different.zone": "Creating Instance from Backup on a different Zone. Please ensure that the backup repository is accessible in the selected Zone.",
|
"message.create.instance.from.backup.different.zone": "Creating Instance from Backup on a different Zone. Please ensure that the backup repository is accessible in the selected Zone.",
|
||||||
|
"message.template.ostype.different.from.backup": "Selected Template has a different OS type than the Backup. Please proceed with caution.",
|
||||||
|
"message.iso.ostype.different.from.backup": "Selected ISO has a different OS type than the Backup. Please proceed with caution.",
|
||||||
"message.action.delete.asnrange": "Please confirm the AS range that you want to delete",
|
"message.action.delete.asnrange": "Please confirm the AS range that you want to delete",
|
||||||
"message.action.delete.autoscale.vmgroup": "Please confirm that you want to delete this autoscaling group.",
|
"message.action.delete.autoscale.vmgroup": "Please confirm that you want to delete this autoscaling group.",
|
||||||
"message.action.delete.backup.offering": "Please confirm that you want to delete this backup offering?",
|
"message.action.delete.backup.offering": "Please confirm that you want to delete this backup offering?",
|
||||||
|
|||||||
@ -42,6 +42,11 @@
|
|||||||
{{ getTemplateDisplayName() }}
|
{{ getTemplateDisplayName() }}
|
||||||
</router-link>
|
</router-link>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-else-if="item === 'ostypeid'">
|
||||||
|
<router-link :to="{ path: '/guestos' + '/' + backupMetadata[item] }">
|
||||||
|
{{ backupMetadata.osname }}
|
||||||
|
</router-link>
|
||||||
|
</div>
|
||||||
<div v-else-if="item === 'serviceofferingid'">
|
<div v-else-if="item === 'serviceofferingid'">
|
||||||
<router-link :to="{ path: '/computeoffering/' + backupMetadata[item] }">
|
<router-link :to="{ path: '/computeoffering/' + backupMetadata[item] }">
|
||||||
{{ getServiceOfferingDisplayName() }}
|
{{ getServiceOfferingDisplayName() }}
|
||||||
@ -84,15 +89,14 @@ export default {
|
|||||||
if (!this.backupMetadata || Object.keys(this.backupMetadata).length === 0) {
|
if (!this.backupMetadata || Object.keys(this.backupMetadata).length === 0) {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
const fieldOrder = []
|
const fieldOrder = [
|
||||||
fieldOrder.push('templateid')
|
'templateid',
|
||||||
if (this.backupMetadata.isiso === 'true') {
|
'ostypeid',
|
||||||
fieldOrder.push('hypervisor')
|
'hypervisor',
|
||||||
}
|
'serviceofferingid',
|
||||||
fieldOrder.push('serviceofferingid')
|
'nics',
|
||||||
fieldOrder.push('nics')
|
'vmsettings'
|
||||||
fieldOrder.push('vmsettings')
|
]
|
||||||
|
|
||||||
return fieldOrder.filter(field => this.backupMetadata[field] !== undefined)
|
return fieldOrder.filter(field => this.backupMetadata[field] !== undefined)
|
||||||
},
|
},
|
||||||
getNicEntities () {
|
getNicEntities () {
|
||||||
|
|||||||
@ -168,6 +168,23 @@
|
|||||||
:tabList="tabList"
|
:tabList="tabList"
|
||||||
:activeTabKey="tabKey"
|
:activeTabKey="tabKey"
|
||||||
@tabChange="key => onTabChange(key, 'tabKey')">
|
@tabChange="key => onTabChange(key, 'tabKey')">
|
||||||
|
<a-alert
|
||||||
|
v-if="showOsTypeWarning && selectedTemplateIso"
|
||||||
|
style="margin-bottom: 10px">
|
||||||
|
<template #message>
|
||||||
|
<div>
|
||||||
|
{{ selectedTemplateIso.message }}<br>
|
||||||
|
{{ selectedTemplateIso.label }} :
|
||||||
|
<router-link :to="{ path: '/guestos/' + selectedTemplateIso.item.ostypeid }">
|
||||||
|
{{ selectedTemplateIso.item.ostypename }}
|
||||||
|
</router-link><br>
|
||||||
|
{{ $t('label.backup') }} :
|
||||||
|
<router-link :to="{ path: '/guestos/' + dataPreFill.ostypeid }">
|
||||||
|
{{ dataPreFill.ostypename }}
|
||||||
|
</router-link>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</a-alert>
|
||||||
<div v-if="tabKey === 'templateid'">
|
<div v-if="tabKey === 'templateid'">
|
||||||
{{ $t('message.template.desc') }}
|
{{ $t('message.template.desc') }}
|
||||||
<div v-if="isZoneSelectedMultiArch" style="width: 100%; margin-top: 5px">
|
<div v-if="isZoneSelectedMultiArch" style="width: 100%; margin-top: 5px">
|
||||||
@ -933,6 +950,7 @@ export default {
|
|||||||
dataPreFill: {},
|
dataPreFill: {},
|
||||||
showDetails: false,
|
showDetails: false,
|
||||||
showRootDiskSizeChanger: false,
|
showRootDiskSizeChanger: false,
|
||||||
|
showOsTypeWarning: false,
|
||||||
showOverrideDiskOfferingOption: false,
|
showOverrideDiskOfferingOption: false,
|
||||||
securitygroupids: [],
|
securitygroupids: [],
|
||||||
rootDiskSizeFixed: 0,
|
rootDiskSizeFixed: 0,
|
||||||
@ -978,6 +996,15 @@ export default {
|
|||||||
isNormalUserOrProject () {
|
isNormalUserOrProject () {
|
||||||
return ['User'].includes(this.$store.getters.userInfo.roletype) || store.getters.project.id
|
return ['User'].includes(this.$store.getters.userInfo.roletype) || store.getters.project.id
|
||||||
},
|
},
|
||||||
|
selectedTemplateIso () {
|
||||||
|
if (this.tabKey === 'templateid' && this.template?.ostypeid) {
|
||||||
|
return { label: this.$t('label.template'), item: this.template, message: this.$t('message.template.ostype.different.from.backup') }
|
||||||
|
}
|
||||||
|
if (this.tabKey === 'isoid' && this.iso?.ostypeid) {
|
||||||
|
return { label: this.$t('label.iso'), item: this.iso, message: this.$t('message.iso.ostype.different.from.backup') }
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
},
|
||||||
diskSize () {
|
diskSize () {
|
||||||
const customRootDiskSize = _.get(this.instanceConfig, 'rootdisksize', null)
|
const customRootDiskSize = _.get(this.instanceConfig, 'rootdisksize', null)
|
||||||
const customDataDiskSize = _.get(this.instanceConfig, 'size', null)
|
const customDataDiskSize = _.get(this.instanceConfig, 'size', null)
|
||||||
@ -1687,6 +1714,7 @@ export default {
|
|||||||
this.form.iothreadsenabled = template.details && Object.prototype.hasOwnProperty.call(template.details, 'iothreads')
|
this.form.iothreadsenabled = template.details && Object.prototype.hasOwnProperty.call(template.details, 'iothreads')
|
||||||
this.form.iodriverpolicy = template.details?.['io.policy']
|
this.form.iodriverpolicy = template.details?.['io.policy']
|
||||||
this.form.keyboard = template.details?.keyboard
|
this.form.keyboard = template.details?.keyboard
|
||||||
|
this.showOsTypeWarning = this.dataPreFill.ostypeid && template.ostypeid !== this.dataPreFill.ostypeid
|
||||||
if (template.details['vmware-to-kvm-mac-addresses']) {
|
if (template.details['vmware-to-kvm-mac-addresses']) {
|
||||||
this.dataPreFill.macAddressArray = JSON.parse(template.details['vmware-to-kvm-mac-addresses'])
|
this.dataPreFill.macAddressArray = JSON.parse(template.details['vmware-to-kvm-mac-addresses'])
|
||||||
}
|
}
|
||||||
@ -1700,6 +1728,13 @@ export default {
|
|||||||
this.tabKey = 'isoid'
|
this.tabKey = 'isoid'
|
||||||
this.form.isoid = value
|
this.form.isoid = value
|
||||||
this.form.templateid = null
|
this.form.templateid = null
|
||||||
|
for (const key in this.options.isos) {
|
||||||
|
var iso = _.find(_.get(this.options.isos[key], 'iso', []), (option) => option.id === value)
|
||||||
|
if (iso) {
|
||||||
|
this.showOsTypeWarning = this.dataPreFill.ostypeid && iso.ostypeid !== this.dataPreFill.ostypeid
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if (['cpuspeed', 'cpunumber', 'memory'].includes(name)) {
|
} else if (['cpuspeed', 'cpunumber', 'memory'].includes(name)) {
|
||||||
this.vm[name] = value
|
this.vm[name] = value
|
||||||
this.form[name] = value
|
this.form[name] = value
|
||||||
|
|||||||
@ -29,7 +29,7 @@
|
|||||||
<a-form-item :label="$t('label.name.optional')" name="name">
|
<a-form-item :label="$t('label.name.optional')" name="name">
|
||||||
<a-input v-model:value="form.name" />
|
<a-input v-model:value="form.name" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item v-if="!resource.virtualmachineid" name="preserveIpAddresses" style="margin-top: 8px">
|
<a-form-item v-if="resource.isbackupvmexpunged" name="preserveIpAddresses" style="margin-top: 8px">
|
||||||
<a-switch v-model:checked="form.preserveIpAddresses" />
|
<a-switch v-model:checked="form.preserveIpAddresses" />
|
||||||
<template #label>
|
<template #label>
|
||||||
<tooltip-label :title="$t('label.use.backup.ip.address')" :tooltip="$t('label.use.backup.ip.address.tooltip')"/>
|
<tooltip-label :title="$t('label.use.backup.ip.address')" :tooltip="$t('label.use.backup.ip.address.tooltip')"/>
|
||||||
@ -91,16 +91,16 @@ export default {
|
|||||||
required: true
|
required: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created () {
|
async created () {
|
||||||
this.fetchServiceOffering()
|
await Promise.all[(
|
||||||
this.fetchBackupOffering().then(() => {
|
this.fetchServiceOffering(),
|
||||||
this.fetchBackupRepository()
|
this.fetchBackupOffering()
|
||||||
this.loading = false
|
)]
|
||||||
})
|
this.loading = false
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
fetchServiceOffering () {
|
fetchServiceOffering () {
|
||||||
getAPI('listServiceOfferings', {
|
return getAPI('listServiceOfferings', {
|
||||||
zoneid: this.resource.zoneid,
|
zoneid: this.resource.zoneid,
|
||||||
id: this.resource.vmdetails.serviceofferingid,
|
id: this.resource.vmdetails.serviceofferingid,
|
||||||
listall: true
|
listall: true
|
||||||
@ -118,28 +118,19 @@ export default {
|
|||||||
this.backupOffering = backupOfferings[0]
|
this.backupOffering = backupOfferings[0]
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
fetchBackupRepository () {
|
|
||||||
if (this.backupOffering.provider !== 'nas') {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
getAPI('listBackupRepositories', {
|
|
||||||
id: this.backupOffering.externalid
|
|
||||||
}).then(response => {
|
|
||||||
const backupRepositories = response.listbackuprepositoriesresponse.backuprepository || []
|
|
||||||
this.backupRepository = backupRepositories[0]
|
|
||||||
})
|
|
||||||
},
|
|
||||||
populatePreFillData () {
|
populatePreFillData () {
|
||||||
this.vmdetails = this.resource.vmdetails
|
this.vmdetails = this.resource.vmdetails
|
||||||
this.dataPreFill.zoneid = this.resource.zoneid
|
this.dataPreFill.zoneid = this.resource.zoneid
|
||||||
this.dataPreFill.crosszoneinstancecreation = this.backupRepository?.crosszoneinstancecreation || this.backupOffering.provider === 'dummy'
|
this.dataPreFill.crosszoneinstancecreation = this.backupOffering?.crosszoneinstancecreation || this.backupOffering.provider === 'dummy'
|
||||||
this.dataPreFill.isIso = (this.vmdetails.isiso === 'true')
|
this.dataPreFill.isIso = (this.vmdetails.isiso === 'true')
|
||||||
|
this.dataPreFill.ostypeid = this.resource.vmdetails.ostypeid
|
||||||
|
this.dataPreFill.ostypename = this.resource.vmdetails.osname
|
||||||
this.dataPreFill.backupid = this.resource.id
|
this.dataPreFill.backupid = this.resource.id
|
||||||
this.dataPreFill.computeofferingid = this.vmdetails.serviceofferingid
|
this.dataPreFill.computeofferingid = this.vmdetails.serviceofferingid
|
||||||
this.dataPreFill.templateid = this.vmdetails.templateid
|
this.dataPreFill.templateid = this.vmdetails.templateid
|
||||||
this.dataPreFill.allowtemplateisoselection = true
|
this.dataPreFill.allowtemplateisoselection = true
|
||||||
this.dataPreFill.isoid = this.vmdetails.templateid
|
this.dataPreFill.isoid = this.vmdetails.templateid
|
||||||
this.dataPreFill.allowIpAddressesFetch = !this.resource.virtualmachineid
|
this.dataPreFill.allowIpAddressesFetch = this.resource.isbackupvmexpunged
|
||||||
if (this.vmdetails.nics) {
|
if (this.vmdetails.nics) {
|
||||||
const nics = JSON.parse(this.vmdetails.nics)
|
const nics = JSON.parse(this.vmdetails.nics)
|
||||||
this.dataPreFill.networkids = nics.map(nic => nic.networkid)
|
this.dataPreFill.networkids = nics.map(nic => nic.networkid)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user