use of com.cloud.agent.api.to.DataStoreTO in project cloudstack by apache.
the class VmwareStorageProcessor method attachVolume.
private Answer attachVolume(Command cmd, DiskTO disk, boolean isAttach, boolean isManaged, String vmName, String iScsiName, String storageHost, int storagePort, Map<String, String> controllerInfo) {
VolumeObjectTO volumeTO = (VolumeObjectTO) disk.getData();
DataStoreTO primaryStore = volumeTO.getDataStore();
try {
VmwareContext context = hostService.getServiceContext(null);
VmwareHypervisorHost hyperHost = hostService.getHyperHost(context, null);
VirtualMachineMO vmMo = hyperHost.findVmOnHyperHost(vmName);
if (vmMo == null) {
String msg = "Unable to find the VM to execute AttachCommand, vmName: " + vmName;
s_logger.error(msg);
throw new Exception(msg);
}
vmName = vmMo.getName();
ManagedObjectReference morDs = null;
String diskUuid = volumeTO.getUuid().replace("-", "");
if (isAttach && isManaged) {
Map<String, String> details = disk.getDetails();
morDs = prepareManagedStorage(context, hyperHost, diskUuid, iScsiName, storageHost, storagePort, null, details.get(DiskTO.CHAP_INITIATOR_USERNAME), details.get(DiskTO.CHAP_INITIATOR_SECRET), details.get(DiskTO.CHAP_TARGET_USERNAME), details.get(DiskTO.CHAP_TARGET_SECRET), volumeTO.getSize(), cmd);
} else {
if (storagePort == DEFAULT_NFS_PORT) {
morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, isManaged ? VmwareResource.getDatastoreName(diskUuid) : primaryStore.getUuid());
} else {
morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, isManaged ? VmwareResource.getDatastoreName(iScsiName) : primaryStore.getUuid());
}
}
if (morDs == null) {
String msg = "Unable to find the mounted datastore to execute AttachCommand, vmName: " + vmName;
s_logger.error(msg);
throw new Exception(msg);
}
DatastoreMO dsMo = new DatastoreMO(context, morDs);
String datastoreVolumePath;
if (isAttach) {
if (isManaged) {
datastoreVolumePath = dsMo.getDatastorePath(dsMo.getName() + ".vmdk");
} else {
datastoreVolumePath = VmwareStorageLayoutHelper.syncVolumeToVmDefaultFolder(dsMo.getOwnerDatacenter().first(), vmName, dsMo, volumeTO.getPath());
}
} else {
if (isManaged) {
datastoreVolumePath = dsMo.getDatastorePath(dsMo.getName() + ".vmdk");
} else {
datastoreVolumePath = VmwareStorageLayoutHelper.getLegacyDatastorePathFromVmdkFileName(dsMo, volumeTO.getPath() + ".vmdk");
if (!dsMo.fileExists(datastoreVolumePath)) {
datastoreVolumePath = VmwareStorageLayoutHelper.getVmwareDatastorePathFromVmdkFileName(dsMo, vmName, volumeTO.getPath() + ".vmdk");
}
}
}
disk.setPath(datastoreVolumePath);
AttachAnswer answer = new AttachAnswer(disk);
if (isAttach) {
String diskController = getLegacyVmDataDiskController();
if (controllerInfo != null && !Strings.isNullOrEmpty(controllerInfo.get(VmDetailConstants.DATA_DISK_CONTROLLER))) {
diskController = controllerInfo.get(VmDetailConstants.DATA_DISK_CONTROLLER);
}
if (DiskControllerType.getType(diskController) == DiskControllerType.osdefault) {
diskController = vmMo.getRecommendedDiskController(null);
}
vmMo.attachDisk(new String[] { datastoreVolumePath }, morDs, diskController);
} else {
vmMo.removeAllSnapshots();
vmMo.detachDisk(datastoreVolumePath, false);
if (isManaged) {
handleDatastoreAndVmdkDetachManaged(diskUuid, iScsiName, storageHost, storagePort);
} else {
VmwareStorageLayoutHelper.syncVolumeToRootFolder(dsMo.getOwnerDatacenter().first(), dsMo, volumeTO.getPath(), vmName);
}
}
return answer;
} catch (Throwable e) {
if (e instanceof RemoteException) {
s_logger.warn("Encounter remote exception to vCenter, invalidate VMware session context");
hostService.invalidateServiceContext(null);
}
String msg = "";
if (isAttach)
msg += "Failed to attach volume: " + e.getMessage();
else
msg += "Failed to detach volume: " + e.getMessage();
s_logger.error(msg, e);
return new AttachAnswer(msg);
}
}
use of com.cloud.agent.api.to.DataStoreTO in project cloudstack by apache.
the class VmwareStorageProcessor method deleteVolume.
@Override
public Answer deleteVolume(DeleteCommand cmd) {
if (s_logger.isInfoEnabled()) {
s_logger.info("Executing resource DeleteCommand: " + _gson.toJson(cmd));
}
try {
VmwareContext context = hostService.getServiceContext(null);
VmwareHypervisorHost hyperHost = hostService.getHyperHost(context, null);
VolumeObjectTO vol = (VolumeObjectTO) cmd.getData();
DataStoreTO store = vol.getDataStore();
PrimaryDataStoreTO primaryDataStoreTO = (PrimaryDataStoreTO) store;
Map<String, String> details = primaryDataStoreTO.getDetails();
boolean isManaged = false;
String managedDatastoreName = null;
if (details != null) {
isManaged = Boolean.parseBoolean(details.get(PrimaryDataStoreTO.MANAGED));
if (isManaged) {
managedDatastoreName = getManagedDatastoreNameFromPath(vol.getPath());
}
}
ManagedObjectReference morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, isManaged ? managedDatastoreName : store.getUuid());
if (morDs == null) {
String msg = "Unable to find datastore based on volume mount point " + store.getUuid();
s_logger.error(msg);
throw new Exception(msg);
}
DatastoreMO dsMo = new DatastoreMO(context, morDs);
ManagedObjectReference morDc = hyperHost.getHyperHostDatacenter();
ManagedObjectReference morCluster = hyperHost.getHyperHostCluster();
ClusterMO clusterMo = new ClusterMO(context, morCluster);
if (vol.getVolumeType() == Volume.Type.ROOT) {
String vmName = vol.getVmName();
if (vmName != null) {
VirtualMachineMO vmMo = clusterMo.findVmOnHyperHost(vmName);
if (vmMo == null) {
// Volume might be on a zone-wide storage pool, look for VM in datacenter
DatacenterMO dcMo = new DatacenterMO(context, morDc);
vmMo = dcMo.findVm(vmName);
}
if (vmMo != null) {
if (s_logger.isInfoEnabled()) {
s_logger.info("Destroy root volume and VM itself. vmName " + vmName);
}
VirtualMachineDiskInfo diskInfo = null;
if (vol.getChainInfo() != null)
diskInfo = _gson.fromJson(vol.getChainInfo(), VirtualMachineDiskInfo.class);
HostMO hostMo = vmMo.getRunningHost();
List<NetworkDetails> networks = vmMo.getNetworksWithDetails();
// tear down all devices first before we destroy the VM to avoid accidently delete disk backing files
if (VmwareResource.getVmState(vmMo) != PowerState.PowerOff) {
vmMo.safePowerOff(_shutdownWaitMs);
}
// call this before calling detachAllDisksExcept
// when expunging a VM, we need to see if any of its disks are serviced by managed storage
// if there is one or more disk serviced by managed storage, remove the iSCSI connection(s)
// don't remove the iSCSI connection(s) until the supported disk(s) is/are removed from the VM
// (removeManagedTargetsFromCluster should be called after detachAllDisksExcept and vm.destroy)
List<VirtualDisk> virtualDisks = vmMo.getVirtualDisks();
List<String> managedIqns = getManagedIqnsFromVirtualDisks(virtualDisks);
List<String> detachedDisks = vmMo.detachAllDisksExcept(vol.getPath(), diskInfo != null ? diskInfo.getDiskDeviceBusName() : null);
VmwareStorageLayoutHelper.moveVolumeToRootFolder(new DatacenterMO(context, morDc), detachedDisks);
if (isManaged) {
vmMo.unregisterVm();
} else {
vmMo.destroy();
}
// this.hostService.handleDatastoreAndVmdkDetach(iScsiName, storageHost, storagePort);
if (managedIqns != null && !managedIqns.isEmpty()) {
removeManagedTargetsFromCluster(managedIqns);
}
for (NetworkDetails netDetails : networks) {
if (netDetails.getGCTag() != null && netDetails.getGCTag().equalsIgnoreCase("true")) {
if (netDetails.getVMMorsOnNetwork() == null || netDetails.getVMMorsOnNetwork().length == 1) {
resource.cleanupNetwork(hostMo, netDetails);
}
}
}
}
/*
if (s_logger.isInfoEnabled()) {
s_logger.info("Destroy volume by original name: " + vol.getPath() + ".vmdk");
}
VmwareStorageLayoutHelper.deleteVolumeVmdkFiles(dsMo, vol.getPath(), new DatacenterMO(context, morDc));
*/
return new Answer(cmd, true, "Success");
}
if (s_logger.isInfoEnabled()) {
s_logger.info("Destroy root volume directly from datastore");
}
}
VmwareStorageLayoutHelper.deleteVolumeVmdkFiles(dsMo, vol.getPath(), new DatacenterMO(context, morDc));
return new Answer(cmd, true, "Success");
} catch (Throwable e) {
if (e instanceof RemoteException) {
s_logger.warn("Encounter remote exception to vCenter, invalidate VMware session context");
hostService.invalidateServiceContext(null);
}
String msg = "delete volume failed due to " + VmwareHelper.getExceptionMessage(e);
s_logger.error(msg, e);
return new Answer(cmd, false, msg);
}
}
use of com.cloud.agent.api.to.DataStoreTO in project cloudstack by apache.
the class VmwareStorageProcessor method createVolume.
@Override
public Answer createVolume(CreateObjectCommand cmd) {
VolumeObjectTO volume = (VolumeObjectTO) cmd.getData();
DataStoreTO primaryStore = volume.getDataStore();
try {
VmwareContext context = hostService.getServiceContext(null);
VmwareHypervisorHost hyperHost = hostService.getHyperHost(context, null);
DatacenterMO dcMo = new DatacenterMO(context, hyperHost.getHyperHostDatacenter());
ManagedObjectReference morDatastore = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, primaryStore.getUuid());
if (morDatastore == null) {
throw new Exception("Unable to find datastore in vSphere");
}
DatastoreMO dsMo = new DatastoreMO(context, morDatastore);
// create data volume
VirtualMachineMO vmMo = null;
String volumeUuid = UUID.randomUUID().toString().replace("-", "");
String volumeDatastorePath = dsMo.getDatastorePath(volumeUuid + ".vmdk");
String dummyVmName = hostService.getWorkerName(context, cmd, 0);
try {
s_logger.info("Create worker VM " + dummyVmName);
vmMo = HypervisorHostHelper.createWorkerVM(hyperHost, dsMo, dummyVmName);
if (vmMo == null) {
throw new Exception("Unable to create a dummy VM for volume creation");
}
synchronized (this) {
try {
vmMo.createDisk(volumeDatastorePath, (int) (volume.getSize() / (1024L * 1024L)), morDatastore, vmMo.getScsiDeviceControllerKey());
vmMo.detachDisk(volumeDatastorePath, false);
} catch (Exception e) {
s_logger.error("Deleting file " + volumeDatastorePath + " due to error: " + e.getMessage());
VmwareStorageLayoutHelper.deleteVolumeVmdkFiles(dsMo, volumeUuid.toString(), dcMo);
throw new CloudRuntimeException("Unable to create volume due to: " + e.getMessage());
}
}
VolumeObjectTO newVol = new VolumeObjectTO();
newVol.setPath(volumeUuid);
newVol.setSize(volume.getSize());
return new CreateObjectAnswer(newVol);
} finally {
s_logger.info("Destroy dummy VM after volume creation");
if (vmMo != null) {
vmMo.detachAllDisks();
vmMo.destroy();
}
}
} catch (Throwable e) {
if (e instanceof RemoteException) {
s_logger.warn("Encounter remote exception to vCenter, invalidate VMware session context");
hostService.invalidateServiceContext(null);
}
String msg = "create volume failed due to " + VmwareHelper.getExceptionMessage(e);
s_logger.error(msg, e);
return new CreateObjectAnswer(e.toString());
}
}
use of com.cloud.agent.api.to.DataStoreTO in project cloudstack by apache.
the class VmwareResource method execute.
protected StartAnswer execute(StartCommand cmd) {
if (s_logger.isInfoEnabled()) {
s_logger.info("Executing resource StartCommand: " + _gson.toJson(cmd));
}
VirtualMachineTO vmSpec = cmd.getVirtualMachine();
boolean vmAlreadyExistsInVcenter = false;
String existingVmName = null;
VirtualMachineFileInfo existingVmFileInfo = null;
VirtualMachineFileLayoutEx existingVmFileLayout = null;
Pair<String, String> names = composeVmNames(vmSpec);
String vmInternalCSName = names.first();
String vmNameOnVcenter = names.second();
String dataDiskController = vmSpec.getDetails().get(VmDetailConstants.DATA_DISK_CONTROLLER);
String rootDiskController = vmSpec.getDetails().get(VmDetailConstants.ROOT_DISK_CONTROLLER);
DiskTO rootDiskTO = null;
// This helps avoid mix of different scsi subtype controllers in instance.
if (DiskControllerType.lsilogic == DiskControllerType.getType(rootDiskController)) {
dataDiskController = DiskControllerType.scsi.toString();
}
// Validate the controller types
dataDiskController = DiskControllerType.getType(dataDiskController).toString();
rootDiskController = DiskControllerType.getType(rootDiskController).toString();
if (DiskControllerType.getType(rootDiskController) == DiskControllerType.none) {
throw new CloudRuntimeException("Invalid root disk controller detected : " + rootDiskController);
}
if (DiskControllerType.getType(dataDiskController) == DiskControllerType.none) {
throw new CloudRuntimeException("Invalid data disk controller detected : " + dataDiskController);
}
Pair<String, String> controllerInfo = new Pair<String, String>(rootDiskController, dataDiskController);
Boolean systemVm = vmSpec.getType().isUsedBySystem();
// Thus, vmInternalCSName always holds i-x-y, the cloudstack generated internal VM name.
VmwareContext context = getServiceContext();
DatacenterMO dcMo = null;
try {
VmwareManager mgr = context.getStockObject(VmwareManager.CONTEXT_STOCK_NAME);
VmwareHypervisorHost hyperHost = getHyperHost(context);
dcMo = new DatacenterMO(hyperHost.getContext(), hyperHost.getHyperHostDatacenter());
// Validate VM name is unique in Datacenter
VirtualMachineMO vmInVcenter = dcMo.checkIfVmAlreadyExistsInVcenter(vmNameOnVcenter, vmInternalCSName);
if (vmInVcenter != null) {
vmAlreadyExistsInVcenter = true;
String msg = "VM with name: " + vmNameOnVcenter + " already exists in vCenter.";
s_logger.error(msg);
throw new Exception(msg);
}
String guestOsId = translateGuestOsIdentifier(vmSpec.getArch(), vmSpec.getOs(), vmSpec.getPlatformEmulator()).value();
DiskTO[] disks = validateDisks(vmSpec.getDisks());
assert (disks.length > 0);
NicTO[] nics = vmSpec.getNics();
HashMap<String, Pair<ManagedObjectReference, DatastoreMO>> dataStoresDetails = inferDatastoreDetailsFromDiskInfo(hyperHost, context, disks, cmd);
if ((dataStoresDetails == null) || (dataStoresDetails.isEmpty())) {
String msg = "Unable to locate datastore details of the volumes to be attached";
s_logger.error(msg);
throw new Exception(msg);
}
DatastoreMO dsRootVolumeIsOn = getDatastoreThatRootDiskIsOn(dataStoresDetails, disks);
if (dsRootVolumeIsOn == null) {
String msg = "Unable to locate datastore details of root volume";
s_logger.error(msg);
throw new Exception(msg);
}
VirtualMachineDiskInfoBuilder diskInfoBuilder = null;
VirtualMachineMO vmMo = hyperHost.findVmOnHyperHost(vmInternalCSName);
DiskControllerType systemVmScsiControllerType = DiskControllerType.lsilogic;
int firstScsiControllerBusNum = 0;
int numScsiControllerForSystemVm = 1;
boolean hasSnapshot = false;
if (vmMo != null) {
s_logger.info("VM " + vmInternalCSName + " already exists, tear down devices for reconfiguration");
if (getVmPowerState(vmMo) != PowerState.PowerOff)
vmMo.safePowerOff(_shutdownWaitMs);
// retrieve disk information before we tear down
diskInfoBuilder = vmMo.getDiskInfoBuilder();
hasSnapshot = vmMo.hasSnapshot();
if (!hasSnapshot)
vmMo.tearDownDevices(new Class<?>[] { VirtualDisk.class, VirtualEthernetCard.class });
else
vmMo.tearDownDevices(new Class<?>[] { VirtualEthernetCard.class });
if (systemVm) {
ensureScsiDiskControllers(vmMo, systemVmScsiControllerType.toString(), numScsiControllerForSystemVm, firstScsiControllerBusNum);
} else {
ensureDiskControllers(vmMo, controllerInfo);
}
} else {
ManagedObjectReference morDc = hyperHost.getHyperHostDatacenter();
assert (morDc != null);
vmMo = hyperHost.findVmOnPeerHyperHost(vmInternalCSName);
if (vmMo != null) {
if (s_logger.isInfoEnabled()) {
s_logger.info("Found vm " + vmInternalCSName + " at other host, relocate to " + hyperHost.getHyperHostName());
}
takeVmFromOtherHyperHost(hyperHost, vmInternalCSName);
if (getVmPowerState(vmMo) != PowerState.PowerOff)
vmMo.safePowerOff(_shutdownWaitMs);
diskInfoBuilder = vmMo.getDiskInfoBuilder();
hasSnapshot = vmMo.hasSnapshot();
if (!hasSnapshot)
vmMo.tearDownDevices(new Class<?>[] { VirtualDisk.class, VirtualEthernetCard.class });
else
vmMo.tearDownDevices(new Class<?>[] { VirtualEthernetCard.class });
if (systemVm) {
// System volumes doesn't require more than 1 SCSI controller as there is no requirement for data volumes.
ensureScsiDiskControllers(vmMo, systemVmScsiControllerType.toString(), numScsiControllerForSystemVm, firstScsiControllerBusNum);
} else {
ensureDiskControllers(vmMo, controllerInfo);
}
} else {
// If a VM with the same name is found in a different cluster in the DC, unregister the old VM and configure a new VM (cold-migration).
VirtualMachineMO existingVmInDc = dcMo.findVm(vmInternalCSName);
if (existingVmInDc != null) {
s_logger.debug("Found VM: " + vmInternalCSName + " on a host in a different cluster. Unregistering the exisitng VM.");
existingVmName = existingVmInDc.getName();
existingVmFileInfo = existingVmInDc.getFileInfo();
existingVmFileLayout = existingVmInDc.getFileLayout();
existingVmInDc.unregisterVm();
}
Pair<ManagedObjectReference, DatastoreMO> rootDiskDataStoreDetails = null;
for (DiskTO vol : disks) {
if (vol.getType() == Volume.Type.ROOT) {
Map<String, String> details = vol.getDetails();
boolean managed = false;
if (details != null) {
managed = Boolean.parseBoolean(details.get(DiskTO.MANAGED));
}
if (managed) {
String datastoreName = VmwareResource.getDatastoreName(details.get(DiskTO.IQN));
rootDiskDataStoreDetails = dataStoresDetails.get(datastoreName);
} else {
DataStoreTO primaryStore = vol.getData().getDataStore();
rootDiskDataStoreDetails = dataStoresDetails.get(primaryStore.getUuid());
}
}
}
assert (vmSpec.getMinSpeed() != null) && (rootDiskDataStoreDetails != null);
boolean vmFolderExists = rootDiskDataStoreDetails.second().folderExists(String.format("[%s]", rootDiskDataStoreDetails.second().getName()), vmNameOnVcenter);
String vmxFileFullPath = dsRootVolumeIsOn.searchFileInSubFolders(vmNameOnVcenter + ".vmx", false);
if (vmFolderExists && vmxFileFullPath != null) {
// VM can be registered only if .vmx is present.
registerVm(vmNameOnVcenter, dsRootVolumeIsOn);
vmMo = hyperHost.findVmOnHyperHost(vmInternalCSName);
if (vmMo != null) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Found registered vm " + vmInternalCSName + " at host " + hyperHost.getHyperHostName());
}
}
tearDownVm(vmMo);
} else if (!hyperHost.createBlankVm(vmNameOnVcenter, vmInternalCSName, vmSpec.getCpus(), vmSpec.getMaxSpeed().intValue(), getReservedCpuMHZ(vmSpec), vmSpec.getLimitCpuUse(), (int) (vmSpec.getMaxRam() / (1024 * 1024)), getReservedMemoryMb(vmSpec), guestOsId, rootDiskDataStoreDetails.first(), false, controllerInfo, systemVm)) {
throw new Exception("Failed to create VM. vmName: " + vmInternalCSName);
}
}
vmMo = hyperHost.findVmOnHyperHost(vmInternalCSName);
if (vmMo == null) {
throw new Exception("Failed to find the newly create or relocated VM. vmName: " + vmInternalCSName);
}
}
int totalChangeDevices = disks.length + nics.length;
DiskTO volIso = null;
if (vmSpec.getType() != VirtualMachine.Type.User) {
// system VM needs a patch ISO
totalChangeDevices++;
} else {
volIso = getIsoDiskTO(disks);
if (volIso == null)
totalChangeDevices++;
}
VirtualMachineConfigSpec vmConfigSpec = new VirtualMachineConfigSpec();
VmwareHelper.setBasicVmConfig(vmConfigSpec, vmSpec.getCpus(), vmSpec.getMaxSpeed(), getReservedCpuMHZ(vmSpec), (int) (vmSpec.getMaxRam() / (1024 * 1024)), getReservedMemoryMb(vmSpec), guestOsId, vmSpec.getLimitCpuUse());
// Check for multi-cores per socket settings
int numCoresPerSocket = 1;
String coresPerSocket = vmSpec.getDetails().get("cpu.corespersocket");
if (coresPerSocket != null) {
String apiVersion = HypervisorHostHelper.getVcenterApiVersion(vmMo.getContext());
// Property 'numCoresPerSocket' is supported since vSphere API 5.0
if (apiVersion.compareTo("5.0") >= 0) {
numCoresPerSocket = NumbersUtil.parseInt(coresPerSocket, 1);
vmConfigSpec.setNumCoresPerSocket(numCoresPerSocket);
}
}
// Check for hotadd settings
vmConfigSpec.setMemoryHotAddEnabled(vmMo.isMemoryHotAddSupported(guestOsId));
String hostApiVersion = ((HostMO) hyperHost).getHostAboutInfo().getApiVersion();
if (numCoresPerSocket > 1 && hostApiVersion.compareTo("5.0") < 0) {
s_logger.warn("Dynamic scaling of CPU is not supported for Virtual Machines with multi-core vCPUs in case of ESXi hosts 4.1 and prior. Hence CpuHotAdd will not be" + " enabled for Virtual Machine: " + vmInternalCSName);
vmConfigSpec.setCpuHotAddEnabled(false);
} else {
vmConfigSpec.setCpuHotAddEnabled(vmMo.isCpuHotAddSupported(guestOsId));
}
configNestedHVSupport(vmMo, vmSpec, vmConfigSpec);
VirtualDeviceConfigSpec[] deviceConfigSpecArray = new VirtualDeviceConfigSpec[totalChangeDevices];
int i = 0;
int ideUnitNumber = 0;
int scsiUnitNumber = 0;
int nicUnitNumber = 0;
int ideControllerKey = vmMo.getIDEDeviceControllerKey();
int scsiControllerKey = vmMo.getGenericScsiDeviceControllerKeyNoException();
int controllerKey;
// prepare systemvm patch ISO
if (vmSpec.getType() != VirtualMachine.Type.User) {
// attach ISO (for patching of system VM)
Pair<String, Long> secStoreUrlAndId = mgr.getSecondaryStorageStoreUrlAndId(Long.parseLong(_dcId));
String secStoreUrl = secStoreUrlAndId.first();
Long secStoreId = secStoreUrlAndId.second();
if (secStoreUrl == null) {
String msg = "secondary storage for dc " + _dcId + " is not ready yet?";
throw new Exception(msg);
}
mgr.prepareSecondaryStorageStore(secStoreUrl, secStoreId);
ManagedObjectReference morSecDs = prepareSecondaryDatastoreOnHost(secStoreUrl);
if (morSecDs == null) {
String msg = "Failed to prepare secondary storage on host, secondary store url: " + secStoreUrl;
throw new Exception(msg);
}
DatastoreMO secDsMo = new DatastoreMO(hyperHost.getContext(), morSecDs);
deviceConfigSpecArray[i] = new VirtualDeviceConfigSpec();
Pair<VirtualDevice, Boolean> isoInfo = VmwareHelper.prepareIsoDevice(vmMo, String.format("[%s] systemvm/%s", secDsMo.getName(), mgr.getSystemVMIsoFileNameOnDatastore()), secDsMo.getMor(), true, true, ideUnitNumber++, i + 1);
deviceConfigSpecArray[i].setDevice(isoInfo.first());
if (isoInfo.second()) {
if (s_logger.isDebugEnabled())
s_logger.debug("Prepare ISO volume at new device " + _gson.toJson(isoInfo.first()));
deviceConfigSpecArray[i].setOperation(VirtualDeviceConfigSpecOperation.ADD);
} else {
if (s_logger.isDebugEnabled())
s_logger.debug("Prepare ISO volume at existing device " + _gson.toJson(isoInfo.first()));
deviceConfigSpecArray[i].setOperation(VirtualDeviceConfigSpecOperation.EDIT);
}
} else {
// Note: we will always plug a CDROM device
if (volIso != null) {
TemplateObjectTO iso = (TemplateObjectTO) volIso.getData();
if (iso.getPath() != null && !iso.getPath().isEmpty()) {
DataStoreTO imageStore = iso.getDataStore();
if (!(imageStore instanceof NfsTO)) {
s_logger.debug("unsupported protocol");
throw new Exception("unsupported protocol");
}
NfsTO nfsImageStore = (NfsTO) imageStore;
String isoPath = nfsImageStore.getUrl() + File.separator + iso.getPath();
Pair<String, ManagedObjectReference> isoDatastoreInfo = getIsoDatastoreInfo(hyperHost, isoPath);
assert (isoDatastoreInfo != null);
assert (isoDatastoreInfo.second() != null);
deviceConfigSpecArray[i] = new VirtualDeviceConfigSpec();
Pair<VirtualDevice, Boolean> isoInfo = VmwareHelper.prepareIsoDevice(vmMo, isoDatastoreInfo.first(), isoDatastoreInfo.second(), true, true, ideUnitNumber++, i + 1);
deviceConfigSpecArray[i].setDevice(isoInfo.first());
if (isoInfo.second()) {
if (s_logger.isDebugEnabled())
s_logger.debug("Prepare ISO volume at new device " + _gson.toJson(isoInfo.first()));
deviceConfigSpecArray[i].setOperation(VirtualDeviceConfigSpecOperation.ADD);
} else {
if (s_logger.isDebugEnabled())
s_logger.debug("Prepare ISO volume at existing device " + _gson.toJson(isoInfo.first()));
deviceConfigSpecArray[i].setOperation(VirtualDeviceConfigSpecOperation.EDIT);
}
}
} else {
deviceConfigSpecArray[i] = new VirtualDeviceConfigSpec();
Pair<VirtualDevice, Boolean> isoInfo = VmwareHelper.prepareIsoDevice(vmMo, null, null, true, true, ideUnitNumber++, i + 1);
deviceConfigSpecArray[i].setDevice(isoInfo.first());
if (isoInfo.second()) {
if (s_logger.isDebugEnabled())
s_logger.debug("Prepare ISO volume at existing device " + _gson.toJson(isoInfo.first()));
deviceConfigSpecArray[i].setOperation(VirtualDeviceConfigSpecOperation.ADD);
} else {
if (s_logger.isDebugEnabled())
s_logger.debug("Prepare ISO volume at existing device " + _gson.toJson(isoInfo.first()));
deviceConfigSpecArray[i].setOperation(VirtualDeviceConfigSpecOperation.EDIT);
}
}
}
i++;
//
// Setup ROOT/DATA disk devices
//
DiskTO[] sortedDisks = sortVolumesByDeviceId(disks);
for (DiskTO vol : sortedDisks) {
if (vol.getType() == Volume.Type.ISO)
continue;
VirtualMachineDiskInfo matchingExistingDisk = getMatchingExistingDisk(diskInfoBuilder, vol, hyperHost, context);
controllerKey = getDiskController(matchingExistingDisk, vol, vmSpec, ideControllerKey, scsiControllerKey);
String diskController = getDiskController(vmMo, matchingExistingDisk, vol, new Pair<String, String>(rootDiskController, dataDiskController));
if (DiskControllerType.getType(diskController) == DiskControllerType.osdefault) {
diskController = vmMo.getRecommendedDiskController(null);
}
if (DiskControllerType.getType(diskController) == DiskControllerType.ide) {
controllerKey = vmMo.getIDEControllerKey(ideUnitNumber);
if (vol.getType() == Volume.Type.DATADISK) {
// Ensure maximum of 2 data volumes over IDE controller, 3 includeing root volume
if (vmMo.getNumberOfVirtualDisks() > 3) {
throw new CloudRuntimeException("Found more than 3 virtual disks attached to this VM [" + vmMo.getVmName() + "]. Unable to implement the disks over " + diskController + " controller, as maximum number of devices supported over IDE controller is 4 includeing CDROM device.");
}
}
} else {
controllerKey = vmMo.getScsiDiskControllerKeyNoException(diskController);
if (controllerKey == -1) {
// This may happen for ROOT legacy VMs which doesn't have recommended disk controller when global configuration parameter 'vmware.root.disk.controller' is set to "osdefault"
// Retrieve existing controller and use.
Ternary<Integer, Integer, DiskControllerType> vmScsiControllerInfo = vmMo.getScsiControllerInfo();
DiskControllerType existingControllerType = vmScsiControllerInfo.third();
controllerKey = vmMo.getScsiDiskControllerKeyNoException(existingControllerType.toString());
}
}
if (!hasSnapshot) {
deviceConfigSpecArray[i] = new VirtualDeviceConfigSpec();
VolumeObjectTO volumeTO = (VolumeObjectTO) vol.getData();
DataStoreTO primaryStore = volumeTO.getDataStore();
Map<String, String> details = vol.getDetails();
boolean managed = false;
String iScsiName = null;
if (details != null) {
managed = Boolean.parseBoolean(details.get(DiskTO.MANAGED));
iScsiName = details.get(DiskTO.IQN);
}
// if the storage is managed, iScsiName should not be null
String datastoreName = managed ? VmwareResource.getDatastoreName(iScsiName) : primaryStore.getUuid();
Pair<ManagedObjectReference, DatastoreMO> volumeDsDetails = dataStoresDetails.get(datastoreName);
assert (volumeDsDetails != null);
String[] diskChain = syncDiskChain(dcMo, vmMo, vmSpec, vol, matchingExistingDisk, dataStoresDetails);
if (controllerKey == scsiControllerKey && VmwareHelper.isReservedScsiDeviceNumber(scsiUnitNumber))
scsiUnitNumber++;
VirtualDevice device = VmwareHelper.prepareDiskDevice(vmMo, null, controllerKey, diskChain, volumeDsDetails.first(), (controllerKey == vmMo.getIDEControllerKey(ideUnitNumber)) ? ((ideUnitNumber++) % VmwareHelper.MAX_IDE_CONTROLLER_COUNT) : scsiUnitNumber++, i + 1);
if (vol.getType() == Volume.Type.ROOT)
rootDiskTO = vol;
deviceConfigSpecArray[i].setDevice(device);
deviceConfigSpecArray[i].setOperation(VirtualDeviceConfigSpecOperation.ADD);
if (s_logger.isDebugEnabled())
s_logger.debug("Prepare volume at new device " + _gson.toJson(device));
i++;
} else {
if (controllerKey == scsiControllerKey && VmwareHelper.isReservedScsiDeviceNumber(scsiUnitNumber))
scsiUnitNumber++;
if (controllerKey == vmMo.getIDEControllerKey(ideUnitNumber))
ideUnitNumber++;
else
scsiUnitNumber++;
}
}
//
if (guestOsId.startsWith("darwin")) {
//Mac OS
VirtualDevice[] devices = vmMo.getMatchedDevices(new Class<?>[] { VirtualUSBController.class });
if (devices.length == 0) {
s_logger.debug("No USB Controller device on VM Start. Add USB Controller device for Mac OS VM " + vmInternalCSName);
//For Mac OS X systems, the EHCI+UHCI controller is enabled by default and is required for USB mouse and keyboard access.
VirtualDevice usbControllerDevice = VmwareHelper.prepareUSBControllerDevice();
deviceConfigSpecArray[i] = new VirtualDeviceConfigSpec();
deviceConfigSpecArray[i].setDevice(usbControllerDevice);
deviceConfigSpecArray[i].setOperation(VirtualDeviceConfigSpecOperation.ADD);
if (s_logger.isDebugEnabled())
s_logger.debug("Prepare USB controller at new device " + _gson.toJson(deviceConfigSpecArray[i]));
i++;
} else {
s_logger.debug("USB Controller device exists on VM Start for Mac OS VM " + vmInternalCSName);
}
}
//
// Setup NIC devices
//
VirtualDevice nic;
int nicMask = 0;
int nicCount = 0;
VirtualEthernetCardType nicDeviceType = VirtualEthernetCardType.valueOf(vmSpec.getDetails().get(VmDetailConstants.NIC_ADAPTER));
if (s_logger.isDebugEnabled())
s_logger.debug("VM " + vmInternalCSName + " will be started with NIC device type: " + nicDeviceType);
NiciraNvpApiVersion.logNiciraApiVersion();
Map<String, String> nicUuidToDvSwitchUuid = new HashMap<String, String>();
for (NicTO nicTo : sortNicsByDeviceId(nics)) {
s_logger.info("Prepare NIC device based on NicTO: " + _gson.toJson(nicTo));
boolean configureVServiceInNexus = (nicTo.getType() == TrafficType.Guest) && (vmSpec.getDetails().containsKey("ConfigureVServiceInNexus"));
VirtualMachine.Type vmType = cmd.getVirtualMachine().getType();
Pair<ManagedObjectReference, String> networkInfo = prepareNetworkFromNicInfo(vmMo.getRunningHost(), nicTo, configureVServiceInNexus, vmType);
if ((nicTo.getBroadcastType() != BroadcastDomainType.Lswitch) || (nicTo.getBroadcastType() == BroadcastDomainType.Lswitch && NiciraNvpApiVersion.isApiVersionLowerThan("4.2"))) {
if (VmwareHelper.isDvPortGroup(networkInfo.first())) {
String dvSwitchUuid;
ManagedObjectReference dcMor = hyperHost.getHyperHostDatacenter();
DatacenterMO dataCenterMo = new DatacenterMO(context, dcMor);
ManagedObjectReference dvsMor = dataCenterMo.getDvSwitchMor(networkInfo.first());
dvSwitchUuid = dataCenterMo.getDvSwitchUuid(dvsMor);
s_logger.info("Preparing NIC device on dvSwitch : " + dvSwitchUuid);
nic = VmwareHelper.prepareDvNicDevice(vmMo, networkInfo.first(), nicDeviceType, networkInfo.second(), dvSwitchUuid, nicTo.getMac(), nicUnitNumber++, i + 1, true, true);
if (nicTo.getUuid() != null) {
nicUuidToDvSwitchUuid.put(nicTo.getUuid(), dvSwitchUuid);
}
} else {
s_logger.info("Preparing NIC device on network " + networkInfo.second());
nic = VmwareHelper.prepareNicDevice(vmMo, networkInfo.first(), nicDeviceType, networkInfo.second(), nicTo.getMac(), nicUnitNumber++, i + 1, true, true);
}
} else {
//if NSX API VERSION >= 4.2, connect to br-int (nsx.network), do not create portgroup else previous behaviour
nic = VmwareHelper.prepareNicOpaque(vmMo, nicDeviceType, networkInfo.second(), nicTo.getMac(), nicUnitNumber++, i + 1, true, true);
}
deviceConfigSpecArray[i] = new VirtualDeviceConfigSpec();
deviceConfigSpecArray[i].setDevice(nic);
deviceConfigSpecArray[i].setOperation(VirtualDeviceConfigSpecOperation.ADD);
if (s_logger.isDebugEnabled())
s_logger.debug("Prepare NIC at new device " + _gson.toJson(deviceConfigSpecArray[i]));
// this is really a hacking for DomR, upon DomR startup, we will reset all the NIC allocation after eth3
if (nicCount < 3)
nicMask |= (1 << nicCount);
i++;
nicCount++;
}
for (int j = 0; j < i; j++) vmConfigSpec.getDeviceChange().add(deviceConfigSpecArray[j]);
//
// Setup VM options
//
// pass boot arguments through machine.id & perform customized options to VMX
ArrayList<OptionValue> extraOptions = new ArrayList<OptionValue>();
configBasicExtraOption(extraOptions, vmSpec);
configNvpExtraOption(extraOptions, vmSpec, nicUuidToDvSwitchUuid);
configCustomExtraOption(extraOptions, vmSpec);
// config VNC
String keyboardLayout = null;
if (vmSpec.getDetails() != null)
keyboardLayout = vmSpec.getDetails().get(VmDetailConstants.KEYBOARD);
vmConfigSpec.getExtraConfig().addAll(Arrays.asList(configureVnc(extraOptions.toArray(new OptionValue[0]), hyperHost, vmInternalCSName, vmSpec.getVncPassword(), keyboardLayout)));
// config video card
configureVideoCard(vmMo, vmSpec, vmConfigSpec);
//
if (!vmMo.configureVm(vmConfigSpec)) {
throw new Exception("Failed to configure VM before start. vmName: " + vmInternalCSName);
}
if (vmSpec.getType() == VirtualMachine.Type.DomainRouter) {
hyperHost.setRestartPriorityForVM(vmMo, DasVmPriority.HIGH.value());
}
//For resizing root disk.
if (rootDiskTO != null && !hasSnapshot) {
resizeRootDisk(vmMo, rootDiskTO, hyperHost, context);
}
//
// Post Configuration
//
vmMo.setCustomFieldValue(CustomFieldConstants.CLOUD_NIC_MASK, String.valueOf(nicMask));
postNvpConfigBeforeStart(vmMo, vmSpec);
Map<String, String> iqnToPath = new HashMap<String, String>();
postDiskConfigBeforeStart(vmMo, vmSpec, sortedDisks, ideControllerKey, scsiControllerKey, iqnToPath, hyperHost, context);
//
if (!vmMo.powerOn()) {
throw new Exception("Failed to start VM. vmName: " + vmInternalCSName + " with hostname " + vmNameOnVcenter);
}
StartAnswer startAnswer = new StartAnswer(cmd);
startAnswer.setIqnToPath(iqnToPath);
// Since VM was successfully powered-on, if there was an existing VM in a different cluster that was unregistered, delete all the files associated with it.
if (existingVmName != null && existingVmFileLayout != null) {
deleteUnregisteredVmFiles(existingVmFileLayout, dcMo, true);
}
return startAnswer;
} catch (Throwable e) {
if (e instanceof RemoteException) {
s_logger.warn("Encounter remote exception to vCenter, invalidate VMware session context");
invalidateServiceContext();
}
String msg = "StartCommand failed due to " + VmwareHelper.getExceptionMessage(e);
s_logger.warn(msg, e);
StartAnswer startAnswer = new StartAnswer(cmd, msg);
if (vmAlreadyExistsInVcenter) {
startAnswer.setContextParam("stopRetry", "true");
}
// Since VM start failed, if there was an existing VM in a different cluster that was unregistered, register it back.
if (existingVmName != null && existingVmFileInfo != null) {
s_logger.debug("Since VM start failed, registering back an existing VM: " + existingVmName + " that was unregistered");
try {
DatastoreFile fileInDatastore = new DatastoreFile(existingVmFileInfo.getVmPathName());
DatastoreMO existingVmDsMo = new DatastoreMO(dcMo.getContext(), dcMo.findDatastore(fileInDatastore.getDatastoreName()));
registerVm(existingVmName, existingVmDsMo);
} catch (Exception ex) {
String message = "Failed to register an existing VM: " + existingVmName + " due to " + VmwareHelper.getExceptionMessage(ex);
s_logger.warn(message, ex);
}
}
return startAnswer;
} finally {
}
}
use of com.cloud.agent.api.to.DataStoreTO in project cloudstack by apache.
the class VmwareResource method validateDisks.
private DiskTO[] validateDisks(DiskTO[] disks) {
List<DiskTO> validatedDisks = new ArrayList<DiskTO>();
for (DiskTO vol : disks) {
if (vol.getType() != Volume.Type.ISO) {
VolumeObjectTO volumeTO = (VolumeObjectTO) vol.getData();
DataStoreTO primaryStore = volumeTO.getDataStore();
if (primaryStore.getUuid() != null && !primaryStore.getUuid().isEmpty()) {
validatedDisks.add(vol);
}
} else if (vol.getType() == Volume.Type.ISO) {
TemplateObjectTO templateTO = (TemplateObjectTO) vol.getData();
if (templateTO.getPath() != null && !templateTO.getPath().isEmpty()) {
validatedDisks.add(vol);
}
} else {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Drop invalid disk option, volumeTO: " + _gson.toJson(vol));
}
}
}
return validatedDisks.toArray(new DiskTO[0]);
}
Aggregations