You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ed...@apache.org on 2013/05/10 18:49:19 UTC
[1/7] refactor kvm/vmware resource code
Updated Branches:
refs/heads/object_store a83b87b7e -> e444867e6
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/42e25a22/server/src/com/cloud/template/TemplateManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/template/TemplateManagerImpl.java b/server/src/com/cloud/template/TemplateManagerImpl.java
index 20cdce1..0bdd8c1 100755
--- a/server/src/com/cloud/template/TemplateManagerImpl.java
+++ b/server/src/com/cloud/template/TemplateManagerImpl.java
@@ -65,7 +65,9 @@ import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory;
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope;
import org.apache.cloudstack.framework.async.AsyncCallFuture;
+import org.apache.cloudstack.storage.command.AttachCommand;
import org.apache.cloudstack.storage.command.CommandResult;
+import org.apache.cloudstack.storage.command.DettachCommand;
import org.apache.cloudstack.storage.datastore.db.ImageStoreDao;
import org.apache.cloudstack.storage.datastore.db.ImageStoreVO;
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
@@ -79,8 +81,11 @@ import org.springframework.stereotype.Component;
import com.cloud.agent.AgentManager;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.AttachIsoCommand;
+import com.cloud.agent.api.Command;
import com.cloud.agent.api.ComputeChecksumCommand;
import com.cloud.agent.api.storage.DestroyCommand;
+import com.cloud.agent.api.to.DataTO;
+import com.cloud.agent.api.to.DiskTO;
import com.cloud.api.ApiDBUtils;
import com.cloud.async.AsyncJobManager;
import com.cloud.async.AsyncJobVO;
@@ -1024,27 +1029,13 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
} else if (vm.getState() != State.Running) {
return true;
}
- String isoPath;
- VMTemplateVO tmplt = this._tmpltDao.findById(isoId);
+ //FIXME: if it's s3, need to download into cache store
+ TemplateInfo tmplt = this._tmplFactory.getTemplate(isoId, DataStoreRole.Image, vm.getDataCenterId());
if (tmplt == null) {
s_logger.warn("ISO: " + isoId + " does not exist");
return false;
}
- // Get the path of the ISO
- Pair<String, String> isoPathPair = null;
- if (tmplt.getTemplateType() == TemplateType.PERHOST) {
- isoPath = tmplt.getName();
- } else {
- isoPathPair = getAbsoluteIsoPath(isoId,
- vm.getDataCenterId());
- if (isoPathPair == null) {
- s_logger.warn("Couldn't get absolute iso path");
- return false;
- } else {
- isoPath = isoPathPair.first();
- }
- }
-
+
String vmName = vm.getInstanceName();
HostVO host = _hostDao.findById(vm.getHostId());
@@ -1052,12 +1043,16 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
s_logger.warn("Host: " + vm.getHostId() + " does not exist");
return false;
}
- AttachIsoCommand cmd = new AttachIsoCommand(vmName, isoPath, attach);
- if (isoPathPair != null) {
- cmd.setStoreUrl(isoPathPair.second());
+
+ DataTO isoTO = tmplt.getTO();
+ DiskTO disk = new DiskTO(isoTO, null, Volume.Type.ISO);
+ Command cmd = null;
+ if (attach) {
+ cmd = new AttachCommand(disk, vmName);
+ } else {
+ cmd = new DettachCommand(disk, vmName);
}
Answer a = _agentMgr.easySend(vm.getHostId(), cmd);
-
return (a != null && a.getResult());
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/42e25a22/server/src/com/cloud/vm/UserVmManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java
index 000430f..98aeaf2 100755
--- a/server/src/com/cloud/vm/UserVmManagerImpl.java
+++ b/server/src/com/cloud/vm/UserVmManagerImpl.java
@@ -42,7 +42,10 @@ import org.apache.cloudstack.api.command.user.vmgroup.CreateVMGroupCmd;
import org.apache.cloudstack.api.command.user.vmgroup.DeleteVMGroupCmd;
import org.apache.cloudstack.engine.cloud.entity.api.VirtualMachineEntity;
import org.apache.cloudstack.engine.service.api.OrchestrationService;
+import org.apache.cloudstack.engine.subsystem.api.storage.TemplateDataFactory;
+import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo;
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
+import org.apache.cloudstack.storage.to.TemplateObjectTO;
import org.apache.commons.codec.binary.Base64;
import org.apache.log4j.Logger;
@@ -58,6 +61,7 @@ import com.cloud.agent.api.StopAnswer;
import com.cloud.agent.api.UnPlugNicAnswer;
import com.cloud.agent.api.UnPlugNicCommand;
import com.cloud.agent.api.VmStatsEntry;
+import com.cloud.agent.api.to.DiskTO;
import com.cloud.agent.api.to.NicTO;
import com.cloud.agent.api.to.VirtualMachineTO;
import com.cloud.agent.api.to.VolumeTO;
@@ -159,6 +163,7 @@ import com.cloud.storage.Storage;
import com.cloud.storage.Storage.ImageFormat;
import com.cloud.storage.Storage.StoragePoolType;
import com.cloud.storage.Storage.TemplateType;
+import com.cloud.storage.DataStoreRole;
import com.cloud.storage.StorageManager;
import com.cloud.storage.StoragePool;
import com.cloud.storage.StoragePoolStatus;
@@ -373,6 +378,8 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
@Inject
List<DeployPlannerSelector> plannerSelectors;
+ @Inject
+ TemplateDataFactory templateFactory;
protected ScheduledExecutorService _executor = null;
protected int _expungeInterval;
@@ -2625,52 +2632,33 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
vm.setDetails(details);
if (vm.getIsoId() != null) {
- String isoPath = null;
-
- VirtualMachineTemplate template = _templateDao.findById(vm
- .getIsoId());
+ TemplateInfo template = templateFactory.getTemplate(vm.getIsoId(), DataStoreRole.Image, vm.getDataCenterId());
+
if (template == null || template.getFormat() != ImageFormat.ISO) {
throw new CloudRuntimeException(
"Can not find ISO in vm_template table for id "
+ vm.getIsoId());
}
-
- Pair<String, String> isoPathPair = this.templateMgr.getAbsoluteIsoPath(
- template.getId(), vm.getDataCenterId());
-
- if (template.getTemplateType() == TemplateType.PERHOST) {
- isoPath = template.getName();
- } else {
- if (isoPathPair == null) {
- s_logger.warn("Couldn't get absolute iso path");
- return false;
- } else {
- isoPath = isoPathPair.first();
- }
- }
-
+
if (template.isBootable()) {
profile.setBootLoaderType(BootloaderType.CD);
}
+
GuestOSVO guestOS = _guestOSDao.findById(template.getGuestOSId());
String displayName = null;
if (guestOS != null) {
displayName = guestOS.getDisplayName();
}
- VolumeTO iso = new VolumeTO(profile.getId(), Volume.Type.ISO,
- StoragePoolType.ISO, null, template.getName(), null,
- isoPath, 0, null, displayName);
-
- iso.setDeviceId(3);
- profile.addDisk(iso);
+
+ TemplateObjectTO iso = (TemplateObjectTO)template.getTO();
+ iso.setGuestOsType(displayName);
+ DiskTO disk = new DiskTO(iso, 3L, Volume.Type.ISO);
+ profile.addDisk(disk);
} else {
- VirtualMachineTemplate template = profile.getTemplate();
- /* create a iso placeholder */
- VolumeTO iso = new VolumeTO(profile.getId(), Volume.Type.ISO,
- StoragePoolType.ISO, null, template.getName(), null, null,
- 0, null);
- iso.setDeviceId(3);
- profile.addDisk(iso);
+ TemplateObjectTO iso = new TemplateObjectTO();
+ iso.setFormat(ImageFormat.ISO);
+ DiskTO disk = new DiskTO(iso, 3L, Volume.Type.ISO);
+ profile.addDisk(disk);
}
return true;
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/42e25a22/server/src/com/cloud/vm/VirtualMachineProfileImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/vm/VirtualMachineProfileImpl.java b/server/src/com/cloud/vm/VirtualMachineProfileImpl.java
index 24f44cb..c4e8822 100644
--- a/server/src/com/cloud/vm/VirtualMachineProfileImpl.java
+++ b/server/src/com/cloud/vm/VirtualMachineProfileImpl.java
@@ -22,6 +22,7 @@ import java.util.List;
import java.util.Map;
+import com.cloud.agent.api.to.DiskTO;
import com.cloud.agent.api.to.VolumeTO;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.offering.ServiceOffering;
@@ -46,7 +47,7 @@ public class VirtualMachineProfileImpl<T extends VMInstanceVO> implements Virtua
UserVmDetailVO _userVmDetails;
Map<Param, Object> _params;
List<NicProfile> _nics = new ArrayList<NicProfile>();
- List<VolumeTO> _disks = new ArrayList<VolumeTO>();
+ List<DiskTO> _disks = new ArrayList<DiskTO>();
StringBuilder _bootArgs = new StringBuilder();
Account _owner;
BootloaderType _bootloader;
@@ -141,7 +142,7 @@ public class VirtualMachineProfileImpl<T extends VMInstanceVO> implements Virtua
_nics = nics;
}
- public void setDisks(List<VolumeTO> disks) {
+ public void setDisks(List<DiskTO> disks) {
_disks = disks;
}
@@ -151,7 +152,7 @@ public class VirtualMachineProfileImpl<T extends VMInstanceVO> implements Virtua
}
@Override
- public List<VolumeTO> getDisks() {
+ public List<DiskTO> getDisks() {
return _disks;
}
@@ -161,7 +162,7 @@ public class VirtualMachineProfileImpl<T extends VMInstanceVO> implements Virtua
}
@Override
- public void addDisk(int index, VolumeTO disk) {
+ public void addDisk(int index, DiskTO disk) {
_disks.add(index, disk);
}
@@ -210,7 +211,7 @@ public class VirtualMachineProfileImpl<T extends VMInstanceVO> implements Virtua
}
@Override
- public void addDisk(VolumeTO disk) {
+ public void addDisk(DiskTO disk) {
_disks.add(disk);
}
[4/7] refactor kvm/vmware resource code
Posted by ed...@apache.org.
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/42e25a22/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageProcessor.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageProcessor.java b/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageProcessor.java
new file mode 100644
index 0000000..988658d
--- /dev/null
+++ b/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareStorageProcessor.java
@@ -0,0 +1,1144 @@
+package com.cloud.storage.resource;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.OutputStreamWriter;
+import java.net.URI;
+import java.rmi.RemoteException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import org.apache.cloudstack.storage.command.AttachAnswer;
+import org.apache.cloudstack.storage.command.AttachCommand;
+import org.apache.cloudstack.storage.command.CopyCmdAnswer;
+import org.apache.cloudstack.storage.command.CopyCommand;
+import org.apache.cloudstack.storage.command.CreateObjectAnswer;
+import org.apache.cloudstack.storage.command.CreateObjectCommand;
+import org.apache.cloudstack.storage.command.DeleteCommand;
+import org.apache.cloudstack.storage.command.DettachCommand;
+import org.apache.cloudstack.storage.to.PrimaryDataStoreTO;
+import org.apache.cloudstack.storage.to.SnapshotObjectTO;
+import org.apache.cloudstack.storage.to.TemplateObjectTO;
+import org.apache.cloudstack.storage.to.VolumeObjectTO;
+import org.apache.log4j.Logger;
+
+import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.BackupSnapshotAnswer;
+import com.cloud.agent.api.Command;
+import com.cloud.agent.api.ManageSnapshotAnswer;
+import com.cloud.agent.api.ManageSnapshotCommand;
+import com.cloud.agent.api.storage.CreatePrivateTemplateAnswer;
+import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer;
+import com.cloud.agent.api.to.DataStoreTO;
+import com.cloud.agent.api.to.DataTO;
+import com.cloud.agent.api.to.DiskTO;
+import com.cloud.agent.api.to.NfsTO;
+import com.cloud.agent.api.to.VolumeTO;
+import com.cloud.hypervisor.vmware.manager.VmwareHostService;
+import com.cloud.hypervisor.vmware.manager.VmwareStorageMount;
+import com.cloud.hypervisor.vmware.mo.ClusterMO;
+import com.cloud.hypervisor.vmware.mo.CustomFieldConstants;
+import com.cloud.hypervisor.vmware.mo.DatacenterMO;
+import com.cloud.hypervisor.vmware.mo.DatastoreMO;
+import com.cloud.hypervisor.vmware.mo.HostMO;
+import com.cloud.hypervisor.vmware.mo.HypervisorHostHelper;
+import com.cloud.hypervisor.vmware.mo.NetworkDetails;
+import com.cloud.hypervisor.vmware.mo.VirtualMachineMO;
+import com.cloud.hypervisor.vmware.mo.VmwareHypervisorHost;
+import com.cloud.hypervisor.vmware.resource.VmwareResource;
+import com.cloud.hypervisor.vmware.util.VmwareContext;
+import com.cloud.hypervisor.vmware.util.VmwareHelper;
+import com.cloud.serializer.GsonHelper;
+import com.cloud.storage.JavaStorageLayer;
+import com.cloud.storage.StorageLayer;
+import com.cloud.storage.Volume;
+import com.cloud.storage.Storage.ImageFormat;
+import com.cloud.storage.template.VmdkProcessor;
+import com.cloud.utils.Pair;
+import com.cloud.utils.StringUtils;
+import com.cloud.utils.Ternary;
+import com.cloud.utils.script.Script;
+import com.cloud.vm.VirtualMachine.State;
+import com.google.gson.Gson;
+import com.vmware.vim25.ManagedObjectReference;
+import com.vmware.vim25.VirtualDeviceConfigSpec;
+import com.vmware.vim25.VirtualDeviceConfigSpecOperation;
+import com.vmware.vim25.VirtualDisk;
+import com.vmware.vim25.VirtualEthernetCard;
+import com.vmware.vim25.VirtualLsiLogicController;
+import com.vmware.vim25.VirtualMachineConfigSpec;
+import com.vmware.vim25.VirtualMachineFileInfo;
+import com.vmware.vim25.VirtualMachineGuestOsIdentifier;
+import com.vmware.vim25.VirtualSCSISharing;
+
+public class VmwareStorageProcessor implements StorageProcessor {
+ private static final Logger s_logger = Logger.getLogger(VmwareStorageProcessor.class);
+ private VmwareHostService hostService;
+ private boolean _fullCloneFlag;
+ private VmwareStorageMount mountService;
+ private VmwareResource resource;
+ private Integer _timeout;
+ protected Integer _shutdown_waitMs;
+ private final Gson _gson;
+ private final StorageLayer _storage = new JavaStorageLayer();
+ public VmwareStorageProcessor(VmwareHostService hostService, boolean fullCloneFlag, VmwareStorageMount mountService,
+ Integer timeout,
+ VmwareResource resource,
+ Integer shutdownWaitMs) {
+ this.hostService = hostService;
+ this._fullCloneFlag = fullCloneFlag;
+ this.mountService = mountService;
+ this._timeout = timeout;
+ this.resource = resource;
+ this._shutdown_waitMs = shutdownWaitMs;
+ _gson = GsonHelper.getGsonLogger();
+ }
+
+ private String getOVFFilePath(String srcOVAFileName) {
+ File file = new File(srcOVAFileName);
+ assert(_storage != null);
+ String[] files = _storage.listFiles(file.getParent());
+ if(files != null) {
+ for(String fileName : files) {
+ if(fileName.toLowerCase().endsWith(".ovf")) {
+ File ovfFile = new File(fileName);
+ return file.getParent() + File.separator + ovfFile.getName();
+ }
+ }
+ }
+ return null;
+ }
+ private void copyTemplateFromSecondaryToPrimary(VmwareHypervisorHost hyperHost, DatastoreMO datastoreMo, String secondaryStorageUrl,
+ String templatePathAtSecondaryStorage, String templateName, String templateUuid) throws Exception {
+
+ s_logger.info("Executing copyTemplateFromSecondaryToPrimary. secondaryStorage: "
+ + secondaryStorageUrl + ", templatePathAtSecondaryStorage: " + templatePathAtSecondaryStorage
+ + ", templateName: " + templateName);
+
+ String secondaryMountPoint = mountService.getMountPoint(secondaryStorageUrl);
+ s_logger.info("Secondary storage mount point: " + secondaryMountPoint);
+
+ String srcOVAFileName = secondaryMountPoint + "/" + templatePathAtSecondaryStorage +
+ templateName + "." + ImageFormat.OVA.getFileExtension();
+
+ String srcFileName = getOVFFilePath(srcOVAFileName);
+ if(srcFileName == null) {
+ Script command = new Script("tar", 0, s_logger);
+ command.add("--no-same-owner");
+ command.add("-xf", srcOVAFileName);
+ command.setWorkDir(secondaryMountPoint + "/" + templatePathAtSecondaryStorage);
+ s_logger.info("Executing command: " + command.toString());
+ String result = command.execute();
+ if(result != null) {
+ String msg = "Unable to unpack snapshot OVA file at: " + srcOVAFileName;
+ s_logger.error(msg);
+ throw new Exception(msg);
+ }
+ }
+
+ srcFileName = getOVFFilePath(srcOVAFileName);
+ if(srcFileName == null) {
+ String msg = "Unable to locate OVF file in template package directory: " + srcOVAFileName;
+ s_logger.error(msg);
+ throw new Exception(msg);
+ }
+
+ String vmName = templateUuid;
+ hyperHost.importVmFromOVF(srcFileName, vmName, datastoreMo, "thin");
+
+ VirtualMachineMO vmMo = hyperHost.findVmOnHyperHost(vmName);
+ if(vmMo == null) {
+ String msg = "Failed to import OVA template. secondaryStorage: "
+ + secondaryStorageUrl + ", templatePathAtSecondaryStorage: " + templatePathAtSecondaryStorage
+ + ", templateName: " + templateName + ", templateUuid: " + templateUuid;
+ s_logger.error(msg);
+ throw new Exception(msg);
+ }
+
+ if(vmMo.createSnapshot("cloud.template.base", "Base snapshot", false, false)) {
+ vmMo.setCustomFieldValue(CustomFieldConstants.CLOUD_UUID, templateUuid);
+ vmMo.markAsTemplate();
+ } else {
+ vmMo.destroy();
+ String msg = "Unable to create base snapshot for template, templateName: " + templateName + ", templateUuid: " + templateUuid;
+ s_logger.error(msg);
+ throw new Exception(msg);
+ }
+ }
+
+ @Override
+ public Answer copyTemplateToPrimaryStorage(CopyCommand cmd) {
+ DataTO srcData = cmd.getSrcTO();
+ TemplateObjectTO template = (TemplateObjectTO)srcData;
+ DataStoreTO srcStore = srcData.getDataStore();
+ if (!(srcStore instanceof NfsTO)) {
+ return new CopyCmdAnswer("unsupported protocol");
+ }
+ NfsTO nfsImageStore = (NfsTO)srcStore;
+ DataTO destData = cmd.getDestTO();
+ DataStoreTO destStore = destData.getDataStore();
+ PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)destStore;
+ String secondaryStorageUrl = nfsImageStore.getUrl();
+ assert (secondaryStorageUrl != null);
+
+ String templateUrl = secondaryStorageUrl + File.separator + srcData.getPath();
+
+ String templateName = null;
+ String mountPoint = null;
+ if (templateUrl.endsWith(".ova")) {
+ int index = templateUrl.lastIndexOf("/");
+ mountPoint = templateUrl.substring(0, index);
+ mountPoint = mountPoint.substring(secondaryStorageUrl.length() + 1);
+ if (!mountPoint.endsWith("/")) {
+ mountPoint = mountPoint + "/";
+ }
+
+ templateName = templateUrl.substring(index + 1).replace("." + ImageFormat.OVA.getFileExtension(), "");
+
+ if (templateName == null || templateName.isEmpty()) {
+ templateName = template.getName();
+ }
+ } else {
+ mountPoint = templateUrl.substring(secondaryStorageUrl.length() + 1);
+ if (!mountPoint.endsWith("/")) {
+ mountPoint = mountPoint + "/";
+ }
+ templateName = template.getName();
+ }
+
+ VmwareContext context = hostService.getServiceContext(cmd);
+ try {
+ VmwareHypervisorHost hyperHost = hostService.getHyperHost(context, cmd);
+
+ String templateUuidName = UUID.nameUUIDFromBytes((templateName + "@" + primaryStore.getUuid() + "-" + hyperHost.getMor().getValue()).getBytes()).toString();
+ // truncate template name to 32 chars to ensure they work well with vSphere API's.
+ templateUuidName = templateUuidName.replace("-", "");
+
+ DatacenterMO dcMo = new DatacenterMO(context, hyperHost.getHyperHostDatacenter());
+ VirtualMachineMO templateMo = VmwareHelper.pickOneVmOnRunningHost(dcMo.findVmByNameAndLabel(templateUuidName), true);
+
+ if (templateMo == null) {
+ if(s_logger.isInfoEnabled())
+ s_logger.info("Template " + templateName + " is not setup yet, setup template from secondary storage with uuid name: " + templateUuidName);
+ ManagedObjectReference morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, primaryStore.getUuid());
+ assert (morDs != null);
+ DatastoreMO primaryStorageDatastoreMo = new DatastoreMO(context, morDs);
+
+ copyTemplateFromSecondaryToPrimary(hyperHost,
+ primaryStorageDatastoreMo, secondaryStorageUrl,
+ mountPoint, templateName, templateUuidName);
+ } else {
+ s_logger.info("Template " + templateName + " has already been setup, skip the template setup process in primary storage");
+ }
+
+ TemplateObjectTO newTemplate = new TemplateObjectTO();
+ newTemplate.setPath(templateUuidName);
+ return new CopyCmdAnswer(newTemplate);
+ } catch (Throwable e) {
+ if (e instanceof RemoteException) {
+ hostService.invalidateServiceContext(context);
+ }
+
+ String msg = "Unable to execute PrimaryStorageDownloadCommand due to exception";
+ s_logger.error(msg, e);
+ return new CopyCmdAnswer(msg);
+ }
+ }
+ private boolean createVMLinkedClone(VirtualMachineMO vmTemplate, DatacenterMO dcMo, DatastoreMO dsMo,
+ String vmdkName, ManagedObjectReference morDatastore, ManagedObjectReference morPool) throws Exception {
+
+ ManagedObjectReference morBaseSnapshot = vmTemplate.getSnapshotMor("cloud.template.base");
+ if (morBaseSnapshot == null) {
+ String msg = "Unable to find template base snapshot, invalid template";
+ s_logger.error(msg);
+ throw new Exception(msg);
+ }
+
+ if(dsMo.folderExists(String.format("[%s]", dsMo.getName()), vmdkName))
+ dsMo.deleteFile(String.format("[%s] %s/", dsMo.getName(), vmdkName), dcMo.getMor(), false);
+
+ s_logger.info("creating linked clone from template");
+ if (!vmTemplate.createLinkedClone(vmdkName, morBaseSnapshot, dcMo.getVmFolder(), morPool, morDatastore)) {
+ String msg = "Unable to clone from the template";
+ s_logger.error(msg);
+ throw new Exception(msg);
+ }
+
+ // we can't rely on un-offical API (VirtualMachineMO.moveAllVmDiskFiles() any more, use hard-coded disk names that we know
+ // to move files
+ s_logger.info("Move volume out of volume-wrapper VM ");
+ dsMo.moveDatastoreFile(String.format("[%s] %s/%s.vmdk", dsMo.getName(), vmdkName, vmdkName),
+ dcMo.getMor(), dsMo.getMor(),
+ String.format("[%s] %s.vmdk", dsMo.getName(), vmdkName), dcMo.getMor(), true);
+
+ dsMo.moveDatastoreFile(String.format("[%s] %s/%s-delta.vmdk", dsMo.getName(), vmdkName, vmdkName),
+ dcMo.getMor(), dsMo.getMor(),
+ String.format("[%s] %s-delta.vmdk", dsMo.getName(), vmdkName), dcMo.getMor(), true);
+
+ return true;
+ }
+
+ private boolean createVMFullClone(VirtualMachineMO vmTemplate, DatacenterMO dcMo, DatastoreMO dsMo,
+ String vmdkName, ManagedObjectReference morDatastore, ManagedObjectReference morPool) throws Exception {
+
+ if(dsMo.folderExists(String.format("[%s]", dsMo.getName()), vmdkName))
+ dsMo.deleteFile(String.format("[%s] %s/", dsMo.getName(), vmdkName), dcMo.getMor(), false);
+
+ s_logger.info("creating full clone from template");
+ if (!vmTemplate.createFullClone(vmdkName, dcMo.getVmFolder(), morPool, morDatastore)) {
+ String msg = "Unable to create full clone from the template";
+ s_logger.error(msg);
+ throw new Exception(msg);
+ }
+
+ // we can't rely on un-offical API (VirtualMachineMO.moveAllVmDiskFiles() any more, use hard-coded disk names that we know
+ // to move files
+ s_logger.info("Move volume out of volume-wrapper VM ");
+ dsMo.moveDatastoreFile(String.format("[%s] %s/%s.vmdk", dsMo.getName(), vmdkName, vmdkName),
+ dcMo.getMor(), dsMo.getMor(),
+ String.format("[%s] %s.vmdk", dsMo.getName(), vmdkName), dcMo.getMor(), true);
+
+ dsMo.moveDatastoreFile(String.format("[%s] %s/%s-flat.vmdk", dsMo.getName(), vmdkName, vmdkName),
+ dcMo.getMor(), dsMo.getMor(),
+ String.format("[%s] %s-flat.vmdk", dsMo.getName(), vmdkName), dcMo.getMor(), true);
+
+ return true;
+ }
+
+ @Override
+ public Answer cloneVolumeFromBaseTemplate(CopyCommand cmd) {
+ DataTO srcData = cmd.getSrcTO();
+ TemplateObjectTO template = (TemplateObjectTO)srcData;
+ DataStoreTO imageStore = template.getDataStore();
+ DataTO destData = cmd.getDestTO();
+ VolumeObjectTO volume = (VolumeObjectTO)destData;
+ PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)volume.getDataStore();
+ if (imageStore != null && !(imageStore instanceof NfsTO)) {
+ return new CopyCmdAnswer("unsupported protocol");
+ }
+ NfsTO nfsImageStore = (NfsTO)imageStore;
+
+ try {
+ VmwareContext context = this.hostService.getServiceContext(null);
+ VmwareHypervisorHost hyperHost = this.hostService.getHyperHost(context, null);
+ DatacenterMO dcMo = new DatacenterMO(context, hyperHost.getHyperHostDatacenter());
+ VirtualMachineMO vmMo = null;
+ 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);
+
+
+ // attach volume id to make the name unique
+ String vmdkName = volume.getName() + "-" + volume.getId();
+ if (nfsImageStore == null) {
+ // create a root volume for blank VM
+ String dummyVmName = this.hostService.getWorkerName(context, cmd, 0);
+
+ try {
+ vmMo = prepareVolumeHostDummyVm(hyperHost, dsMo, dummyVmName);
+ if (vmMo == null) {
+ throw new Exception("Unable to create a dummy VM for volume creation");
+ }
+
+ String volumeDatastorePath = String.format("[%s] %s.vmdk", dsMo.getName(), vmdkName);
+ synchronized (this) {
+ s_logger.info("Delete file if exists in datastore to clear the way for creating the volume. file: " + volumeDatastorePath);
+ VmwareHelper.deleteVolumeVmdkFiles(dsMo, vmdkName, dcMo);
+ vmMo.createDisk(volumeDatastorePath, (int) (volume.getSize() / (1024L * 1024L)), morDatastore, -1);
+ vmMo.detachDisk(volumeDatastorePath, false);
+ }
+
+ VolumeObjectTO newVol = new VolumeObjectTO();
+ newVol.setPath(vmdkName);
+ return new CopyCmdAnswer(newVol);
+ } finally {
+ vmMo.detachAllDisks();
+
+ s_logger.info("Destroy dummy VM after volume creation");
+ vmMo.destroy();
+ }
+ } else {
+ String templateUrl = nfsImageStore.getUrl() + File.separator + template.getPath();
+ VirtualMachineMO vmTemplate = VmwareHelper.pickOneVmOnRunningHost(dcMo.findVmByNameAndLabel(templateUrl), true);
+ if (vmTemplate == null) {
+ s_logger.warn("Template host in vSphere is not in connected state, request template reload");
+ return new CopyCmdAnswer("Template host in vSphere is not in connected state, request template reload");
+ }
+
+ ManagedObjectReference morPool = hyperHost.getHyperHostOwnerResourcePool();
+ ManagedObjectReference morCluster = hyperHost.getHyperHostCluster();
+ //createVMLinkedClone(vmTemplate, dcMo, dsMo, vmdkName, morDatastore, morPool);
+ if (!_fullCloneFlag) {
+ createVMLinkedClone(vmTemplate, dcMo, dsMo, vmdkName, morDatastore, morPool);
+ } else {
+ createVMFullClone(vmTemplate, dcMo, dsMo, vmdkName, morDatastore, morPool);
+ }
+
+ vmMo = new ClusterMO(context, morCluster).findVmOnHyperHost(vmdkName);
+ assert (vmMo != null);
+
+ s_logger.info("detach disks from volume-wrapper VM " + vmdkName);
+ vmMo.detachAllDisks();
+
+ s_logger.info("destroy volume-wrapper VM " + vmdkName);
+ vmMo.destroy();
+
+ String srcFile = String.format("[%s] %s/", dsMo.getName(), vmdkName);
+ dsMo.deleteFile(srcFile, dcMo.getMor(), true);
+ VolumeObjectTO newVol = new VolumeObjectTO();
+ newVol.setPath(vmdkName);
+ return new CopyCmdAnswer(newVol);
+ }
+ } catch (Throwable e) {
+ if (e instanceof RemoteException) {
+ s_logger.warn("Encounter remote exception to vCenter, invalidate VMware session context");
+ this.hostService.invalidateServiceContext(null);
+ }
+
+ String msg = "CreateCommand failed due to " + VmwareHelper.getExceptionMessage(e);
+ s_logger.error(msg, e);
+ return new CopyCmdAnswer(e.toString());
+ }
+ }
+
+
+ @Override
+ public Answer copyVolumeFromImageCacheToPrimary(CopyCommand cmd) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Answer copyVolumeFromPrimaryToSecondary(CopyCommand cmd) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ private void postCreatePrivateTemplate(String installFullPath, long templateId,
+ String templateName, long size, long virtualSize) throws Exception {
+
+ // TODO a bit ugly here
+ BufferedWriter out = null;
+ try {
+ out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(installFullPath + "/template.properties")));
+ out.write("filename=" + templateName + ".ova");
+ out.newLine();
+ out.write("description=");
+ out.newLine();
+ out.write("checksum=");
+ out.newLine();
+ out.write("hvm=false");
+ out.newLine();
+ out.write("size=" + size);
+ out.newLine();
+ out.write("ova=true");
+ out.newLine();
+ out.write("id=" + templateId);
+ out.newLine();
+ out.write("public=false");
+ out.newLine();
+ out.write("ova.filename=" + templateName + ".ova");
+ out.newLine();
+ out.write("uniquename=" + templateName);
+ out.newLine();
+ out.write("ova.virtualsize=" + virtualSize);
+ out.newLine();
+ out.write("virtualsize=" + virtualSize);
+ out.newLine();
+ out.write("ova.size=" + size);
+ out.newLine();
+ } finally {
+ if(out != null)
+ out.close();
+ }
+ }
+
+ private Ternary<String, Long, Long> createTemplateFromVolume(VirtualMachineMO vmMo, String installPath, long templateId, String templateUniqueName,
+ String secStorageUrl, String volumePath, String workerVmName) throws Exception {
+
+ String secondaryMountPoint = mountService.getMountPoint(secStorageUrl);
+ String installFullPath = secondaryMountPoint + "/" + installPath;
+ synchronized(installPath.intern()) {
+ Script command = new Script(false, "mkdir", _timeout, s_logger);
+ command.add("-p");
+ command.add(installFullPath);
+
+ String result = command.execute();
+ if(result != null) {
+ String msg = "unable to prepare template directory: "
+ + installPath + ", storage: " + secStorageUrl + ", error msg: " + result;
+ s_logger.error(msg);
+ throw new Exception(msg);
+ }
+ }
+
+ VirtualMachineMO clonedVm = null;
+ try {
+ Pair<VirtualDisk, String> volumeDeviceInfo = vmMo.getDiskDevice(volumePath, false);
+ if(volumeDeviceInfo == null) {
+ String msg = "Unable to find related disk device for volume. volume path: " + volumePath;
+ s_logger.error(msg);
+ throw new Exception(msg);
+ }
+
+ if(!vmMo.createSnapshot(templateUniqueName, "Temporary snapshot for template creation", false, false)) {
+ String msg = "Unable to take snapshot for creating template from volume. volume path: " + volumePath;
+ s_logger.error(msg);
+ throw new Exception(msg);
+ }
+
+ // 4 MB is the minimum requirement for VM memory in VMware
+ vmMo.cloneFromCurrentSnapshot(workerVmName, 0, 4, volumeDeviceInfo.second(),
+ VmwareHelper.getDiskDeviceDatastore(volumeDeviceInfo.first()));
+ clonedVm = vmMo.getRunningHost().findVmOnHyperHost(workerVmName);
+ if(clonedVm == null) {
+ String msg = "Unable to create dummy VM to export volume. volume path: " + volumePath;
+ s_logger.error(msg);
+ throw new Exception(msg);
+ }
+
+ clonedVm.exportVm(secondaryMountPoint + "/" + installPath, templateUniqueName, true, false);
+
+ long physicalSize = new File(installFullPath + "/" + templateUniqueName + ".ova").length();
+ VmdkProcessor processor = new VmdkProcessor();
+ Map<String, Object> params = new HashMap<String, Object>();
+ params.put(StorageLayer.InstanceConfigKey, _storage);
+ processor.configure("VMDK Processor", params);
+ long virtualSize = processor.getTemplateVirtualSize(installFullPath, templateUniqueName);
+
+ postCreatePrivateTemplate(installFullPath, templateId, templateUniqueName, physicalSize, virtualSize);
+ return new Ternary<String, Long, Long>(installPath + "/" + templateUniqueName + ".ova", physicalSize, virtualSize);
+
+ } finally {
+ if(clonedVm != null) {
+ clonedVm.detachAllDisks();
+ clonedVm.destroy();
+ }
+
+ vmMo.removeSnapshot(templateUniqueName, false);
+ }
+ }
+
+ @Override
+ public Answer createTemplateFromVolume(CopyCommand cmd) {
+ VolumeObjectTO volume = (VolumeObjectTO)cmd.getSrcTO();
+ PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)volume.getDataStore();
+ TemplateObjectTO template = (TemplateObjectTO)cmd.getDestTO();
+ DataStoreTO imageStore = template.getDataStore();
+
+ if (!(imageStore instanceof NfsTO)) {
+ return new CopyCmdAnswer("unsupported protocol");
+ }
+ NfsTO nfsImageStore = (NfsTO)imageStore;
+ String secondaryStoragePoolURL = nfsImageStore.getUrl();
+ String volumePath = volume.getPath();
+
+ String details = null;
+
+ VmwareContext context = hostService.getServiceContext(cmd);
+ try {
+ VmwareHypervisorHost hyperHost = hostService.getHyperHost(context, cmd);
+
+ VirtualMachineMO vmMo = hyperHost.findVmOnHyperHost(volume.getVmName());
+ if (vmMo == null) {
+ if(s_logger.isDebugEnabled())
+ s_logger.debug("Unable to find the owner VM for CreatePrivateTemplateFromVolumeCommand on host " + hyperHost.getHyperHostName() + ", try within datacenter");
+ vmMo = hyperHost.findVmOnPeerHyperHost(volume.getVmName());
+
+ if(vmMo == null) {
+ String msg = "Unable to find the owner VM for volume operation. vm: " + volume.getVmName();
+ s_logger.error(msg);
+ throw new Exception(msg);
+ }
+ }
+
+ Ternary<String, Long, Long> result = createTemplateFromVolume(vmMo,
+ template.getPath(), template.getId(), template.getName(),
+ secondaryStoragePoolURL, volumePath,
+ hostService.getWorkerName(context, cmd, 0));
+
+ TemplateObjectTO newTemplate = new TemplateObjectTO();
+ newTemplate.setPath(template.getName());
+ newTemplate.setFormat(ImageFormat.OVA);
+ return new CopyCmdAnswer(newTemplate);
+
+ } catch (Throwable e) {
+ if (e instanceof RemoteException) {
+ hostService.invalidateServiceContext(context);
+ }
+
+ s_logger.error("Unexpecpted exception ", e);
+
+ details = "CreatePrivateTemplateFromVolumeCommand exception: " + StringUtils.getExceptionStackInfo(e);
+ return new CopyCmdAnswer(details);
+ }
+ }
+
+ private void exportVolumeToSecondaryStroage(VirtualMachineMO vmMo, String volumePath,
+ String secStorageUrl, String secStorageDir, String exportName,
+ String workerVmName) throws Exception {
+
+ String secondaryMountPoint = mountService.getMountPoint(secStorageUrl);
+ String exportPath = secondaryMountPoint + "/" + secStorageDir + "/" + exportName;
+
+ synchronized(exportPath.intern()) {
+ if(!new File(exportPath).exists()) {
+ Script command = new Script(false, "mkdir", _timeout, s_logger);
+ command.add("-p");
+ command.add(exportPath);
+ if(command.execute() != null)
+ throw new Exception("unable to prepare snapshot backup directory");
+ }
+ }
+
+ VirtualMachineMO clonedVm = null;
+ try {
+
+ Pair<VirtualDisk, String> volumeDeviceInfo = vmMo.getDiskDevice(volumePath, false);
+ if(volumeDeviceInfo == null) {
+ String msg = "Unable to find related disk device for volume. volume path: " + volumePath;
+ s_logger.error(msg);
+ throw new Exception(msg);
+ }
+
+ // 4 MB is the minimum requirement for VM memory in VMware
+ vmMo.cloneFromCurrentSnapshot(workerVmName, 0, 4, volumeDeviceInfo.second(),
+ VmwareHelper.getDiskDeviceDatastore(volumeDeviceInfo.first()));
+ clonedVm = vmMo.getRunningHost().findVmOnHyperHost(workerVmName);
+ if(clonedVm == null) {
+ String msg = "Unable to create dummy VM to export volume. volume path: " + volumePath;
+ s_logger.error(msg);
+ throw new Exception(msg);
+ }
+
+ clonedVm.exportVm(exportPath, exportName, true, true);
+ } finally {
+ if(clonedVm != null) {
+ clonedVm.detachAllDisks();
+ clonedVm.destroy();
+ }
+ }
+ }
+
+
+ private String backupSnapshotToSecondaryStorage(VirtualMachineMO vmMo, String installPath,
+ String volumePath, String snapshotUuid, String secStorageUrl,
+ String prevSnapshotUuid, String prevBackupUuid, String workerVmName) throws Exception {
+
+ String backupUuid = UUID.randomUUID().toString();
+ exportVolumeToSecondaryStroage(vmMo, volumePath, secStorageUrl,
+ installPath, backupUuid, workerVmName);
+ return backupUuid + "/" + backupUuid;
+ }
+ @Override
+ public Answer backupSnasphot(CopyCommand cmd) {
+ SnapshotObjectTO srcSnapshot = (SnapshotObjectTO)cmd.getSrcTO();
+ PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)srcSnapshot.getDataStore();
+ SnapshotObjectTO destSnapshot = (SnapshotObjectTO)cmd.getDestTO();
+ DataStoreTO destStore = destSnapshot.getDataStore();
+ if (!(destStore instanceof NfsTO)) {
+ return new CopyCmdAnswer("unsupported protocol");
+ }
+
+ NfsTO destNfsStore = (NfsTO)destStore;
+
+
+ String secondaryStorageUrl = destNfsStore.getUrl();
+ String snapshotUuid = srcSnapshot.getPath();
+ String prevSnapshotUuid = srcSnapshot.getParentSnapshotPath();
+ String prevBackupUuid = destSnapshot.getParentSnapshotPath();
+ VirtualMachineMO workerVm=null;
+ String workerVMName = null;
+ String volumePath = srcSnapshot.getVolume().getPath();
+ ManagedObjectReference morDs = null;
+ DatastoreMO dsMo=null;
+
+ // By default assume failure
+ String details = null;
+ boolean success = false;
+ String snapshotBackupUuid = null;
+
+ VmwareContext context = hostService.getServiceContext(cmd);
+ VirtualMachineMO vmMo = null;
+ String vmName = srcSnapshot.getVmName();
+ try {
+ VmwareHypervisorHost hyperHost = hostService.getHyperHost(context, cmd);
+ morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, primaryStore.getUuid());
+
+ try {
+ vmMo = hyperHost.findVmOnHyperHost(vmName);
+ if (vmMo == null) {
+ if(s_logger.isDebugEnabled())
+ s_logger.debug("Unable to find owner VM for BackupSnapshotCommand on host " + hyperHost.getHyperHostName() + ", will try within datacenter");
+
+ vmMo = hyperHost.findVmOnPeerHyperHost(vmName);
+ if(vmMo == null) {
+ dsMo = new DatastoreMO(hyperHost.getContext(), morDs);
+
+ workerVMName = hostService.getWorkerName(context, cmd, 0);
+
+ // attach a volume to dummay wrapper VM for taking snapshot and exporting the VM for backup
+ if (!hyperHost.createBlankVm(workerVMName, 1, 512, 0, false, 4, 0, VirtualMachineGuestOsIdentifier.OTHER_GUEST.value(), morDs, false)) {
+ String msg = "Unable to create worker VM to execute BackupSnapshotCommand";
+ s_logger.error(msg);
+ throw new Exception(msg);
+ }
+ vmMo = hyperHost.findVmOnHyperHost(workerVMName);
+ if (vmMo == null) {
+ throw new Exception("Failed to find the newly create or relocated VM. vmName: " + workerVMName);
+ }
+ workerVm = vmMo;
+
+ // attach volume to worker VM
+ String datastoreVolumePath = String.format("[%s] %s.vmdk", dsMo.getName(), volumePath);
+ vmMo.attachDisk(new String[] { datastoreVolumePath }, morDs);
+ }
+ }
+
+ if (!vmMo.createSnapshot(snapshotUuid, "Snapshot taken for " + srcSnapshot.getName(), false, false)) {
+ throw new Exception("Failed to take snapshot " + srcSnapshot.getName() + " on vm: " + vmName);
+ }
+
+ snapshotBackupUuid = backupSnapshotToSecondaryStorage(vmMo, destSnapshot.getPath(), srcSnapshot.getVolume().getPath(), snapshotUuid, secondaryStorageUrl, prevSnapshotUuid, prevBackupUuid,
+ hostService.getWorkerName(context, cmd, 1));
+
+ success = (snapshotBackupUuid != null);
+ if (success) {
+ details = "Successfully backedUp the snapshotUuid: " + snapshotUuid + " to secondary storage.";
+ return new CopyCmdAnswer(details);
+ } else {
+ SnapshotObjectTO newSnapshot = new SnapshotObjectTO();
+ newSnapshot.setPath(snapshotBackupUuid);
+ return new CopyCmdAnswer(newSnapshot);
+ }
+ } finally {
+ if(vmMo != null){
+ ManagedObjectReference snapshotMor = vmMo.getSnapshotMor(snapshotUuid);
+ if (snapshotMor != null){
+ vmMo.removeSnapshot(snapshotUuid, false);
+ }
+ }
+
+ try {
+ if (workerVm != null) {
+ // detach volume and destroy worker vm
+ workerVm.detachAllDisks();
+ workerVm.destroy();
+ }
+ } catch (Throwable e) {
+ s_logger.warn("Failed to destroy worker VM: " + workerVMName);
+ }
+ }
+ } catch (Throwable e) {
+ if (e instanceof RemoteException) {
+ hostService.invalidateServiceContext(context);
+ }
+
+ s_logger.error("Unexpecpted exception ", e);
+
+ details = "BackupSnapshotCommand exception: " + StringUtils.getExceptionStackInfo(e);
+ return new CopyCmdAnswer(details);
+ }
+ }
+
+ @Override
+ public Answer attachIso(AttachCommand cmd) {
+ return this.attachIso(cmd.getDisk(), true, cmd.getVmName());
+ }
+
+ @Override
+ public Answer attachVolume(AttachCommand cmd) {
+ return this.attachVolume(cmd, cmd.getDisk(), true, cmd.getVmName());
+ }
+
+ private Answer attachVolume(Command cmd, DiskTO disk, boolean isAttach, String vmName) {
+
+ VolumeObjectTO volumeTO = (VolumeObjectTO)disk.getData();
+ PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)volumeTO.getDataStore();
+ try {
+ VmwareHypervisorHost hyperHost = this.hostService.getHyperHost(this.hostService.getServiceContext(null), null);
+ VirtualMachineMO vmMo = hyperHost.findVmOnHyperHost(vmName);
+ if (vmMo == null) {
+ String msg = "Unable to find the VM to execute AttachVolumeCommand, vmName: " + vmName;
+ s_logger.error(msg);
+ throw new Exception(msg);
+ }
+
+ ManagedObjectReference morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, primaryStore.getUuid());
+ if (morDs == null) {
+ String msg = "Unable to find the mounted datastore to execute AttachVolumeCommand, vmName: " + vmName;
+ s_logger.error(msg);
+ throw new Exception(msg);
+ }
+
+ DatastoreMO dsMo = new DatastoreMO(this.hostService.getServiceContext(null), morDs);
+ String datastoreVolumePath = String.format("[%s] %s.vmdk", dsMo.getName(), volumeTO.getPath());
+
+ AttachAnswer answer = new AttachAnswer(disk);
+ if (isAttach) {
+ vmMo.attachDisk(new String[] { datastoreVolumePath }, morDs);
+ } else {
+ vmMo.removeAllSnapshots();
+ vmMo.detachDisk(datastoreVolumePath, false);
+ }
+
+ return answer;
+ } catch (Throwable e) {
+ if (e instanceof RemoteException) {
+ s_logger.warn("Encounter remote exception to vCenter, invalidate VMware session context");
+ this.hostService.invalidateServiceContext(null);
+ }
+
+ String msg = "AttachVolumeCommand failed due to " + VmwareHelper.getExceptionMessage(e);
+ s_logger.error(msg, e);
+ return new AttachAnswer(msg);
+ }
+ }
+
+ private static String getSecondaryDatastoreUUID(String storeUrl) {
+ return UUID.nameUUIDFromBytes(storeUrl.getBytes()).toString();
+ }
+
+ public synchronized ManagedObjectReference prepareSecondaryDatastoreOnHost(String storeUrl) throws Exception {
+ String storeName = getSecondaryDatastoreUUID(storeUrl);
+ URI uri = new URI(storeUrl);
+
+ VmwareHypervisorHost hyperHost = this.hostService.getHyperHost(this.hostService.getServiceContext(null), null);
+ ManagedObjectReference morDatastore = hyperHost.mountDatastore(false, uri.getHost(), 0, uri.getPath(), storeName.replace("-", ""));
+
+ if (morDatastore == null)
+ throw new Exception("Unable to mount secondary storage on host. storeUrl: " + storeUrl);
+
+ return morDatastore;
+ }
+ private Answer attachIso(DiskTO disk, boolean isAttach, String vmName) {
+
+
+ try {
+ VmwareHypervisorHost hyperHost = this.hostService.getHyperHost(this.hostService.getServiceContext(null), null);
+ VirtualMachineMO vmMo = hyperHost.findVmOnHyperHost(vmName);
+ if (vmMo == null) {
+ String msg = "Unable to find VM in vSphere to execute AttachIsoCommand, vmName: " + vmName;
+ s_logger.error(msg);
+ throw new Exception(msg);
+ }
+ TemplateObjectTO iso = (TemplateObjectTO)disk.getData();
+ NfsTO nfsImageStore = (NfsTO)iso.getDataStore();
+ String storeUrl = nfsImageStore.getUrl();
+ if (storeUrl == null) {
+ if (!iso.getName().equalsIgnoreCase("vmware-tools.iso")) {
+ String msg = "ISO store root url is not found in AttachIsoCommand";
+ s_logger.error(msg);
+ throw new Exception(msg);
+ } else {
+ if (isAttach) {
+ vmMo.mountToolsInstaller();
+ } else {
+ try{
+ vmMo.unmountToolsInstaller();
+ }catch(Throwable e){
+ vmMo.detachIso(null);
+ }
+ }
+
+ return new AttachAnswer(disk);
+ }
+ }
+
+ ManagedObjectReference morSecondaryDs = prepareSecondaryDatastoreOnHost(storeUrl);
+ String isoPath = nfsImageStore.getUrl() + File.separator + iso.getPath();
+ if (!isoPath.startsWith(storeUrl)) {
+ assert (false);
+ String msg = "ISO path does not start with the secondary storage root";
+ s_logger.error(msg);
+ throw new Exception(msg);
+ }
+
+ int isoNameStartPos = isoPath.lastIndexOf('/');
+ String isoFileName = isoPath.substring(isoNameStartPos + 1);
+ String isoStorePathFromRoot = isoPath.substring(storeUrl.length(), isoNameStartPos);
+
+ // TODO, check if iso is already attached, or if there is a previous
+ // attachment
+ DatastoreMO secondaryDsMo = new DatastoreMO(this.hostService.getServiceContext(null), morSecondaryDs);
+ String storeName = secondaryDsMo.getName();
+ String isoDatastorePath = String.format("[%s] %s%s", storeName, isoStorePathFromRoot, isoFileName);
+
+ if (isAttach) {
+ vmMo.attachIso(isoDatastorePath, morSecondaryDs, true, false);
+ } else {
+ vmMo.detachIso(isoDatastorePath);
+ }
+
+ return new AttachAnswer(disk);
+ } catch (Throwable e) {
+ if (e instanceof RemoteException) {
+ s_logger.warn("Encounter remote exception to vCenter, invalidate VMware session context");
+ this.hostService.invalidateServiceContext(null);
+ }
+
+ if(isAttach) {
+ String msg = "AttachIsoCommand(attach) failed due to " + VmwareHelper.getExceptionMessage(e);
+ s_logger.error(msg, e);
+ return new AttachAnswer(msg);
+ } else {
+ String msg = "AttachIsoCommand(detach) failed due to " + VmwareHelper.getExceptionMessage(e);
+ s_logger.warn(msg, e);
+ return new AttachAnswer(msg);
+ }
+ }
+ }
+ @Override
+ public Answer dettachIso(DettachCommand cmd) {
+ return this.attachIso(cmd.getDisk(), false, cmd.getVmName());
+ }
+
+ @Override
+ public Answer dettachVolume(DettachCommand cmd) {
+ return this.attachVolume(cmd, cmd.getDisk(), false, cmd.getVmName());
+ }
+
+ protected VirtualMachineMO prepareVolumeHostDummyVm(VmwareHypervisorHost hyperHost, DatastoreMO dsMo, String vmName) throws Exception {
+ assert (hyperHost != null);
+
+ VirtualMachineMO vmMo = null;
+ VirtualMachineConfigSpec vmConfig = new VirtualMachineConfigSpec();
+ vmConfig.setName(vmName);
+ vmConfig.setMemoryMB((long) 4); // vmware request minimum of 4 MB
+ vmConfig.setNumCPUs(1);
+ vmConfig.setGuestId(VirtualMachineGuestOsIdentifier.OTHER_GUEST.value());
+ VirtualMachineFileInfo fileInfo = new VirtualMachineFileInfo();
+ fileInfo.setVmPathName(String.format("[%s]", dsMo.getName()));
+ vmConfig.setFiles(fileInfo);
+
+ // Scsi controller
+ VirtualLsiLogicController scsiController = new VirtualLsiLogicController();
+ scsiController.setSharedBus(VirtualSCSISharing.NO_SHARING);
+ scsiController.setBusNumber(0);
+ scsiController.setKey(1);
+ VirtualDeviceConfigSpec scsiControllerSpec = new VirtualDeviceConfigSpec();
+ scsiControllerSpec.setDevice(scsiController);
+ scsiControllerSpec.setOperation(VirtualDeviceConfigSpecOperation.ADD);
+
+ vmConfig.getDeviceChange().add(scsiControllerSpec );
+ hyperHost.createVm(vmConfig);
+ vmMo = hyperHost.findVmOnHyperHost(vmName);
+ return vmMo;
+ }
+ @Override
+ public Answer createVolume(CreateObjectCommand cmd) {
+
+ VolumeObjectTO volume = (VolumeObjectTO)cmd.getData();
+ PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)volume.getDataStore();
+
+ try {
+ VmwareContext context = this.hostService.getServiceContext(null);
+ VmwareHypervisorHost hyperHost = this.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 = String.format("[%s] %s.vmdk", dsMo.getName(), volumeUuid);
+ String dummyVmName = this.hostService.getWorkerName(context, cmd, 0);
+ try {
+ vmMo = prepareVolumeHostDummyVm(hyperHost, dsMo, dummyVmName);
+ if (vmMo == null) {
+ throw new Exception("Unable to create a dummy VM for volume creation");
+ }
+
+ synchronized (this) {
+ // s_logger.info("Delete file if exists in datastore to clear the way for creating the volume. file: " + volumeDatastorePath);
+ VmwareHelper.deleteVolumeVmdkFiles(dsMo, volumeUuid.toString(), dcMo);
+
+ vmMo.createDisk(volumeDatastorePath, (int) (volume.getSize() / (1024L * 1024L)), morDatastore, vmMo.getScsiDeviceControllerKey());
+ vmMo.detachDisk(volumeDatastorePath, false);
+ }
+
+ VolumeObjectTO newVol = new VolumeObjectTO();
+ newVol.setPath(volumeUuid);
+ return new CreateObjectAnswer(newVol);
+ } finally {
+ s_logger.info("Destroy dummy VM after volume creation");
+ vmMo.detachAllDisks();
+ vmMo.destroy();
+ }
+
+ } catch (Throwable e) {
+ if (e instanceof RemoteException) {
+ s_logger.warn("Encounter remote exception to vCenter, invalidate VMware session context");
+ this.hostService.invalidateServiceContext(null);
+ }
+
+ String msg = "CreateCommand failed due to " + VmwareHelper.getExceptionMessage(e);
+ s_logger.error(msg, e);
+ return new CreateObjectAnswer(e.toString());
+ }
+ }
+
+ @Override
+ public Answer createSnapshot(CreateObjectCommand cmd) {
+ // snapshot operation (create or destroy) is handled inside BackupSnapshotCommand(), we just fake
+ // a success return here
+ String snapshotUUID = UUID.randomUUID().toString();
+ SnapshotObjectTO newSnapshot = new SnapshotObjectTO();
+ newSnapshot.setPath(snapshotUUID);
+ return new CreateObjectAnswer(newSnapshot);
+ }
+
+ @Override
+ public Answer deleteVolume(DeleteCommand cmd) {
+ if (s_logger.isInfoEnabled()) {
+ s_logger.info("Executing resource DestroyCommand: " + _gson.toJson(cmd));
+ }
+
+ /*
+ * DestroyCommand content example
+ *
+ * {"volume": {"id":5,"name":"Volume1", "mountPoint":"/export/home/kelven/vmware-test/primary",
+ * "path":"6bb8762f-c34c-453c-8e03-26cc246ceec4", "size":0,"type":"DATADISK","resourceType":
+ * "STORAGE_POOL","storagePoolType":"NetworkFilesystem", "poolId":0,"deviceId":0 } }
+ *
+ * {"volume": {"id":1, "name":"i-2-1-KY-ROOT", "mountPoint":"/export/home/kelven/vmware-test/primary",
+ * "path":"i-2-1-KY-ROOT","size":0,"type":"ROOT", "resourceType":"STORAGE_POOL", "storagePoolType":"NetworkFilesystem",
+ * "poolId":0,"deviceId":0 } }
+ */
+
+ try {
+ VmwareContext context = this.hostService.getServiceContext(null);
+ VmwareHypervisorHost hyperHost = this.hostService.getHyperHost(context, null);
+ VolumeObjectTO vol = (VolumeObjectTO)cmd.getData();
+ PrimaryDataStoreTO store = (PrimaryDataStoreTO)vol.getDataStore();
+
+ ManagedObjectReference morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, store.getUuid());
+ if (morDs == null) {
+ String msg = "Unable to find datastore based on volume mount point " + store.getPath();
+ 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) {
+ if (s_logger.isInfoEnabled()) {
+ s_logger.info("Destroy root volume and VM itself. vmName " + vmName);
+ }
+
+ 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 (this.resource.getVmState(vmMo) != State.Stopped)
+ vmMo.safePowerOff(_shutdown_waitMs);
+ vmMo.tearDownDevices(new Class<?>[] { VirtualDisk.class, VirtualEthernetCard.class });
+ vmMo.destroy();
+
+ for (NetworkDetails netDetails : networks) {
+ if (netDetails.getGCTag() != null && netDetails.getGCTag().equalsIgnoreCase("true")) {
+ if (netDetails.getVMMorsOnNetwork() == null || netDetails.getVMMorsOnNetwork().length == 1) {
+ this.resource.cleanupNetwork(hostMo, netDetails);
+ }
+ }
+ }
+ }
+
+ if (s_logger.isInfoEnabled())
+ s_logger.info("Destroy volume by original name: " + vol.getPath() + ".vmdk");
+ dsMo.deleteFile(vol.getPath() + ".vmdk", morDc, true);
+
+ // root volume may be created via linked-clone, delete the delta disk as well
+ if (_fullCloneFlag) {
+ if (s_logger.isInfoEnabled()) {
+ s_logger.info("Destroy volume by derived name: " + vol.getPath() + "-flat.vmdk");
+ }
+ dsMo.deleteFile(vol.getPath() + "-flat.vmdk", morDc, true);
+ } else {
+ if (s_logger.isInfoEnabled()) {
+ s_logger.info("Destroy volume by derived name: " + vol.getPath() + "-delta.vmdk");
+ }
+ dsMo.deleteFile(vol.getPath() + "-delta.vmdk", morDc, true);
+ }
+ return new Answer(cmd, true, "Success");
+ }
+
+ if (s_logger.isInfoEnabled()) {
+ s_logger.info("Destroy root volume directly from datastore");
+ }
+ } else {
+ // evitTemplate will be converted into DestroyCommand, test if we are running in this case
+ VirtualMachineMO vmMo = clusterMo.findVmOnHyperHost(vol.getPath());
+ if (vmMo != null) {
+ if (s_logger.isInfoEnabled())
+ s_logger.info("Destroy template volume " + vol.getPath());
+
+ vmMo.destroy();
+ return new Answer(cmd, true, "Success");
+ }
+ }
+
+ String chainInfo = vol.getChainInfo();
+ if (chainInfo != null && !chainInfo.isEmpty()) {
+ s_logger.info("Destroy volume by chain info: " + chainInfo);
+ String[] diskChain = _gson.fromJson(chainInfo, String[].class);
+
+ if (diskChain != null && diskChain.length > 0) {
+ for (String backingName : diskChain) {
+ if (s_logger.isInfoEnabled()) {
+ s_logger.info("Delete volume backing file: " + backingName);
+ }
+ dsMo.deleteFile(backingName, morDc, true);
+ }
+ } else {
+ if (s_logger.isInfoEnabled()) {
+ s_logger.info("Empty disk chain info, fall back to try to delete by original backing file name");
+ }
+ dsMo.deleteFile(vol.getPath() + ".vmdk", morDc, true);
+
+ if (s_logger.isInfoEnabled()) {
+ s_logger.info("Destroy volume by derived name: " + vol.getPath() + "-flat.vmdk");
+ }
+ dsMo.deleteFile(vol.getPath() + "-flat.vmdk", morDc, true);
+ }
+ } else {
+ if (s_logger.isInfoEnabled()) {
+ s_logger.info("Destroy volume by original name: " + vol.getPath() + ".vmdk");
+ }
+ dsMo.deleteFile(vol.getPath() + ".vmdk", morDc, true);
+
+ if (s_logger.isInfoEnabled()) {
+ s_logger.info("Destroy volume by derived name: " + vol.getPath() + "-flat.vmdk");
+ }
+ dsMo.deleteFile(vol.getPath() + "-flat.vmdk", morDc, true);
+ }
+
+ 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");
+ this.hostService.invalidateServiceContext(null);
+ }
+
+ String msg = "DestroyCommand failed due to " + VmwareHelper.getExceptionMessage(e);
+ s_logger.error(msg, e);
+ return new Answer(cmd, false, msg);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/42e25a22/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java
index c88a746..701adbe 100644
--- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java
+++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java
@@ -58,6 +58,8 @@ import com.cloud.agent.api.to.*;
import com.cloud.network.rules.FirewallRule;
import org.apache.cloudstack.storage.command.StorageSubSystemCommand;
+import org.apache.cloudstack.storage.to.TemplateObjectTO;
+import org.apache.cloudstack.storage.to.VolumeObjectTO;
import org.apache.log4j.Logger;
import org.apache.xmlrpc.XmlRpcException;
import org.w3c.dom.Document;
@@ -234,6 +236,8 @@ import com.cloud.storage.Storage.ImageFormat;
import com.cloud.storage.Storage.StoragePoolType;
import com.cloud.storage.Volume;
import com.cloud.storage.VolumeVO;
+import com.cloud.storage.resource.StorageSubsystemCommandHandler;
+import com.cloud.storage.resource.StorageSubsystemCommandHandlerBase;
import com.cloud.storage.template.TemplateProp;
import com.cloud.template.VirtualMachineTemplate.BootloaderType;
import com.cloud.utils.NumbersUtil;
@@ -334,7 +338,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
protected boolean _canBridgeFirewall = false;
protected boolean _isOvs = false;
protected List<VIF> _tmpDom0Vif = new ArrayList<VIF>();
- protected XenServerStorageResource storageResource;
+ protected StorageSubsystemCommandHandler storageHandler;
protected int _maxNics = 7;
public enum SRType {
@@ -594,7 +598,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
} else if (clazz == CheckS2SVpnConnectionsCommand.class) {
return execute((CheckS2SVpnConnectionsCommand) cmd);
} else if (cmd instanceof StorageSubSystemCommand) {
- return this.storageResource.handleStorageCommands((StorageSubSystemCommand)cmd);
+ return this.storageHandler.handleStorageCommands((StorageSubSystemCommand)cmd);
} else if (clazz == CreateVMSnapshotCommand.class) {
return execute((CreateVMSnapshotCommand)cmd);
} else if (clazz == DeleteVMSnapshotCommand.class) {
@@ -1089,31 +1093,42 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
}
}
- protected VDI mount(Connection conn, String vmName, VolumeTO volume) throws XmlRpcException, XenAPIException {
- if (volume.getType() == Volume.Type.ISO) {
- String isopath = volume.getPath();
- if (isopath == null) {
+ protected VDI mount(Connection conn, String vmName, DiskTO volume) throws XmlRpcException, XenAPIException {
+ DataTO data = volume.getData();
+ Volume.Type type = volume.getType();
+ if (type == Volume.Type.ISO) {
+ TemplateObjectTO iso = (TemplateObjectTO)data;
+ DataStoreTO store = iso.getDataStore();
+
+ if (store == null) {
+ //It's a fake iso
return null;
}
- if (isopath.startsWith("xs-tools")) {
+
+ //corer case, xenserver pv driver iso
+ String templateName = iso.getName();
+ if (templateName.startsWith("xs-tools")) {
try {
- Set<VDI> vdis = VDI.getByNameLabel(conn, isopath);
+ Set<VDI> vdis = VDI.getByNameLabel(conn, templateName);
if (vdis.isEmpty()) {
- throw new CloudRuntimeException("Could not find ISO with URL: " + isopath);
+ throw new CloudRuntimeException("Could not find ISO with URL: " + templateName);
}
return vdis.iterator().next();
-
} catch (XenAPIException e) {
- throw new CloudRuntimeException("Unable to get pv iso: " + isopath + " due to " + e.toString());
+ throw new CloudRuntimeException("Unable to get pv iso: " + templateName + " due to " + e.toString());
} catch (Exception e) {
- throw new CloudRuntimeException("Unable to get pv iso: " + isopath + " due to " + e.toString());
+ throw new CloudRuntimeException("Unable to get pv iso: " + templateName + " due to " + e.toString());
}
}
+
+ if (!(store instanceof NfsTO)) {
+ throw new CloudRuntimeException("only support mount iso on nfs");
+ }
+ NfsTO nfsStore = (NfsTO)store;
+ String isoPath = nfsStore.getUrl() + File.separator + iso.getPath();
+ int index = isoPath.lastIndexOf("/");
-
- int index = isopath.lastIndexOf("/");
-
- String mountpoint = isopath.substring(0, index);
+ String mountpoint = isoPath.substring(0, index);
URI uri;
try {
uri = new URI(mountpoint);
@@ -1122,20 +1137,21 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
}
SR isoSr = createIsoSRbyURI(conn, uri, vmName, false);
- String isoname = isopath.substring(index + 1);
+ String isoname = isoPath.substring(index + 1);
VDI isoVdi = getVDIbyLocationandSR(conn, isoname, isoSr);
if (isoVdi == null) {
- throw new CloudRuntimeException("Unable to find ISO " + volume.getPath());
+ throw new CloudRuntimeException("Unable to find ISO " + isoPath);
}
return isoVdi;
} else {
- return VDI.getByUuid(conn, volume.getPath());
+ VolumeObjectTO vol = (VolumeObjectTO)data;
+ return VDI.getByUuid(conn,vol.getPath());
}
}
- protected VBD createVbd(Connection conn, VolumeTO volume, String vmName, VM vm, BootloaderType bootLoaderType) throws XmlRpcException, XenAPIException {
+ protected VBD createVbd(Connection conn, DiskTO volume, String vmName, VM vm, BootloaderType bootLoaderType) throws XmlRpcException, XenAPIException {
Volume.Type type = volume.getType();
VDI vdi = mount(conn, vmName, volume);
@@ -1153,7 +1169,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
vbdr.bootable = true;
}
- vbdr.userdevice = Long.toString(volume.getDeviceId());
+ vbdr.userdevice = Long.toString(volume.getDiskSeq());
if (volume.getType() == Volume.Type.ISO) {
vbdr.mode = Types.VbdMode.RO;
vbdr.type = Types.VbdType.CD;
@@ -1246,12 +1262,17 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
if (!(guestOsTypeName.startsWith("Windows") || guestOsTypeName.startsWith("Citrix") || guestOsTypeName.startsWith("Other"))) {
if (vmSpec.getBootloader() == BootloaderType.CD) {
- VolumeTO [] disks = vmSpec.getDisks();
- for (VolumeTO disk : disks) {
- if (disk.getType() == Volume.Type.ISO && disk.getOsType() != null) {
- String isoGuestOsName = getGuestOsType(disk.getOsType(), vmSpec.getBootloader() == BootloaderType.CD);
- if (!isoGuestOsName.equals(guestOsTypeName)) {
- vmSpec.setBootloader(BootloaderType.PyGrub);
+ DiskTO [] disks = vmSpec.getDisks();
+ for (DiskTO disk : disks) {
+ Volume.Type type = disk.getType();
+ if (type == Volume.Type.ISO) {
+ TemplateObjectTO tmpl = (TemplateObjectTO)disk.getData();
+ String osType = tmpl.getGuestOsType();
+ if (tmpl.getFormat() == ImageFormat.ISO && osType != null ) {
+ String isoGuestOsName = getGuestOsType(osType, vmSpec.getBootloader() == BootloaderType.CD);
+ if (!isoGuestOsName.equals(guestOsTypeName)) {
+ vmSpec.setBootloader(BootloaderType.PyGrub);
+ }
}
}
}
@@ -1496,7 +1517,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
Host host = Host.getByUuid(conn, _host.uuid);
vm = createVmFromTemplate(conn, vmSpec, host);
- for (VolumeTO disk : vmSpec.getDisks()) {
+ for (DiskTO disk : vmSpec.getDisks()) {
createVbd(conn, disk, vmName, vm, vmSpec.getBootloader());
}
@@ -5774,13 +5795,14 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
CheckXenHostInfo();
- this.storageResource = getStorageResource();
+ this.storageHandler = getStorageHandler();
return true;
}
- protected XenServerStorageResource getStorageResource() {
- return new XenServerStorageResource(this);
+ protected StorageSubsystemCommandHandler getStorageHandler() {
+ XenServerStorageProcessor processor = new XenServerStorageProcessor(this);
+ return new StorageSubsystemCommandHandlerBase(processor);
}
private void CheckXenHostInfo() throws ConfigurationException {
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/42e25a22/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServer56FP1Resource.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServer56FP1Resource.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServer56FP1Resource.java
index d64e173..6ce3837 100644
--- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServer56FP1Resource.java
+++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServer56FP1Resource.java
@@ -26,11 +26,14 @@ import java.util.Map;
import java.util.Set;
import javax.ejb.Local;
+
+import org.apache.cloudstack.storage.to.TemplateObjectTO;
import org.apache.log4j.Logger;
import org.apache.xmlrpc.XmlRpcException;
import com.cloud.agent.api.FenceAnswer;
import com.cloud.agent.api.FenceCommand;
+import com.cloud.agent.api.to.DiskTO;
import com.cloud.agent.api.to.VirtualMachineTO;
import com.cloud.agent.api.to.VolumeTO;
import com.cloud.resource.ServerResource;
@@ -194,13 +197,17 @@ public class XenServer56FP1Resource extends XenServer56Resource {
if (!(guestOsTypeName.startsWith("Windows") || guestOsTypeName.startsWith("Citrix") || guestOsTypeName.startsWith("Other"))) {
if (vmSpec.getBootloader() == BootloaderType.CD) {
- VolumeTO[] disks = vmSpec.getDisks();
- for (VolumeTO disk : disks) {
- if (disk.getType() == Volume.Type.ISO && disk.getOsType() != null) {
- String isoGuestOsName = getGuestOsType(disk.getOsType(), vmSpec.getBootloader() == BootloaderType.CD);
- if (!isoGuestOsName.equals(guestOsTypeName)) {
- vmSpec.setBootloader(BootloaderType.PyGrub);
- }
+ DiskTO[] disks = vmSpec.getDisks();
+ for (DiskTO disk : disks) {
+ if (disk.getType() == Volume.Type.ISO ) {
+ TemplateObjectTO iso = (TemplateObjectTO)disk.getData();
+ String osType = iso.getGuestOsType();
+ if (osType != null) {
+ String isoGuestOsName = getGuestOsType(osType, vmSpec.getBootloader() == BootloaderType.CD);
+ if (!isoGuestOsName.equals(guestOsTypeName)) {
+ vmSpec.setBootloader(BootloaderType.PyGrub);
+ }
+ }
}
}
}
[2/7] refactor kvm/vmware resource code
Posted by ed...@apache.org.
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/42e25a22/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageResource.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageResource.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageResource.java
deleted file mode 100644
index 8b27efe..0000000
--- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageResource.java
+++ /dev/null
@@ -1,1327 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package com.cloud.hypervisor.xen.resource;
-
-import java.beans.BeanInfo;
-import java.beans.IntrospectionException;
-import java.beans.Introspector;
-import java.beans.PropertyDescriptor;
-import java.io.BufferedOutputStream;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.lang.reflect.InvocationTargetException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.UUID;
-
-import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType;
-import org.apache.cloudstack.engine.subsystem.api.storage.DataTO;
-import org.apache.cloudstack.storage.command.AttachPrimaryDataStoreAnswer;
-import org.apache.cloudstack.storage.command.AttachPrimaryDataStoreCmd;
-import org.apache.cloudstack.storage.command.CopyCmdAnswer;
-import org.apache.cloudstack.storage.command.CopyCommand;
-import org.apache.cloudstack.storage.command.CreateObjectAnswer;
-import org.apache.cloudstack.storage.command.CreateObjectCommand;
-import org.apache.cloudstack.storage.command.CreatePrimaryDataStoreCmd;
-import org.apache.cloudstack.storage.command.DeleteCommand;
-import org.apache.cloudstack.storage.command.StorageSubSystemCommand;
-import org.apache.cloudstack.storage.datastore.protocol.DataStoreProtocol;
-import org.apache.cloudstack.storage.to.ImageStoreTO;
-import org.apache.cloudstack.storage.to.PrimaryDataStoreTO;
-import org.apache.cloudstack.storage.to.SnapshotObjectTO;
-import org.apache.cloudstack.storage.to.TemplateObjectTO;
-import org.apache.cloudstack.storage.to.VolumeObjectTO;
-import org.apache.http.HttpEntity;
-import org.apache.http.HttpResponse;
-import org.apache.http.client.ClientProtocolException;
-import org.apache.http.client.methods.HttpGet;
-import org.apache.http.impl.client.DefaultHttpClient;
-import org.apache.log4j.Logger;
-import org.apache.xmlrpc.XmlRpcException;
-
-import com.cloud.agent.api.Answer;
-import com.cloud.agent.api.BackupSnapshotAnswer;
-import com.cloud.agent.api.Command;
-import com.cloud.agent.api.ManageSnapshotAnswer;
-import com.cloud.agent.api.ManageSnapshotCommand;
-import com.cloud.agent.api.storage.CopyVolumeAnswer;
-import com.cloud.agent.api.storage.CreateAnswer;
-import com.cloud.agent.api.storage.CreatePrivateTemplateAnswer;
-import com.cloud.agent.api.storage.DeleteVolumeCommand;
-import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer;
-import com.cloud.agent.api.to.DataStoreTO;
-import com.cloud.agent.api.to.NfsTO;
-import com.cloud.agent.api.to.S3TO;
-import com.cloud.agent.api.to.StorageFilerTO;
-import com.cloud.agent.api.to.SwiftTO;
-import com.cloud.agent.api.to.VolumeTO;
-import com.cloud.exception.InternalErrorException;
-import com.cloud.hypervisor.xen.resource.CitrixResourceBase.SRType;
-import com.cloud.storage.DataStoreRole;
-import com.cloud.storage.Storage.ImageFormat;
-import com.cloud.utils.S3Utils;
-import com.cloud.utils.StringUtils;
-import com.cloud.utils.exception.CloudRuntimeException;
-import com.cloud.utils.storage.encoding.DecodedDataObject;
-import com.cloud.utils.storage.encoding.DecodedDataStore;
-import com.cloud.utils.storage.encoding.Decoder;
-import com.cloud.vm.DiskProfile;
-import com.xensource.xenapi.Connection;
-import com.xensource.xenapi.Host;
-import com.xensource.xenapi.PBD;
-import com.xensource.xenapi.SR;
-import com.xensource.xenapi.Types;
-import com.xensource.xenapi.Types.BadServerResponse;
-import com.xensource.xenapi.Types.XenAPIException;
-import com.xensource.xenapi.VDI;
-
-public class XenServerStorageResource {
- private static final Logger s_logger = Logger.getLogger(XenServerStorageResource.class);
- protected CitrixResourceBase hypervisorResource;
-
- public XenServerStorageResource(CitrixResourceBase resource) {
- this.hypervisorResource = resource;
- }
-
- public Answer handleStorageCommands(StorageSubSystemCommand command) {
- if (command instanceof CopyCommand) {
- return this.execute((CopyCommand)command);
- } else if (command instanceof AttachPrimaryDataStoreCmd) {
- return this.execute((AttachPrimaryDataStoreCmd)command);
- } else if (command instanceof CreatePrimaryDataStoreCmd) {
- return execute((CreatePrimaryDataStoreCmd) command);
- } else if (command instanceof CreateObjectCommand) {
- return execute((CreateObjectCommand) command);
- } else if (command instanceof DeleteCommand) {
- return execute((DeleteCommand)command);
- }
- return new Answer((Command)command, false, "not implemented yet");
- }
-
- protected SR getSRByNameLabel(Connection conn, String nameLabel) throws BadServerResponse, XenAPIException, XmlRpcException {
- Set<SR> srs = SR.getByNameLabel(conn, nameLabel);
- if (srs.size() != 1) {
- throw new CloudRuntimeException("storage uuid: " + nameLabel + " is not unique");
- }
- SR poolsr = srs.iterator().next();
- return poolsr;
- }
-
- protected VDI createVdi(Connection conn, String vdiName, SR sr, long size) throws BadServerResponse, XenAPIException, XmlRpcException {
- VDI.Record vdir = new VDI.Record();
- vdir.nameLabel = vdiName;
- vdir.SR = sr;
- vdir.type = Types.VdiType.USER;
-
- vdir.virtualSize = size;
- VDI vdi = VDI.create(conn, vdir);
- return vdi;
- }
-
- protected void deleteVDI(Connection conn, VDI vdi) throws BadServerResponse, XenAPIException, XmlRpcException {
- vdi.destroy(conn);
- }
-
- private Map<String, String> getParameters(URI uri) {
- String parameters = uri.getQuery();
- Map<String, String> params = new HashMap<String, String>();
- List<String> paraLists = Arrays.asList(parameters.split("&"));
- for (String para : paraLists) {
- String[] pair = para.split("=");
- params.put(pair[0], pair[1]);
- }
- return params;
- }
-
- protected CreateObjectAnswer getTemplateSize(CreateObjectCommand cmd, String templateUrl) {
- /*Connection conn = hypervisorResource.getConnection();
- long size = this.getTemplateSize(conn, templateUrl);
- return new CreateObjectAnswer(cmd, templateUrl, size);*/
- return null;
- }
-
- protected CreateObjectAnswer createSnapshot(SnapshotObjectTO snapshotTO) {
- Connection conn = hypervisorResource.getConnection();
- long snapshotId = snapshotTO.getId();
- String snapshotName = snapshotTO.getName();
- String details = "create snapshot operation Failed for snapshotId: " + snapshotId;
- String snapshotUUID = null;
-
- try {
- String volumeUUID = snapshotTO.getVolume().getPath();
- VDI volume = VDI.getByUuid(conn, volumeUUID);
-
- VDI snapshot = volume.snapshot(conn, new HashMap<String, String>());
-
- if (snapshotName != null) {
- snapshot.setNameLabel(conn, snapshotName);
- }
-
- snapshotUUID = snapshot.getUuid(conn);
- String preSnapshotUUID = snapshotTO.getParentSnapshotPath();
- //check if it is a empty snapshot
- if( preSnapshotUUID != null) {
- SR sr = volume.getSR(conn);
- String srUUID = sr.getUuid(conn);
- String type = sr.getType(conn);
- Boolean isISCSI = IsISCSI(type);
- String snapshotParentUUID = getVhdParent(conn, srUUID, snapshotUUID, isISCSI);
-
- String preSnapshotParentUUID = getVhdParent(conn, srUUID, preSnapshotUUID, isISCSI);
- if( snapshotParentUUID != null && snapshotParentUUID.equals(preSnapshotParentUUID)) {
- // this is empty snapshot, remove it
- snapshot.destroy(conn);
- snapshotUUID = preSnapshotUUID;
- }
- }
- SnapshotObjectTO newSnapshot = new SnapshotObjectTO();
- newSnapshot.setPath(snapshotUUID);
- return new CreateObjectAnswer(newSnapshot);
- } catch (XenAPIException e) {
- details += ", reason: " + e.toString();
- s_logger.warn(details, e);
- } catch (Exception e) {
- details += ", reason: " + e.toString();
- s_logger.warn(details, e);
- }
-
- return new CreateObjectAnswer(details);
- }
- protected CreateObjectAnswer execute(CreateObjectCommand cmd) {
- DataTO data = cmd.getData();
- try {
- if (data.getObjectType() == DataObjectType.VOLUME) {
- return createVolume(data);
- } else if (data.getObjectType() == DataObjectType.SNAPSHOT) {
- return createSnapshot((SnapshotObjectTO)data);
- }
- return new CreateObjectAnswer("not supported type");
- } catch (Exception e) {
- s_logger.debug("Failed to create object: " + data.getObjectType() + ": " + e.toString());
- return new CreateObjectAnswer(e.toString());
- }
- }
-
- protected Answer deleteVolume(VolumeObjectTO volume) {
- Connection conn = hypervisorResource.getConnection();
- String errorMsg = null;
- try {
- VDI vdi = VDI.getByUuid(conn, volume.getPath());
- deleteVDI(conn, vdi);
- return new Answer(null);
- } catch (BadServerResponse e) {
- s_logger.debug("Failed to delete volume", e);
- errorMsg = e.toString();
- } catch (XenAPIException e) {
- s_logger.debug("Failed to delete volume", e);
- errorMsg = e.toString();
- } catch (XmlRpcException e) {
- s_logger.debug("Failed to delete volume", e);
- errorMsg = e.toString();
- }
- return new Answer(null, false, errorMsg);
- }
-
- protected Answer execute(DeleteCommand cmd) {
- DataTO data = cmd.getData();
- Answer answer = null;
- if (data.getObjectType() == DataObjectType.VOLUME) {
- answer = deleteVolume((VolumeObjectTO)data);
- } else {
- answer = new Answer(cmd, false, "unsupported type");
- }
-
- return answer;
- }
-
- /* protected Answer execute(CreateVolumeFromBaseImageCommand cmd) {
- VolumeObjectTO volume = cmd.getVolume();
- ImageOnPrimayDataStoreTO baseImage = cmd.getImage();
- Connection conn = hypervisorResource.getConnection();
-
- try {
- VDI baseVdi = VDI.getByUuid(conn, baseImage.getPathOnPrimaryDataStore());
- VDI newVol = baseVdi.createClone(conn, new HashMap<String, String>());
- newVol.setNameLabel(conn, volume.getName());
- return new CreateObjectAnswer(cmd, newVol.getUuid(conn), newVol.getVirtualSize(conn));
- } catch (BadServerResponse e) {
- return new Answer(cmd, false, e.toString());
- } catch (XenAPIException e) {
- return new Answer(cmd, false, e.toString());
- } catch (XmlRpcException e) {
- return new Answer(cmd, false, e.toString());
- }
- }*/
-
- protected SR getNfsSR(Connection conn, DecodedDataStore store) {
-
- Map<String, String> deviceConfig = new HashMap<String, String>();
-
- String uuid = store.getUuid();
- try {
- String server = store.getServer();
- String serverpath = store.getPath();
-
- serverpath = serverpath.replace("//", "/");
- Set<SR> srs = SR.getAll(conn);
- for (SR sr : srs) {
- if (!SRType.NFS.equals(sr.getType(conn))) {
- continue;
- }
-
- Set<PBD> pbds = sr.getPBDs(conn);
- if (pbds.isEmpty()) {
- continue;
- }
-
- PBD pbd = pbds.iterator().next();
-
- Map<String, String> dc = pbd.getDeviceConfig(conn);
-
- if (dc == null) {
- continue;
- }
-
- if (dc.get("server") == null) {
- continue;
- }
-
- if (dc.get("serverpath") == null) {
- continue;
- }
-
- if (server.equals(dc.get("server")) && serverpath.equals(dc.get("serverpath"))) {
- throw new CloudRuntimeException("There is a SR using the same configuration server:" + dc.get("server") + ", serverpath:"
- + dc.get("serverpath") + " for pool " + uuid + "on host:" + hypervisorResource.getHost().uuid);
- }
-
- }
- deviceConfig.put("server", server);
- deviceConfig.put("serverpath", serverpath);
- Host host = Host.getByUuid(conn, hypervisorResource.getHost().uuid);
- SR sr = SR.create(conn, host, deviceConfig, new Long(0), uuid, uuid, SRType.NFS.toString(), "user", true,
- new HashMap<String, String>());
- sr.scan(conn);
- return sr;
- } catch (XenAPIException e) {
- throw new CloudRuntimeException("Unable to create NFS SR " + uuid, e);
- } catch (XmlRpcException e) {
- throw new CloudRuntimeException("Unable to create NFS SR " + uuid, e);
- }
- }
- /*
- protected SR getIscsiSR(Connection conn, PrimaryDataStoreTO pool) {
- synchronized (pool.getUuid().intern()) {
- Map<String, String> deviceConfig = new HashMap<String, String>();
- try {
- String target = pool.getHost();
- String path = pool.getPath();
- if (path.endsWith("/")) {
- path = path.substring(0, path.length() - 1);
- }
-
- String tmp[] = path.split("/");
- if (tmp.length != 3) {
- String msg = "Wrong iscsi path " + pool.getPath() + " it should be /targetIQN/LUN";
- s_logger.warn(msg);
- throw new CloudRuntimeException(msg);
- }
- String targetiqn = tmp[1].trim();
- String lunid = tmp[2].trim();
- String scsiid = "";
-
- Set<SR> srs = SR.getByNameLabel(conn, pool.getUuid());
- for (SR sr : srs) {
- if (!SRType.LVMOISCSI.equals(sr.getType(conn))) {
- continue;
- }
- Set<PBD> pbds = sr.getPBDs(conn);
- if (pbds.isEmpty()) {
- continue;
- }
- PBD pbd = pbds.iterator().next();
- Map<String, String> dc = pbd.getDeviceConfig(conn);
- if (dc == null) {
- continue;
- }
- if (dc.get("target") == null) {
- continue;
- }
- if (dc.get("targetIQN") == null) {
- continue;
- }
- if (dc.get("lunid") == null) {
- continue;
- }
- if (target.equals(dc.get("target")) && targetiqn.equals(dc.get("targetIQN")) && lunid.equals(dc.get("lunid"))) {
- throw new CloudRuntimeException("There is a SR using the same configuration target:" + dc.get("target") + ", targetIQN:"
- + dc.get("targetIQN") + ", lunid:" + dc.get("lunid") + " for pool " + pool.getUuid() + "on host:" + _host.uuid);
- }
- }
- deviceConfig.put("target", target);
- deviceConfig.put("targetIQN", targetiqn);
-
- Host host = Host.getByUuid(conn, _host.uuid);
- Map<String, String> smConfig = new HashMap<String, String>();
- String type = SRType.LVMOISCSI.toString();
- String poolId = Long.toString(pool.getId());
- SR sr = null;
- try {
- sr = SR.create(conn, host, deviceConfig, new Long(0), pool.getUuid(), poolId, type, "user", true,
- smConfig);
- } catch (XenAPIException e) {
- String errmsg = e.toString();
- if (errmsg.contains("SR_BACKEND_FAILURE_107")) {
- String lun[] = errmsg.split("<LUN>");
- boolean found = false;
- for (int i = 1; i < lun.length; i++) {
- int blunindex = lun[i].indexOf("<LUNid>") + 7;
- int elunindex = lun[i].indexOf("</LUNid>");
- String ilun = lun[i].substring(blunindex, elunindex);
- ilun = ilun.trim();
- if (ilun.equals(lunid)) {
- int bscsiindex = lun[i].indexOf("<SCSIid>") + 8;
- int escsiindex = lun[i].indexOf("</SCSIid>");
- scsiid = lun[i].substring(bscsiindex, escsiindex);
- scsiid = scsiid.trim();
- found = true;
- break;
- }
- }
- if (!found) {
- String msg = "can not find LUN " + lunid + " in " + errmsg;
- s_logger.warn(msg);
- throw new CloudRuntimeException(msg);
- }
- } else {
- String msg = "Unable to create Iscsi SR " + deviceConfig + " due to " + e.toString();
- s_logger.warn(msg, e);
- throw new CloudRuntimeException(msg, e);
- }
- }
- deviceConfig.put("SCSIid", scsiid);
-
- String result = SR.probe(conn, host, deviceConfig, type , smConfig);
- String pooluuid = null;
- if( result.indexOf("<UUID>") != -1) {
- pooluuid = result.substring(result.indexOf("<UUID>") + 6, result.indexOf("</UUID>")).trim();
- }
- if( pooluuid == null || pooluuid.length() != 36) {
- sr = SR.create(conn, host, deviceConfig, new Long(0), pool.getUuid(), poolId, type, "user", true,
- smConfig);
- } else {
- sr = SR.introduce(conn, pooluuid, pool.getUuid(), poolId,
- type, "user", true, smConfig);
- Pool.Record pRec = XenServerConnectionPool.getPoolRecord(conn);
- PBD.Record rec = new PBD.Record();
- rec.deviceConfig = deviceConfig;
- rec.host = pRec.master;
- rec.SR = sr;
- PBD pbd = PBD.create(conn, rec);
- pbd.plug(conn);
- }
- sr.scan(conn);
- return sr;
- } catch (XenAPIException e) {
- String msg = "Unable to create Iscsi SR " + deviceConfig + " due to " + e.toString();
- s_logger.warn(msg, e);
- throw new CloudRuntimeException(msg, e);
- } catch (Exception e) {
- String msg = "Unable to create Iscsi SR " + deviceConfig + " due to " + e.getMessage();
- s_logger.warn(msg, e);
- throw new CloudRuntimeException(msg, e);
- }
- }
- }*/
-
- protected Answer execute(CreatePrimaryDataStoreCmd cmd) {
- Connection conn = hypervisorResource.getConnection();
- String storeUrl = cmd.getDataStore();
-
- try {
- DecodedDataObject obj = Decoder.decode(storeUrl);
- DecodedDataStore store = obj.getStore();
-
- if (store.getScheme().equalsIgnoreCase("nfs")) {
- SR sr = getNfsSR(conn, store);
- } else if (store.getScheme().equalsIgnoreCase("iscsi")) {
- //getIscsiSR(conn, dataStore);
- } else if (store.getScheme().equalsIgnoreCase("presetup")) {
- } else {
- return new Answer(cmd, false, "The pool type: " + store.getScheme() + " is not supported.");
- }
- return new Answer(cmd, true, "success");
- } catch (Exception e) {
- // String msg = "Catch Exception " + e.getClass().getName() + ", create StoragePool failed due to " + e.toString() + " on host:" + _host.uuid + " pool: " + pool.getHost() + pool.getPath();
- //s_logger.warn(msg, e);
- return new Answer(cmd, false, null);
- }
- }
-
- private long getTemplateSize(Connection conn, String url) {
- String size = hypervisorResource.callHostPlugin(conn, "storagePlugin", "getTemplateSize", "srcUrl", url);
- if (size.equalsIgnoreCase("") || size == null) {
- throw new CloudRuntimeException("Can't get template size");
- }
-
- try {
- return Long.parseLong(size);
- } catch (NumberFormatException e) {
- throw new CloudRuntimeException("Failed to get template lenght", e);
- }
-
- /*
- HttpHead method = new HttpHead(url);
- DefaultHttpClient client = new DefaultHttpClient();
- try {
- HttpResponse response = client.execute(method);
- Header header = response.getFirstHeader("Content-Length");
- if (header == null) {
- throw new CloudRuntimeException("Can't get content-lenght header from :" + url);
- }
- Long length = Long.parseLong(header.getValue());
- return length;
- } catch (HttpException e) {
- throw new CloudRuntimeException("Failed to get template lenght", e);
- } catch (IOException e) {
- throw new CloudRuntimeException("Failed to get template lenght", e);
- } catch (NumberFormatException e) {
- throw new CloudRuntimeException("Failed to get template lenght", e);
- }*/
- }
-
- private void downloadHttpToLocalFile(String destFilePath, String url) {
- File destFile = new File(destFilePath);
- if (!destFile.exists()) {
- throw new CloudRuntimeException("dest file doesn't exist: " + destFilePath);
- }
-
- DefaultHttpClient client = new DefaultHttpClient();
- HttpGet getMethod = new HttpGet(url);
- HttpResponse response;
- BufferedOutputStream output = null;
- long length = 0;
- try {
- response = client.execute(getMethod);
- HttpEntity entity = response.getEntity();
- length = entity.getContentLength();
- output = new BufferedOutputStream(new FileOutputStream(destFile));
- entity.writeTo(output);
- } catch (ClientProtocolException e) {
- throw new CloudRuntimeException("Failed to download template", e);
- } catch (IOException e) {
- throw new CloudRuntimeException("Failed to download template", e);
- } finally {
- if (output != null) {
- try {
- output.close();
- } catch (IOException e) {
- throw new CloudRuntimeException("Failed to download template", e);
- }
- }
- }
-
- //double check the length
- destFile = new File(destFilePath);
- if (destFile.length() != length) {
- throw new CloudRuntimeException("Download file length doesn't match: expected: " + length + ", actual: " + destFile.length());
- }
-
- }
-
- protected Answer directDownloadHttpTemplate(CopyCommand cmd, DecodedDataObject srcObj, DecodedDataObject destObj) {
- Connection conn = hypervisorResource.getConnection();
- SR poolsr = null;
- VDI vdi = null;
- boolean result = false;
- try {
- if (destObj.getPath() == null) {
- //need to create volume at first
-
- }
- vdi = VDI.getByUuid(conn, destObj.getPath());
- if (vdi == null) {
- throw new CloudRuntimeException("can't find volume: " + destObj.getPath());
- }
- String destStoreUuid = destObj.getStore().getUuid();
- Set<SR> srs = SR.getByNameLabel(conn, destStoreUuid);
- if (srs.size() != 1) {
- throw new CloudRuntimeException("storage uuid: " + destStoreUuid + " is not unique");
- }
- poolsr = srs.iterator().next();
- VDI.Record vdir = vdi.getRecord(conn);
- String vdiLocation = vdir.location;
- String pbdLocation = null;
- if (destObj.getStore().getScheme().equalsIgnoreCase(DataStoreProtocol.NFS.toString())) {
- pbdLocation = "/run/sr-mount/" + poolsr.getUuid(conn);
- } else {
- Set<PBD> pbds = poolsr.getPBDs(conn);
- if (pbds.size() != 1) {
- throw new CloudRuntimeException("Don't how to handle multiple pbds:" + pbds.size() + " for sr: " + poolsr.getUuid(conn));
- }
- PBD pbd = pbds.iterator().next();
- Map<String, String> deviceCfg = pbd.getDeviceConfig(conn);
- pbdLocation = deviceCfg.get("location");
- }
- if (pbdLocation == null) {
- throw new CloudRuntimeException("Can't get pbd location");
- }
-
- String vdiPath = pbdLocation + "/" + vdiLocation + ".vhd";
- //download a url into vdipath
- //downloadHttpToLocalFile(vdiPath, template.getPath());
- hypervisorResource.callHostPlugin(conn, "storagePlugin", "downloadTemplateFromUrl", "destPath", vdiPath, "srcUrl", srcObj.getPath());
- result = true;
- //return new CopyCmdAnswer(cmd, vdi.getUuid(conn));
- } catch (BadServerResponse e) {
- s_logger.debug("Failed to download template", e);
- } catch (XenAPIException e) {
- s_logger.debug("Failed to download template", e);
- } catch (XmlRpcException e) {
- s_logger.debug("Failed to download template", e);
- } catch (Exception e) {
- s_logger.debug("Failed to download template", e);
- } finally {
- if (!result && vdi != null) {
- try {
- vdi.destroy(conn);
- } catch (BadServerResponse e) {
- s_logger.debug("Failed to cleanup newly created vdi");
- } catch (XenAPIException e) {
- s_logger.debug("Failed to cleanup newly created vdi");
- } catch (XmlRpcException e) {
- s_logger.debug("Failed to cleanup newly created vdi");
- }
- }
- }
- return new Answer(cmd, false, "Failed to download template");
- }
-
- protected Answer execute(AttachPrimaryDataStoreCmd cmd) {
- String dataStoreUri = cmd.getDataStore();
- Connection conn = hypervisorResource.getConnection();
- try {
- DecodedDataObject obj = Decoder.decode(dataStoreUri);
-
- DecodedDataStore store = obj.getStore();
-
- SR sr = hypervisorResource.getStorageRepository(conn, store.getUuid());
- hypervisorResource.setupHeartbeatSr(conn, sr, false);
- long capacity = sr.getPhysicalSize(conn);
- long available = capacity - sr.getPhysicalUtilisation(conn);
- if (capacity == -1) {
- String msg = "Pool capacity is -1! pool: ";
- s_logger.warn(msg);
- return new Answer(cmd, false, msg);
- }
- AttachPrimaryDataStoreAnswer answer = new AttachPrimaryDataStoreAnswer(cmd);
- answer.setCapacity(capacity);
- answer.setUuid(sr.getUuid(conn));
- answer.setAvailable(available);
- return answer;
- } catch (XenAPIException e) {
- String msg = "AttachPrimaryDataStoreCmd add XenAPIException:" + e.toString();
- s_logger.warn(msg, e);
- return new Answer(cmd, false, msg);
- } catch (Exception e) {
- String msg = "AttachPrimaryDataStoreCmd failed:" + e.getMessage();
- s_logger.warn(msg, e);
- return new Answer(cmd, false, msg);
- }
- }
-
- private boolean IsISCSI(String type) {
- return SRType.LVMOHBA.equals(type) || SRType.LVMOISCSI.equals(type) || SRType.LVM.equals(type) ;
- }
-
- private String copy_vhd_from_secondarystorage(Connection conn, String mountpoint, String sruuid, int wait) {
- String nameLabel = "cloud-" + UUID.randomUUID().toString();
- String results = hypervisorResource.callHostPluginAsync(conn, "vmopspremium", "copy_vhd_from_secondarystorage",
- wait, "mountpoint", mountpoint, "sruuid", sruuid, "namelabel", nameLabel);
- String errMsg = null;
- if (results == null || results.isEmpty()) {
- errMsg = "copy_vhd_from_secondarystorage return null";
- } else {
- String[] tmp = results.split("#");
- String status = tmp[0];
- if (status.equals("0")) {
- return tmp[1];
- } else {
- errMsg = tmp[1];
- }
- }
- String source = mountpoint.substring(mountpoint.lastIndexOf('/') + 1);
- if( hypervisorResource.killCopyProcess(conn, source) ) {
- destroyVDIbyNameLabel(conn, nameLabel);
- }
- s_logger.warn(errMsg);
- throw new CloudRuntimeException(errMsg);
- }
-
- private void destroyVDIbyNameLabel(Connection conn, String nameLabel) {
- try {
- Set<VDI> vdis = VDI.getByNameLabel(conn, nameLabel);
- if ( vdis.size() != 1 ) {
- s_logger.warn("destoryVDIbyNameLabel failed due to there are " + vdis.size() + " VDIs with name " + nameLabel);
- return;
- }
- for (VDI vdi : vdis) {
- try {
- vdi.destroy(conn);
- } catch (Exception e) {
- }
- }
- } catch (Exception e){
- }
- }
-
- protected VDI getVDIbyUuid(Connection conn, String uuid) {
- try {
- return VDI.getByUuid(conn, uuid);
- } catch (Exception e) {
- String msg = "Catch Exception " + e.getClass().getName() + " :VDI getByUuid for uuid: " + uuid + " failed due to " + e.toString();
- s_logger.debug(msg);
- throw new CloudRuntimeException(msg, e);
- }
- }
-
- protected String getVhdParent(Connection conn, String primaryStorageSRUuid, String snapshotUuid, Boolean isISCSI) {
- String parentUuid = hypervisorResource.callHostPlugin(conn, "vmopsSnapshot", "getVhdParent", "primaryStorageSRUuid", primaryStorageSRUuid,
- "snapshotUuid", snapshotUuid, "isISCSI", isISCSI.toString());
-
- if (parentUuid == null || parentUuid.isEmpty() || parentUuid.equalsIgnoreCase("None")) {
- s_logger.debug("Unable to get parent of VHD " + snapshotUuid + " in SR " + primaryStorageSRUuid);
- // errString is already logged.
- return null;
- }
- return parentUuid;
- }
-
- protected CopyCmdAnswer copyTemplateToPrimaryStorage(DataTO srcData, DataTO destData, int wait) {
- DataStoreTO srcStore = srcData.getDataStore();
- try {
- if ((srcStore instanceof NfsTO) && (srcData.getObjectType() == DataObjectType.TEMPLATE)) {
- NfsTO srcImageStore = (NfsTO)srcStore;
- TemplateObjectTO srcTemplate = (TemplateObjectTO)srcData;
- String storeUrl = srcImageStore.getUrl();
-
- URI uri = new URI(storeUrl);
- String tmplpath = uri.getHost() + ":" + uri.getPath() + "/" + srcData.getPath();
- PrimaryDataStoreTO destStore = (PrimaryDataStoreTO)destData.getDataStore();
- String poolName = destStore.getUuid();
- Connection conn = hypervisorResource.getConnection();
-
- SR poolsr = null;
- Set<SR> srs = SR.getByNameLabel(conn, poolName);
- if (srs.size() != 1) {
- String msg = "There are " + srs.size() + " SRs with same name: " + poolName;
- s_logger.warn(msg);
- return new CopyCmdAnswer(msg);
- } else {
- poolsr = srs.iterator().next();
- }
- String pUuid = poolsr.getUuid(conn);
- boolean isISCSI = IsISCSI(poolsr.getType(conn));
- String uuid = copy_vhd_from_secondarystorage(conn, tmplpath, pUuid, wait);
- VDI tmpl = getVDIbyUuid(conn, uuid);
- VDI snapshotvdi = tmpl.snapshot(conn, new HashMap<String, String>());
- String snapshotUuid = snapshotvdi.getUuid(conn);
- snapshotvdi.setNameLabel(conn, "Template " + srcTemplate.getName());
- String parentuuid = getVhdParent(conn, pUuid, snapshotUuid, isISCSI);
- VDI parent = getVDIbyUuid(conn, parentuuid);
- Long phySize = parent.getPhysicalUtilisation(conn);
- tmpl.destroy(conn);
- poolsr.scan(conn);
- try{
- Thread.sleep(5000);
- } catch (Exception e) {
- }
-
- TemplateObjectTO newVol = new TemplateObjectTO();
- newVol.setUuid(snapshotvdi.getUuid(conn));
- newVol.setPath(newVol.getUuid());
- return new CopyCmdAnswer(newVol);
- }
- }catch (Exception e) {
- String msg = "Catch Exception " + e.getClass().getName() + " for template + " + " due to " + e.toString();
- s_logger.warn(msg, e);
- return new CopyCmdAnswer(msg);
- }
- return new CopyCmdAnswer("not implemented yet");
- }
-
- protected CreateObjectAnswer createVolume(DataTO data) throws BadServerResponse, XenAPIException, XmlRpcException {
- VolumeObjectTO volume = (VolumeObjectTO)data;
-
- Connection conn = hypervisorResource.getConnection();
- PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)data.getDataStore();
- SR poolSr = hypervisorResource.getStorageRepository(conn, primaryStore.getUuid());
- VDI.Record vdir = new VDI.Record();
- vdir.nameLabel = volume.getName();
- vdir.SR = poolSr;
- vdir.type = Types.VdiType.USER;
-
- vdir.virtualSize = volume.getSize();
- VDI vdi;
-
- vdi = VDI.create(conn, vdir);
- vdir = vdi.getRecord(conn);
- VolumeObjectTO newVol = new VolumeObjectTO();
- newVol.setName(vdir.nameLabel);
- newVol.setSize(vdir.virtualSize);
- newVol.setPath(vdir.uuid);
-
- return new CreateObjectAnswer(newVol);
- }
-
- protected CopyCmdAnswer cloneVolumeFromBaseTemplate(DataTO srcData, DataTO destData) {
- Connection conn = hypervisorResource.getConnection();
- PrimaryDataStoreTO pool = (PrimaryDataStoreTO)destData.getDataStore();
- VolumeObjectTO volume = (VolumeObjectTO)destData;
- VDI vdi = null;
- try {
- VDI tmpltvdi = null;
-
- tmpltvdi = getVDIbyUuid(conn, srcData.getPath());
- vdi = tmpltvdi.createClone(conn, new HashMap<String, String>());
- vdi.setNameLabel(conn, volume.getName());
-
-
- VDI.Record vdir;
- vdir = vdi.getRecord(conn);
- s_logger.debug("Succesfully created VDI: Uuid = " + vdir.uuid);
-
- VolumeObjectTO newVol = new VolumeObjectTO();
- newVol.setName(vdir.nameLabel);
- newVol.setSize(vdir.virtualSize);
- newVol.setPath(vdir.uuid);
-
- return new CopyCmdAnswer(newVol);
- } catch (Exception e) {
- s_logger.warn("Unable to create volume; Pool=" + pool + "; Disk: ", e);
- return new CopyCmdAnswer(e.toString());
- }
- }
-
-
- protected Answer copyVolumeFromImageCacheToPrimary(DataTO srcData, DataTO destData, int wait) {
- Connection conn = hypervisorResource.getConnection();
- VolumeObjectTO srcVolume = (VolumeObjectTO)srcData;
- VolumeObjectTO destVolume = (VolumeObjectTO)destData;
- PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)destVolume.getDataStore();
- DataStoreTO srcStore = srcVolume.getDataStore();
-
- if (srcStore instanceof NfsTO) {
- NfsTO nfsStore = (NfsTO)srcStore;
- try {
- SR primaryStoragePool = hypervisorResource.getStorageRepository(conn, primaryStore.getUuid());
- String srUuid = primaryStoragePool.getUuid(conn);
- String volumePath = nfsStore.getUrl() + ":" + srcVolume.getPath();
- String uuid = copy_vhd_from_secondarystorage(conn, volumePath, srUuid, wait );
- VolumeObjectTO newVol = new VolumeObjectTO();
- newVol.setPath(uuid);
- newVol.setSize(srcVolume.getSize());
-
- return new CopyCmdAnswer(newVol);
- } catch (Exception e) {
- String msg = "Catch Exception " + e.getClass().getName() + " due to " + e.toString();
- s_logger.warn(msg, e);
- return new CopyCmdAnswer(e.toString());
- }
- }
-
- s_logger.debug("unsupported protocol");
- return new CopyCmdAnswer("unsupported protocol");
- }
-
- protected Answer copyVolumeFromPrimaryToSecondary(DataTO srcData, DataTO destData, int wait) {
- Connection conn = hypervisorResource.getConnection();
- VolumeObjectTO srcVolume = (VolumeObjectTO)srcData;
- VolumeObjectTO destVolume = (VolumeObjectTO)destData;
- DataStoreTO destStore = destVolume.getDataStore();
-
- if (destStore instanceof NfsTO) {
- SR secondaryStorage = null;
- try {
- NfsTO nfsStore = (NfsTO)destStore;
- URI uri = new URI(nfsStore.getUrl());
- // Create the volume folder
- if (!hypervisorResource.createSecondaryStorageFolder(conn, uri.getHost() + ":" + uri.getPath(), destVolume.getPath())) {
- throw new InternalErrorException("Failed to create the volume folder.");
- }
-
- // Create a SR for the volume UUID folder
- secondaryStorage = hypervisorResource.createNfsSRbyURI(conn, new URI(nfsStore.getUrl() + destVolume.getPath()), false);
- // Look up the volume on the source primary storage pool
- VDI srcVdi = getVDIbyUuid(conn, srcVolume.getPath());
- // Copy the volume to secondary storage
- VDI destVdi = hypervisorResource.cloudVDIcopy(conn, srcVdi, secondaryStorage, wait);
- String destVolumeUUID = destVdi.getUuid(conn);
-
- VolumeObjectTO newVol = new VolumeObjectTO();
- newVol.setPath(destVolumeUUID);
- newVol.setSize(srcVolume.getSize());
- return new CopyCmdAnswer(newVol);
- } catch (Exception e) {
- s_logger.debug("Failed to copy volume to secondary: " + e.toString());
- return new CopyCmdAnswer("Failed to copy volume to secondary: " + e.toString());
- } finally {
- hypervisorResource.removeSR(conn, secondaryStorage);
- }
- }
- return new CopyCmdAnswer("unsupported protocol");
- }
-
- boolean swiftUpload(Connection conn, SwiftTO swift, String container, String ldir, String lfilename, Boolean isISCSI, int wait) {
- String result = null;
- try {
- result = hypervisorResource.callHostPluginAsync(conn, "swiftxen", "swift", wait,
- "op", "upload", "url", swift.getUrl(), "account", swift.getAccount(),
- "username", swift.getUserName(), "key", swift.getKey(), "container", container,
- "ldir", ldir, "lfilename", lfilename, "isISCSI", isISCSI.toString());
- if( result != null && result.equals("true")) {
- return true;
- }
- } catch (Exception e) {
- s_logger.warn("swift upload failed due to " + e.toString(), e);
- }
- return false;
- }
-
- protected String deleteSnapshotBackup(Connection conn, String path, String secondaryStorageMountPath, String backupUUID) {
-
- // If anybody modifies the formatting below again, I'll skin them
- String result = hypervisorResource.callHostPlugin(conn, "vmopsSnapshot", "deleteSnapshotBackup", "backupUUID", backupUUID, "path", path, "secondaryStorageMountPath", secondaryStorageMountPath);
-
- return result;
- }
-
- public void swiftBackupSnapshot(Connection conn, SwiftTO swift, String srUuid, String snapshotUuid, String container, Boolean isISCSI, int wait) {
- String lfilename;
- String ldir;
- if ( isISCSI ) {
- ldir = "/dev/VG_XenStorage-" + srUuid;
- lfilename = "VHD-" + snapshotUuid;
- } else {
- ldir = "/var/run/sr-mount/" + srUuid;
- lfilename = snapshotUuid + ".vhd";
- }
- swiftUpload(conn, swift, container, ldir, lfilename, isISCSI, wait);
- }
-
- private static List<String> serializeProperties(final Object object,
- final Class<?> propertySet) {
-
- assert object != null;
- assert propertySet != null;
- assert propertySet.isAssignableFrom(object.getClass());
-
- try {
-
- final BeanInfo beanInfo = Introspector.getBeanInfo(propertySet);
- final PropertyDescriptor[] descriptors = beanInfo
- .getPropertyDescriptors();
-
- final List<String> serializedProperties = new ArrayList<String>();
- for (final PropertyDescriptor descriptor : descriptors) {
-
- serializedProperties.add(descriptor.getName());
- final Object value = descriptor.getReadMethod().invoke(object);
- serializedProperties.add(value != null ? value.toString()
- : "null");
-
- }
-
- return Collections.unmodifiableList(serializedProperties);
-
- } catch (IntrospectionException e) {
- s_logger.warn(
- "Ignored IntrospectionException when serializing class "
- + object.getClass().getCanonicalName(), e);
- } catch (IllegalArgumentException e) {
- s_logger.warn(
- "Ignored IllegalArgumentException when serializing class "
- + object.getClass().getCanonicalName(), e);
- } catch (IllegalAccessException e) {
- s_logger.warn(
- "Ignored IllegalAccessException when serializing class "
- + object.getClass().getCanonicalName(), e);
- } catch (InvocationTargetException e) {
- s_logger.warn(
- "Ignored InvocationTargetException when serializing class "
- + object.getClass().getCanonicalName(), e);
- }
-
- return Collections.emptyList();
-
- }
-
- private boolean backupSnapshotToS3(final Connection connection,
- final S3TO s3, final String srUuid, final String snapshotUuid,
- final Boolean iSCSIFlag, final int wait) {
-
- final String filename = iSCSIFlag ? "VHD-" + snapshotUuid
- : snapshotUuid + ".vhd";
- final String dir = (iSCSIFlag ? "/dev/VG_XenStorage-"
- : "/var/run/sr-mount/") + srUuid;
- final String key = StringUtils.join("/", "snapshots", snapshotUuid);
-
- try {
-
- final List<String> parameters = new ArrayList<String>(
- serializeProperties(s3, S3Utils.ClientOptions.class));
- parameters.addAll(Arrays.asList("operation", "put", "directory",
- dir, "filename", filename, "iSCSIFlag",
- iSCSIFlag.toString(), "key", key));
- final String result = hypervisorResource.callHostPluginAsync(connection, "s3xen",
- "s3", wait,
- parameters.toArray(new String[parameters.size()]));
-
- if (result != null && result.equals("true")) {
- return true;
- }
-
- } catch (Exception e) {
- s_logger.error(String.format(
- "S3 upload failed of snapshot %1$s due to %2$s.",
- snapshotUuid, e.toString()), e);
- }
-
- return false;
-
- }
-
- protected String backupSnapshot(Connection conn, String primaryStorageSRUuid, String path, String secondaryStorageMountPath, String snapshotUuid, String prevBackupUuid, Boolean isISCSI, int wait) {
- String backupSnapshotUuid = null;
-
- if (prevBackupUuid == null) {
- prevBackupUuid = "";
- }
-
- // Each argument is put in a separate line for readability.
- // Using more lines does not harm the environment.
- String backupUuid = UUID.randomUUID().toString();
- String results = hypervisorResource.callHostPluginAsync(conn, "vmopsSnapshot", "backupSnapshot", wait,
- "primaryStorageSRUuid", primaryStorageSRUuid, "path", path, "secondaryStorageMountPath", secondaryStorageMountPath,
- "snapshotUuid", snapshotUuid, "prevBackupUuid", prevBackupUuid, "backupUuid", backupUuid, "isISCSI", isISCSI.toString());
- String errMsg = null;
- if (results == null || results.isEmpty()) {
- errMsg = "Could not copy backupUuid: " + backupSnapshotUuid
- + " from primary storage " + primaryStorageSRUuid + " to secondary storage "
- + secondaryStorageMountPath + " due to null";
- } else {
-
- String[] tmp = results.split("#");
- String status = tmp[0];
- backupSnapshotUuid = tmp[1];
- // status == "1" if and only if backupSnapshotUuid != null
- // So we don't rely on status value but return backupSnapshotUuid as an
- // indicator of success.
- if (status != null && status.equalsIgnoreCase("1") && backupSnapshotUuid != null) {
- s_logger.debug("Successfully copied backupUuid: " + backupSnapshotUuid
- + " to secondary storage");
- return backupSnapshotUuid;
- } else {
- errMsg = "Could not copy backupUuid: " + backupSnapshotUuid
- + " from primary storage " + primaryStorageSRUuid + " to secondary storage "
- + secondaryStorageMountPath + " due to " + tmp[1];
- }
- }
- String source = backupUuid + ".vhd";
- hypervisorResource.killCopyProcess(conn, source);
- s_logger.warn(errMsg);
- return null;
-
- }
-
- private boolean destroySnapshotOnPrimaryStorageExceptThis(Connection conn, String volumeUuid, String avoidSnapshotUuid){
- try {
- VDI volume = getVDIbyUuid(conn, volumeUuid);
- if (volume == null) {
- throw new InternalErrorException("Could not destroy snapshot on volume " + volumeUuid + " due to can not find it");
- }
- Set<VDI> snapshots = volume.getSnapshots(conn);
- for( VDI snapshot : snapshots ) {
- try {
- if(! snapshot.getUuid(conn).equals(avoidSnapshotUuid)) {
- snapshot.destroy(conn);
- }
- } catch (Exception e) {
- String msg = "Destroying snapshot: " + snapshot+ " on primary storage failed due to " + e.toString();
- s_logger.warn(msg, e);
- }
- }
- s_logger.debug("Successfully destroyed snapshot on volume: " + volumeUuid + " execept this current snapshot "+ avoidSnapshotUuid );
- return true;
- } catch (XenAPIException e) {
- String msg = "Destroying snapshot on volume: " + volumeUuid + " execept this current snapshot "+ avoidSnapshotUuid + " failed due to " + e.toString();
- s_logger.error(msg, e);
- } catch (Exception e) {
- String msg = "Destroying snapshot on volume: " + volumeUuid + " execept this current snapshot "+ avoidSnapshotUuid + " failed due to " + e.toString();
- s_logger.warn(msg, e);
- }
-
- return false;
- }
-
- protected Answer backupSnasphot(DataTO srcData, DataTO destData, DataTO cacheData, int wait) {
- Connection conn = hypervisorResource.getConnection();
- PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)srcData.getDataStore();
- String primaryStorageNameLabel = primaryStore.getUuid();
- String secondaryStorageUrl = null;
- NfsTO cacheStore = null;
- String destPath = null;
- if (cacheData != null) {
- cacheStore = (NfsTO)cacheData.getDataStore();
- secondaryStorageUrl = cacheStore.getUrl();
- destPath = cacheData.getPath();
- } else {
- cacheStore = (NfsTO)destData.getDataStore();
- secondaryStorageUrl = cacheStore.getUrl();
- destPath = destData.getPath();
- }
-
- SnapshotObjectTO snapshotTO = (SnapshotObjectTO)srcData;
- SnapshotObjectTO snapshotOnImage = (SnapshotObjectTO)destData;
- String snapshotUuid = snapshotTO.getPath();
-
- String prevBackupUuid = snapshotOnImage.getParentSnapshotPath();
- String prevSnapshotUuid = snapshotTO.getParentSnapshotPath();
-
- // By default assume failure
- String details = null;
- String snapshotBackupUuid = null;
- boolean fullbackup = true;
- try {
- SR primaryStorageSR = hypervisorResource.getSRByNameLabelandHost(conn, primaryStorageNameLabel);
- if (primaryStorageSR == null) {
- throw new InternalErrorException("Could not backup snapshot because the primary Storage SR could not be created from the name label: " + primaryStorageNameLabel);
- }
- String psUuid = primaryStorageSR.getUuid(conn);
- Boolean isISCSI = IsISCSI(primaryStorageSR.getType(conn));
-
- VDI snapshotVdi = getVDIbyUuid(conn, snapshotUuid);
- String snapshotPaUuid = null;
- if ( prevBackupUuid != null ) {
- try {
- snapshotPaUuid = getVhdParent(conn, psUuid, snapshotUuid, isISCSI);
- if( snapshotPaUuid != null ) {
- String snashotPaPaPaUuid = getVhdParent(conn, psUuid, snapshotPaUuid, isISCSI);
- String prevSnashotPaUuid = getVhdParent(conn, psUuid, prevSnapshotUuid, isISCSI);
- if (snashotPaPaPaUuid != null && prevSnashotPaUuid!= null && prevSnashotPaUuid.equals(snashotPaPaPaUuid)) {
- fullbackup = false;
- }
- }
- } catch (Exception e) {
- }
- }
-
- URI uri = new URI(secondaryStorageUrl);
- String secondaryStorageMountPath = uri.getHost() + ":" + uri.getPath();
- DataStoreTO destStore = destData.getDataStore();
- String folder = destPath;
- if (fullbackup) {
- // the first snapshot is always a full snapshot
-
- if( !hypervisorResource.createSecondaryStorageFolder(conn, secondaryStorageMountPath, folder)) {
- details = " Filed to create folder " + folder + " in secondary storage";
- s_logger.warn(details);
- return new CopyCmdAnswer(details);
- }
- String snapshotMountpoint = secondaryStorageUrl + "/" + folder;
- SR snapshotSr = null;
- try {
- snapshotSr = hypervisorResource.createNfsSRbyURI(conn, new URI(snapshotMountpoint), false);
- VDI backedVdi = hypervisorResource.cloudVDIcopy(conn, snapshotVdi, snapshotSr, wait);
- snapshotBackupUuid = backedVdi.getUuid(conn);
-
- if( destStore instanceof SwiftTO) {
- try {
- hypervisorResource.swiftBackupSnapshot(conn, (SwiftTO)destStore, snapshotSr.getUuid(conn), snapshotBackupUuid, "S-" + snapshotTO.getVolume().getVolumeId().toString(), false, wait);
- snapshotBackupUuid = snapshotBackupUuid + ".vhd";
- } finally {
- deleteSnapshotBackup(conn, folder, secondaryStorageMountPath, snapshotBackupUuid);
- }
- } else if (destStore instanceof S3TO) {
- try {
- backupSnapshotToS3(conn, (S3TO)destStore, snapshotSr.getUuid(conn), snapshotBackupUuid, isISCSI, wait);
- snapshotBackupUuid = snapshotBackupUuid + ".vhd";
- } finally {
- deleteSnapshotBackup(conn, folder, secondaryStorageMountPath, snapshotBackupUuid);
- }
- }
-
- } finally {
- if( snapshotSr != null) {
- hypervisorResource.removeSR(conn, snapshotSr);
- }
- }
- } else {
- String primaryStorageSRUuid = primaryStorageSR.getUuid(conn);
- if( destStore instanceof SwiftTO ) {
- swiftBackupSnapshot(conn, (SwiftTO)destStore, primaryStorageSRUuid, snapshotPaUuid, "S-" + snapshotTO.getVolume().getVolumeId().toString(), isISCSI, wait);
- if ( isISCSI ) {
- snapshotBackupUuid = "VHD-" + snapshotPaUuid;
- } else {
- snapshotBackupUuid = snapshotPaUuid + ".vhd";
- }
-
- } else if (destStore instanceof S3TO ) {
- backupSnapshotToS3(conn, (S3TO)destStore, primaryStorageSRUuid, snapshotPaUuid, isISCSI, wait);
- } else {
- snapshotBackupUuid = backupSnapshot(conn, primaryStorageSRUuid, folder + File.separator + UUID.nameUUIDFromBytes(secondaryStorageMountPath.getBytes())
- , secondaryStorageMountPath, snapshotUuid, prevBackupUuid, isISCSI, wait);
-
- }
- }
- String volumeUuid = snapshotTO.getVolume().getPath();
- destroySnapshotOnPrimaryStorageExceptThis(conn, volumeUuid, snapshotUuid);
-
- SnapshotObjectTO newSnapshot = new SnapshotObjectTO();
- newSnapshot.setPath(folder + File.separator + snapshotBackupUuid);
- if (fullbackup) {
- newSnapshot.setParentSnapshotPath(null);
- } else {
- newSnapshot.setParentSnapshotPath(prevBackupUuid);
- }
- return new CopyCmdAnswer(newSnapshot);
- } catch (XenAPIException e) {
- details = "BackupSnapshot Failed due to " + e.toString();
- s_logger.warn(details, e);
- } catch (Exception e) {
- details = "BackupSnapshot Failed due to " + e.getMessage();
- s_logger.warn(details, e);
- }
-
- return new CopyCmdAnswer(details);
- }
-
- protected CopyCmdAnswer createTemplateFromVolume(DataTO srcData, DataTO destData, int wait) {
- Connection conn = this.hypervisorResource.getConnection();
- VolumeObjectTO volume = (VolumeObjectTO)srcData;
- TemplateObjectTO template = (TemplateObjectTO)destData;
- NfsTO destStore = (NfsTO)destData.getDataStore();
-
- String secondaryStoragePoolURL = destStore.getUrl();
- String volumeUUID = volume.getPath();
-
- String userSpecifiedName = template.getName();
-
-
- String details = null;
- SR tmpltSR = null;
- boolean result = false;
- String secondaryStorageMountPath = null;
- String installPath = null;
- try {
- URI uri = new URI(secondaryStoragePoolURL);
- secondaryStorageMountPath = uri.getHost() + ":" + uri.getPath();
- installPath = template.getPath();
- if( !this.hypervisorResource.createSecondaryStorageFolder(conn, secondaryStorageMountPath, installPath)) {
- details = " Filed to create folder " + installPath + " in secondary storage";
- s_logger.warn(details);
- return new CopyCmdAnswer(details);
- }
-
- VDI vol = getVDIbyUuid(conn, volumeUUID);
- // create template SR
- URI tmpltURI = new URI(secondaryStoragePoolURL + "/" + installPath);
- tmpltSR = this.hypervisorResource.createNfsSRbyURI(conn, tmpltURI, false);
-
- // copy volume to template SR
- VDI tmpltVDI = this.hypervisorResource.cloudVDIcopy(conn, vol, tmpltSR, wait);
- // scan makes XenServer pick up VDI physicalSize
- tmpltSR.scan(conn);
- if (userSpecifiedName != null) {
- tmpltVDI.setNameLabel(conn, userSpecifiedName);
- }
-
- String tmpltUUID = tmpltVDI.getUuid(conn);
- String tmpltFilename = tmpltUUID + ".vhd";
- long virtualSize = tmpltVDI.getVirtualSize(conn);
- long physicalSize = tmpltVDI.getPhysicalUtilisation(conn);
- // create the template.properties file
- String templatePath = secondaryStorageMountPath + "/" + installPath;
- result = this.hypervisorResource.postCreatePrivateTemplate(conn, templatePath, tmpltFilename, tmpltUUID, userSpecifiedName, null, physicalSize, virtualSize, template.getId());
- if (!result) {
- throw new CloudRuntimeException("Could not create the template.properties file on secondary storage dir: " + tmpltURI);
- }
- installPath = installPath + "/" + tmpltFilename;
- this.hypervisorResource.removeSR(conn, tmpltSR);
- tmpltSR = null;
- TemplateObjectTO newTemplate = new TemplateObjectTO();
- newTemplate.setPath(installPath);
- newTemplate.setFormat(ImageFormat.VHD);
- CopyCmdAnswer answer = new CopyCmdAnswer(newTemplate);
- return answer;
- } catch (Exception e) {
- if (tmpltSR != null) {
- this.hypervisorResource.removeSR(conn, tmpltSR);
- }
- if ( secondaryStorageMountPath != null) {
- this.hypervisorResource.deleteSecondaryStorageFolder(conn, secondaryStorageMountPath, installPath);
- }
- details = "Creating template from volume " + volumeUUID + " failed due to " + e.toString();
- s_logger.error(details, e);
- }
- return new CopyCmdAnswer(details);
- }
-
- protected Answer execute(CopyCommand cmd) {
- DataTO srcData = cmd.getSrcTO();
- DataTO destData = cmd.getDestTO();
- DataStoreTO srcDataStore = srcData.getDataStore();
- DataStoreTO destDataStore = destData.getDataStore();
- DataObjectType srcType = srcData.getObjectType();
- DataObjectType destType = destData.getObjectType();
- DataStoreRole destRole = destDataStore.getRole();
-
- boolean nfs = (srcDataStore instanceof NfsTO) ? true : false;
-
- if ((srcData.getObjectType() == DataObjectType.TEMPLATE) && (srcDataStore instanceof NfsTO) && (destData.getDataStore().getRole() == DataStoreRole.Primary)) {
- //copy template to primary storage
- return copyTemplateToPrimaryStorage(srcData, destData, cmd.getWait());
- } else if (srcData.getObjectType() == DataObjectType.TEMPLATE && srcDataStore.getRole() == DataStoreRole.Primary && destDataStore.getRole() == DataStoreRole.Primary) {
- //clone template to a volume
- return cloneVolumeFromBaseTemplate(srcData, destData);
- } else if (srcData.getObjectType() == DataObjectType.VOLUME && (srcData.getDataStore().getRole() == DataStoreRole.ImageCache || srcDataStore.getRole() == DataStoreRole.Image)) {
- //copy volume from image cache to primary
- return copyVolumeFromImageCacheToPrimary(srcData, destData, cmd.getWait());
- } else if (srcData.getObjectType() == DataObjectType.VOLUME && srcData.getDataStore().getRole() == DataStoreRole.Primary) {
- if (destData.getObjectType() == DataObjectType.VOLUME) {
- return copyVolumeFromPrimaryToSecondary(srcData, destData, cmd.getWait());
- } else if (destData.getObjectType() == DataObjectType.TEMPLATE) {
- return createTemplateFromVolume(srcData, destData, cmd.getWait());
- }
- } else if (srcData.getObjectType() == DataObjectType.SNAPSHOT && srcData.getDataStore().getRole() == DataStoreRole.Primary) {
- DataTO cacheData = cmd.getCacheTO();
- return backupSnasphot(srcData, destData, cacheData, cmd.getWait());
- }
-
- return new Answer(cmd, false, "not implemented yet");
- }
-}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/42e25a22/plugins/storage/image/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackImageStoreDriverImpl.java
----------------------------------------------------------------------
diff --git a/plugins/storage/image/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackImageStoreDriverImpl.java b/plugins/storage/image/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackImageStoreDriverImpl.java
index 1865068..52f8d9c 100644
--- a/plugins/storage/image/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackImageStoreDriverImpl.java
+++ b/plugins/storage/image/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackImageStoreDriverImpl.java
@@ -27,10 +27,8 @@ import javax.inject.Inject;
import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult;
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
-import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
-import org.apache.cloudstack.engine.subsystem.api.storage.DataTO;
import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint;
import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector;
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
@@ -53,7 +51,9 @@ import com.cloud.agent.api.Answer;
import com.cloud.agent.api.storage.DeleteTemplateCommand;
import com.cloud.agent.api.storage.DeleteVolumeCommand;
import com.cloud.agent.api.storage.DownloadAnswer;
+import com.cloud.agent.api.to.DataObjectType;
import com.cloud.agent.api.to.DataStoreTO;
+import com.cloud.agent.api.to.DataTO;
import com.cloud.agent.api.to.NfsTO;
import com.cloud.event.EventTypes;
import com.cloud.event.UsageEventUtils;
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/42e25a22/plugins/storage/image/s3/src/org/apache/cloudstack/storage/datastore/driver/S3ImageStoreDriverImpl.java
----------------------------------------------------------------------
diff --git a/plugins/storage/image/s3/src/org/apache/cloudstack/storage/datastore/driver/S3ImageStoreDriverImpl.java b/plugins/storage/image/s3/src/org/apache/cloudstack/storage/datastore/driver/S3ImageStoreDriverImpl.java
index 354151e..1992c5e 100644
--- a/plugins/storage/image/s3/src/org/apache/cloudstack/storage/datastore/driver/S3ImageStoreDriverImpl.java
+++ b/plugins/storage/image/s3/src/org/apache/cloudstack/storage/datastore/driver/S3ImageStoreDriverImpl.java
@@ -29,10 +29,8 @@ import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult;
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
-import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
-import org.apache.cloudstack.engine.subsystem.api.storage.DataTO;
import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint;
import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector;
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
@@ -57,7 +55,9 @@ import com.cloud.agent.api.DeleteSnapshotBackupCommand;
import com.cloud.agent.api.storage.DeleteTemplateCommand;
import com.cloud.agent.api.storage.DeleteVolumeCommand;
import com.cloud.agent.api.storage.DownloadAnswer;
+import com.cloud.agent.api.to.DataObjectType;
import com.cloud.agent.api.to.DataStoreTO;
+import com.cloud.agent.api.to.DataTO;
import com.cloud.agent.api.to.S3TO;
import com.cloud.event.EventTypes;
import com.cloud.event.UsageEventUtils;
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/42e25a22/plugins/storage/image/sample/src/org/apache/cloudstack/storage/datastore/driver/SampleImageStoreDriverImpl.java
----------------------------------------------------------------------
diff --git a/plugins/storage/image/sample/src/org/apache/cloudstack/storage/datastore/driver/SampleImageStoreDriverImpl.java b/plugins/storage/image/sample/src/org/apache/cloudstack/storage/datastore/driver/SampleImageStoreDriverImpl.java
index 72864c3..2c7ba11 100644
--- a/plugins/storage/image/sample/src/org/apache/cloudstack/storage/datastore/driver/SampleImageStoreDriverImpl.java
+++ b/plugins/storage/image/sample/src/org/apache/cloudstack/storage/datastore/driver/SampleImageStoreDriverImpl.java
@@ -25,9 +25,7 @@ import javax.inject.Inject;
import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult;
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
-import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
-import org.apache.cloudstack.engine.subsystem.api.storage.DataTO;
import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint;
import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector;
import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
@@ -36,7 +34,9 @@ import org.apache.cloudstack.storage.command.CreateObjectAnswer;
import org.apache.cloudstack.storage.command.CreateObjectCommand;
import org.apache.cloudstack.storage.image.ImageStoreDriver;
+import com.cloud.agent.api.to.DataObjectType;
import com.cloud.agent.api.to.DataStoreTO;
+import com.cloud.agent.api.to.DataTO;
import com.cloud.storage.dao.VMTemplateDao;
//http-read-only based image store
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/42e25a22/plugins/storage/image/swift/src/org/apache/cloudstack/storage/datastore/driver/SwiftImageStoreDriverImpl.java
----------------------------------------------------------------------
diff --git a/plugins/storage/image/swift/src/org/apache/cloudstack/storage/datastore/driver/SwiftImageStoreDriverImpl.java b/plugins/storage/image/swift/src/org/apache/cloudstack/storage/datastore/driver/SwiftImageStoreDriverImpl.java
index 0eb3acf..82df043 100644
--- a/plugins/storage/image/swift/src/org/apache/cloudstack/storage/datastore/driver/SwiftImageStoreDriverImpl.java
+++ b/plugins/storage/image/swift/src/org/apache/cloudstack/storage/datastore/driver/SwiftImageStoreDriverImpl.java
@@ -29,10 +29,8 @@ import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult;
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
-import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
-import org.apache.cloudstack.engine.subsystem.api.storage.DataTO;
import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint;
import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector;
import org.apache.cloudstack.framework.async.AsyncCallbackDispatcher;
@@ -56,7 +54,9 @@ import com.cloud.agent.api.DeleteSnapshotBackupCommand;
import com.cloud.agent.api.storage.DeleteTemplateCommand;
import com.cloud.agent.api.storage.DeleteVolumeCommand;
import com.cloud.agent.api.storage.DownloadAnswer;
+import com.cloud.agent.api.to.DataObjectType;
import com.cloud.agent.api.to.DataStoreTO;
+import com.cloud.agent.api.to.DataTO;
import com.cloud.agent.api.to.SwiftTO;
import com.cloud.event.EventTypes;
import com.cloud.event.UsageEventUtils;
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/42e25a22/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java
----------------------------------------------------------------------
diff --git a/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java b/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java
index 912a11e..aad1769 100644
--- a/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java
+++ b/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java
@@ -25,9 +25,7 @@ import javax.inject.Inject;
import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult;
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
-import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
-import org.apache.cloudstack.engine.subsystem.api.storage.DataTO;
import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint;
import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector;
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreDriver;
@@ -50,7 +48,9 @@ import com.cloud.agent.api.storage.CreateCommand;
import com.cloud.agent.api.storage.DestroyCommand;
import com.cloud.agent.api.storage.ResizeVolumeAnswer;
import com.cloud.agent.api.storage.ResizeVolumeCommand;
+import com.cloud.agent.api.to.DataObjectType;
import com.cloud.agent.api.to.DataStoreTO;
+import com.cloud.agent.api.to.DataTO;
import com.cloud.agent.api.to.StorageFilerTO;
import com.cloud.exception.StorageUnavailableException;
import com.cloud.host.dao.HostDao;
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/42e25a22/plugins/storage/volume/sample/src/org/apache/cloudstack/storage/datastore/driver/SamplePrimaryDataStoreDriverImpl.java
----------------------------------------------------------------------
diff --git a/plugins/storage/volume/sample/src/org/apache/cloudstack/storage/datastore/driver/SamplePrimaryDataStoreDriverImpl.java b/plugins/storage/volume/sample/src/org/apache/cloudstack/storage/datastore/driver/SamplePrimaryDataStoreDriverImpl.java
index f530362..b3a83f7 100644
--- a/plugins/storage/volume/sample/src/org/apache/cloudstack/storage/datastore/driver/SamplePrimaryDataStoreDriverImpl.java
+++ b/plugins/storage/volume/sample/src/org/apache/cloudstack/storage/datastore/driver/SamplePrimaryDataStoreDriverImpl.java
@@ -25,7 +25,6 @@ import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult;
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
-import org.apache.cloudstack.engine.subsystem.api.storage.DataTO;
import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint;
import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector;
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreDriver;
@@ -42,6 +41,7 @@ import org.apache.log4j.Logger;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.to.DataStoreTO;
+import com.cloud.agent.api.to.DataTO;
import com.cloud.storage.dao.StoragePoolHostDao;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.storage.encoding.DecodedDataObject;
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/42e25a22/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/driver/SolidfirePrimaryDataStoreDriver.java
----------------------------------------------------------------------
diff --git a/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/driver/SolidfirePrimaryDataStoreDriver.java b/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/driver/SolidfirePrimaryDataStoreDriver.java
index 9b2334b..eee9ba5 100644
--- a/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/driver/SolidfirePrimaryDataStoreDriver.java
+++ b/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/driver/SolidfirePrimaryDataStoreDriver.java
@@ -22,7 +22,6 @@ import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult;
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
-import org.apache.cloudstack.engine.subsystem.api.storage.DataTO;
import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint;
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreDriver;
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
@@ -30,6 +29,7 @@ import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
import org.apache.cloudstack.storage.command.CommandResult;
import com.cloud.agent.api.to.DataStoreTO;
+import com.cloud.agent.api.to.DataTO;
public class SolidfirePrimaryDataStoreDriver implements PrimaryDataStoreDriver {
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/42e25a22/server/src/com/cloud/hypervisor/HypervisorGuruBase.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/hypervisor/HypervisorGuruBase.java b/server/src/com/cloud/hypervisor/HypervisorGuruBase.java
index d77796d..2300953 100644
--- a/server/src/com/cloud/hypervisor/HypervisorGuruBase.java
+++ b/server/src/com/cloud/hypervisor/HypervisorGuruBase.java
@@ -22,6 +22,7 @@ import java.util.Map;
import javax.inject.Inject;
import com.cloud.agent.api.Command;
+import com.cloud.agent.api.to.DataTO;
import com.cloud.agent.api.to.NicTO;
import com.cloud.agent.api.to.VirtualMachineTO;
import com.cloud.agent.api.to.VolumeTO;
@@ -101,7 +102,7 @@ public abstract class HypervisorGuruBase extends AdapterBase implements Hypervis
}
to.setNics(nics);
- to.setDisks(vmProfile.getDisks().toArray(new VolumeTO[vmProfile.getDisks().size()]));
+ to.setDisks(vmProfile.getDisks().toArray(new DataTO[vmProfile.getDisks().size()]));
if(vmProfile.getTemplate().getBits() == 32) {
to.setArch("i686");
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/42e25a22/server/src/com/cloud/storage/VolumeManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/storage/VolumeManagerImpl.java b/server/src/com/cloud/storage/VolumeManagerImpl.java
index 90b2366..17e0e09 100644
--- a/server/src/com/cloud/storage/VolumeManagerImpl.java
+++ b/server/src/com/cloud/storage/VolumeManagerImpl.java
@@ -45,18 +45,22 @@ import org.apache.cloudstack.api.command.user.volume.UploadVolumeCmd;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProviderManager;
-import org.apache.cloudstack.engine.subsystem.api.storage.TemplateDataFactory;
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.Scope;
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotDataFactory;
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.StoragePoolAllocator;
+import org.apache.cloudstack.engine.subsystem.api.storage.TemplateDataFactory;
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory;
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeService;
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeService.VolumeApiResult;
import org.apache.cloudstack.framework.async.AsyncCallFuture;
+import org.apache.cloudstack.storage.command.AttachAnswer;
+import org.apache.cloudstack.storage.command.AttachCommand;
+import org.apache.cloudstack.storage.command.DettachAnswer;
+import org.apache.cloudstack.storage.command.DettachCommand;
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao;
@@ -69,8 +73,8 @@ import org.springframework.stereotype.Component;
import com.cloud.agent.AgentManager;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.AttachVolumeAnswer;
-import com.cloud.agent.api.AttachVolumeCommand;
-import com.cloud.agent.api.to.VolumeTO;
+import com.cloud.agent.api.to.DataTO;
+import com.cloud.agent.api.to.DiskTO;
import com.cloud.alert.AlertManager;
import com.cloud.api.ApiDBUtils;
import com.cloud.async.AsyncJobExecutor;
@@ -117,7 +121,6 @@ import com.cloud.server.ManagementServer;
import com.cloud.service.ServiceOfferingVO;
import com.cloud.service.dao.ServiceOfferingDao;
import com.cloud.storage.Storage.ImageFormat;
-import com.cloud.storage.Storage.StoragePoolType;
import com.cloud.storage.Volume.Event;
import com.cloud.storage.Volume.Type;
import com.cloud.storage.dao.DiskOfferingDao;
@@ -168,7 +171,6 @@ import com.cloud.vm.dao.DomainRouterDao;
import com.cloud.vm.dao.SecondaryStorageVmDao;
import com.cloud.vm.dao.UserVmDao;
import com.cloud.vm.dao.VMInstanceDao;
-import com.cloud.vm.snapshot.VMSnapshot;
import com.cloud.vm.snapshot.VMSnapshotVO;
import com.cloud.vm.snapshot.dao.VMSnapshotDao;
@@ -1514,7 +1516,7 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager {
String errorMsg = "Failed to attach volume: " + volume.getName()
+ " to VM: " + vm.getHostName();
boolean sendCommand = (vm.getState() == State.Running);
- AttachVolumeAnswer answer = null;
+ AttachAnswer answer = null;
Long hostId = vm.getHostId();
if (hostId == null) {
hostId = vm.getLastHostId();
@@ -1526,16 +1528,11 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager {
}
if (sendCommand) {
- StoragePoolVO volumePool = _storagePoolDao.findById(volume
- .getPoolId());
- AttachVolumeCommand cmd = new AttachVolumeCommand(true,
- vm.getInstanceName(), volume.getPoolType(),
- volume.getFolder(), volume.getPath(), volume.getName(),
- deviceId, volume.getChainInfo());
- cmd.setPoolUuid(volumePool.getUuid());
-
+ DataTO volTO = this.volFactory.getVolume(volume.getId()).getTO();
+ DiskTO disk = new DiskTO(volTO, deviceId, volume.getVolumeType());
+ AttachCommand cmd = new AttachCommand(disk, vm.getInstanceName());
try {
- answer = (AttachVolumeAnswer) _agentMgr.send(hostId, cmd);
+ answer = (AttachAnswer) _agentMgr.send(hostId, cmd);
} catch (Exception e) {
throw new CloudRuntimeException(errorMsg + " due to: "
+ e.getMessage());
@@ -1545,8 +1542,9 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager {
if (!sendCommand || (answer != null && answer.getResult())) {
// Mark the volume as attached
if (sendCommand) {
+ DiskTO disk = answer.getDisk();
_volsDao.attachVolume(volume.getId(), vm.getId(),
- answer.getDeviceId());
+ disk.getDiskSeq());
} else {
_volsDao.attachVolume(volume.getId(), vm.getId(), deviceId);
}
@@ -1858,16 +1856,9 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager {
Answer answer = null;
if (sendCommand) {
- AttachVolumeCommand cmd = new AttachVolumeCommand(false,
- vm.getInstanceName(), volume.getPoolType(),
- volume.getFolder(), volume.getPath(), volume.getName(),
- cmmd.getDeviceId() != null ? cmmd.getDeviceId() : volume
- .getDeviceId(), volume.getChainInfo());
-
- StoragePoolVO volumePool = _storagePoolDao.findById(volume
- .getPoolId());
- cmd.setPoolUuid(volumePool.getUuid());
-
+ DataTO volTO = this.volFactory.getVolume(volume.getId()).getTO();
+ DiskTO disk = new DiskTO(volTO, volume.getDeviceId(), volume.getVolumeType());
+ DettachCommand cmd = new DettachCommand(disk, vm.getInstanceName());
try {
answer = _agentMgr.send(vm.getHostId(), cmd);
} catch (Exception e) {
@@ -1879,12 +1870,6 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager {
if (!sendCommand || (answer != null && answer.getResult())) {
// Mark the volume as detached
_volsDao.detachVolume(volume.getId());
- if (answer != null && answer instanceof AttachVolumeAnswer) {
- volume.setChainInfo(((AttachVolumeAnswer) answer)
- .getChainInfo());
- _volsDao.update(volume.getId(), volume);
- }
-
return _volsDao.findById(volumeId);
} else {
@@ -2097,22 +2082,17 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager {
}
for (VolumeVO vol : vols) {
- PrimaryDataStoreInfo pool = (PrimaryDataStoreInfo)this.dataStoreMgr.getDataStore(vol.getPoolId(), DataStoreRole.Primary);
- vm.addDisk(new VolumeTO(vol, pool));
+ DataTO volTO = this.volFactory.getVolume(vol.getId()).getTO();
+ DiskTO disk = new DiskTO(volTO, vol.getDeviceId(), vol.getVolumeType());
+ vm.addDisk(disk);
}
if (vm.getType() == VirtualMachine.Type.User) {
UserVmVO userVM = (UserVmVO) vm.getVirtualMachine();
if (userVM.getIsoId() != null) {
- Pair<String, String> isoPathPair = this._tmpltMgr.getAbsoluteIsoPath(
- userVM.getIsoId(), userVM.getDataCenterId());
- if (isoPathPair != null) {
- String isoPath = isoPathPair.first();
- VolumeTO iso = new VolumeTO(vm.getId(), Volume.Type.ISO,
- StoragePoolType.ISO, null, null, null, isoPath, 0,
- null, null);
- vm.addDisk(iso);
- }
+ DataTO dataTO = this.tmplFactory.getTemplate(userVM.getIsoId(), DataStoreRole.Image, userVM.getDataCenterId()).getTO();
+ DiskTO iso = new DiskTO(dataTO, 3L, Volume.Type.ISO);
+ vm.addDisk(iso);
}
}
}
@@ -2328,7 +2308,9 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager {
pool = (StoragePool)dataStoreMgr.getDataStore(result.second().getId(), DataStoreRole.Primary);
vol = result.first();
}
- vm.addDisk(new VolumeTO(vol, pool));
+ DataTO volumeTO = this.volFactory.getVolume(vol.getId()).getTO();
+ DiskTO disk = new DiskTO(volumeTO, vol.getDeviceId(), vol.getVolumeType());
+ vm.addDisk(disk);
}
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/42e25a22/server/src/com/cloud/storage/download/DownloadListener.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/storage/download/DownloadListener.java b/server/src/com/cloud/storage/download/DownloadListener.java
index 001b45d..691d655 100755
--- a/server/src/com/cloud/storage/download/DownloadListener.java
+++ b/server/src/com/cloud/storage/download/DownloadListener.java
@@ -26,7 +26,6 @@ import java.util.TimerTask;
import javax.inject.Inject;
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
-import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint;
@@ -50,6 +49,7 @@ import com.cloud.agent.api.StartupCommand;
import com.cloud.agent.api.StartupRoutingCommand;
import com.cloud.agent.api.StartupSecondaryStorageCommand;
import com.cloud.agent.api.storage.DownloadAnswer;
+import com.cloud.agent.api.to.DataObjectType;
import com.cloud.exception.AgentUnavailableException;
import com.cloud.exception.ConnectionException;
import com.cloud.host.Host;
[3/7] refactor kvm/vmware resource code
Posted by ed...@apache.org.
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/42e25a22/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageProcessor.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageProcessor.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageProcessor.java
new file mode 100644
index 0000000..727c3f4
--- /dev/null
+++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageProcessor.java
@@ -0,0 +1,1404 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package com.cloud.hypervisor.xen.resource;
+
+import java.beans.BeanInfo;
+import java.beans.IntrospectionException;
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
+import java.io.File;
+import java.lang.reflect.InvocationTargetException;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+
+import org.apache.cloudstack.storage.command.AttachAnswer;
+import org.apache.cloudstack.storage.command.AttachCommand;
+import org.apache.cloudstack.storage.command.AttachPrimaryDataStoreAnswer;
+import org.apache.cloudstack.storage.command.AttachPrimaryDataStoreCmd;
+import org.apache.cloudstack.storage.command.CopyCmdAnswer;
+import org.apache.cloudstack.storage.command.CopyCommand;
+import org.apache.cloudstack.storage.command.CreateObjectAnswer;
+import org.apache.cloudstack.storage.command.CreateObjectCommand;
+import org.apache.cloudstack.storage.command.DeleteCommand;
+import org.apache.cloudstack.storage.command.DettachAnswer;
+import org.apache.cloudstack.storage.command.DettachCommand;
+import org.apache.cloudstack.storage.datastore.protocol.DataStoreProtocol;
+import org.apache.cloudstack.storage.to.PrimaryDataStoreTO;
+import org.apache.cloudstack.storage.to.SnapshotObjectTO;
+import org.apache.cloudstack.storage.to.TemplateObjectTO;
+import org.apache.cloudstack.storage.to.VolumeObjectTO;
+import org.apache.log4j.Logger;
+import org.apache.xmlrpc.XmlRpcException;
+
+import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.CreateStoragePoolCommand;
+import com.cloud.agent.api.to.DataObjectType;
+import com.cloud.agent.api.to.DataStoreTO;
+import com.cloud.agent.api.to.DataTO;
+import com.cloud.agent.api.to.DiskTO;
+import com.cloud.agent.api.to.NfsTO;
+import com.cloud.agent.api.to.S3TO;
+import com.cloud.agent.api.to.StorageFilerTO;
+import com.cloud.agent.api.to.SwiftTO;
+import com.cloud.exception.InternalErrorException;
+import com.cloud.hypervisor.xen.resource.CitrixResourceBase.SRType;
+import com.cloud.storage.Storage.ImageFormat;
+import com.cloud.storage.Storage.StoragePoolType;
+import com.cloud.storage.resource.StorageProcessor;
+import com.cloud.utils.S3Utils;
+import com.cloud.utils.StringUtils;
+import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.utils.storage.encoding.DecodedDataObject;
+import com.cloud.utils.storage.encoding.DecodedDataStore;
+import com.cloud.utils.storage.encoding.Decoder;
+import com.xensource.xenapi.Connection;
+import com.xensource.xenapi.Host;
+import com.xensource.xenapi.PBD;
+import com.xensource.xenapi.Pool;
+import com.xensource.xenapi.SR;
+import com.xensource.xenapi.Types;
+import com.xensource.xenapi.Types.BadServerResponse;
+import com.xensource.xenapi.Types.XenAPIException;
+import com.xensource.xenapi.VBD;
+import com.xensource.xenapi.VDI;
+import com.xensource.xenapi.VM;
+import com.xensource.xenapi.VMGuestMetrics;
+
+public class XenServerStorageProcessor implements StorageProcessor {
+ private static final Logger s_logger = Logger.getLogger(XenServerStorageProcessor.class);
+ protected CitrixResourceBase hypervisorResource;
+
+ public XenServerStorageProcessor(CitrixResourceBase resource) {
+ this.hypervisorResource = resource;
+ }
+
+ @Override
+ public AttachAnswer attachIso(AttachCommand cmd) {
+ DiskTO disk = cmd.getDisk();
+ DataTO data = disk.getData();
+ DataStoreTO store = data.getDataStore();
+
+ if (!(store instanceof NfsTO)) {
+ s_logger.debug("Can't attach a iso which is not created on nfs: ");
+ return new AttachAnswer("Can't attach a iso which is not created on nfs: ");
+ }
+ NfsTO nfsStore = (NfsTO)store;
+ String isoURL = nfsStore.getUrl() + File.separator + data.getPath();
+
+ String vmName = cmd.getVmName();
+ try {
+ Connection conn = this.hypervisorResource.getConnection();
+
+ VBD isoVBD = null;
+
+ // Find the VM
+ VM vm = this.hypervisorResource.getVM(conn, vmName);
+ // Find the ISO VDI
+ VDI isoVDI = this.hypervisorResource.getIsoVDIByURL(conn, vmName, isoURL);
+
+ // Find the VM's CD-ROM VBD
+ Set<VBD> vbds = vm.getVBDs(conn);
+ for (VBD vbd : vbds) {
+ String userDevice = vbd.getUserdevice(conn);
+ Types.VbdType type = vbd.getType(conn);
+
+ if (userDevice.equals("3") && type == Types.VbdType.CD) {
+ isoVBD = vbd;
+ break;
+ }
+ }
+
+ if (isoVBD == null) {
+ throw new CloudRuntimeException("Unable to find CD-ROM VBD for VM: " + vmName);
+ } else {
+ // If an ISO is already inserted, eject it
+ if (isoVBD.getEmpty(conn) == false) {
+ isoVBD.eject(conn);
+ }
+
+ // Insert the new ISO
+ isoVBD.insert(conn, isoVDI);
+ }
+
+ return new AttachAnswer(disk);
+
+ } catch (XenAPIException e) {
+ s_logger.warn("Failed to attach iso" + ": " + e.toString(), e);
+ return new AttachAnswer(e.toString());
+ } catch (Exception e) {
+ s_logger.warn("Failed to attach iso" + ": " + e.toString(), e);
+ return new AttachAnswer(e.toString());
+ }
+ }
+
+ @Override
+ public AttachAnswer attachVolume(AttachCommand cmd) {
+ String vmName = cmd.getVmName();
+ DiskTO disk = cmd.getDisk();
+ DataTO data = disk.getData();
+
+ try {
+ Connection conn = this.hypervisorResource.getConnection();
+ // Look up the VDI
+ VDI vdi = this.hypervisorResource.mount(conn, null, null, data.getPath());
+ // Look up the VM
+ VM vm = this.hypervisorResource.getVM(conn, vmName);
+ /* For HVM guest, if no pv driver installed, no attach/detach */
+ boolean isHVM;
+ if (vm.getPVBootloader(conn).equalsIgnoreCase("")) {
+ isHVM = true;
+ } else {
+ isHVM = false;
+ }
+ VMGuestMetrics vgm = vm.getGuestMetrics(conn);
+ boolean pvDrvInstalled = false;
+ if (!this.hypervisorResource.isRefNull(vgm) && vgm.getPVDriversUpToDate(conn)) {
+ pvDrvInstalled = true;
+ }
+ if (isHVM && !pvDrvInstalled) {
+ s_logger.warn(": You attempted an operation on a VM which requires PV drivers to be installed but the drivers were not detected");
+ return new AttachAnswer("You attempted an operation that requires PV drivers to be installed on the VM. Please install them by inserting xen-pv-drv.iso.");
+ }
+
+ // Figure out the disk number to attach the VM to
+ String diskNumber = null;
+ Long deviceId = disk.getDiskSeq();
+ if( deviceId != null ) {
+ if( deviceId.longValue() == 3 ) {
+ String msg = "Device 3 is reserved for CD-ROM, choose other device";
+ return new AttachAnswer(msg);
+ }
+ if(this.hypervisorResource.isDeviceUsed(conn, vm, deviceId)) {
+ String msg = "Device " + deviceId + " is used in VM " + vmName;
+ return new AttachAnswer(msg);
+ }
+ diskNumber = deviceId.toString();
+ } else {
+ diskNumber = this.hypervisorResource.getUnusedDeviceNum(conn, vm);
+ }
+ // Create a new VBD
+ VBD.Record vbdr = new VBD.Record();
+ vbdr.VM = vm;
+ vbdr.VDI = vdi;
+ vbdr.bootable = false;
+ vbdr.userdevice = diskNumber;
+ vbdr.mode = Types.VbdMode.RW;
+ vbdr.type = Types.VbdType.DISK;
+ vbdr.unpluggable = true;
+ VBD vbd = VBD.create(conn, vbdr);
+
+ // Attach the VBD to the VM
+ vbd.plug(conn);
+
+ // Update the VDI's label to include the VM name
+ vdi.setNameLabel(conn, vmName + "-DATA");
+ DiskTO newDisk = new DiskTO(disk.getData(), Long.parseLong(diskNumber), disk.getType());
+ return new AttachAnswer(newDisk);
+
+ } catch (XenAPIException e) {
+ String msg = "Failed to attach volume" + " for uuid: " + data.getPath() + " due to " + e.toString();
+ s_logger.warn(msg, e);
+ return new AttachAnswer(msg);
+ } catch (Exception e) {
+ String msg = "Failed to attach volume" + " for uuid: " + data.getPath() + " due to " + e.getMessage();
+ s_logger.warn(msg, e);
+ return new AttachAnswer(msg);
+ }
+ }
+
+ @Override
+ public Answer dettachIso(DettachCommand cmd) {
+ DiskTO disk = cmd.getDisk();
+ DataTO data = disk.getData();
+ DataStoreTO store = data.getDataStore();
+
+ if (!(store instanceof NfsTO)) {
+ s_logger.debug("Can't attach a iso which is not created on nfs: ");
+ return new DettachAnswer("Can't attach a iso which is not created on nfs: ");
+ }
+ NfsTO nfsStore = (NfsTO)store;
+ String isoURL = nfsStore.getUrl() + File.separator + data.getPath();
+
+ try {
+ Connection conn = this.hypervisorResource.getConnection();
+ // Find the VM
+ VM vm = this.hypervisorResource.getVM(conn, cmd.getVmName());
+ String vmUUID = vm.getUuid(conn);
+
+ // Find the ISO VDI
+ VDI isoVDI = this.hypervisorResource.getIsoVDIByURL(conn, cmd.getVmName(), isoURL);
+
+ SR sr = isoVDI.getSR(conn);
+
+ // Look up all VBDs for this VDI
+ Set<VBD> vbds = isoVDI.getVBDs(conn);
+
+ // Iterate through VBDs, and if the VBD belongs the VM, eject
+ // the ISO from it
+ for (VBD vbd : vbds) {
+ VM vbdVM = vbd.getVM(conn);
+ String vbdVmUUID = vbdVM.getUuid(conn);
+
+ if (vbdVmUUID.equals(vmUUID)) {
+ // If an ISO is already inserted, eject it
+ if (!vbd.getEmpty(conn)) {
+ vbd.eject(conn);
+ }
+ break;
+ }
+ }
+
+ if (!sr.getNameLabel(conn).startsWith("XenServer Tools")) {
+ this.hypervisorResource.removeSR(conn, sr);
+ }
+
+ return new DettachAnswer(disk);
+ } catch (XenAPIException e) {
+ String msg = "Failed to dettach volume" + " for uuid: " + data.getPath() + " due to " + e.toString();
+ s_logger.warn(msg, e);
+ return new DettachAnswer(msg);
+ } catch (Exception e) {
+ String msg = "Failed to dettach volume" + " for uuid: " + data.getPath() + " due to " + e.getMessage();
+ s_logger.warn(msg, e);
+ return new DettachAnswer(msg);
+ }
+ }
+
+
+ @Override
+ public Answer dettachVolume(DettachCommand cmd) {
+ String vmName = cmd.getVmName();
+ DiskTO disk = cmd.getDisk();
+ DataTO data = disk.getData();
+ try {
+ Connection conn = this.hypervisorResource.getConnection();
+ // Look up the VDI
+ VDI vdi = this.hypervisorResource.mount(conn, null, null, data.getPath());
+ // Look up the VM
+ VM vm = this.hypervisorResource.getVM(conn, vmName);
+ /* For HVM guest, if no pv driver installed, no attach/detach */
+ boolean isHVM;
+ if (vm.getPVBootloader(conn).equalsIgnoreCase("")) {
+ isHVM = true;
+ } else {
+ isHVM = false;
+ }
+ VMGuestMetrics vgm = vm.getGuestMetrics(conn);
+ boolean pvDrvInstalled = false;
+ if (!this.hypervisorResource.isRefNull(vgm) && vgm.getPVDriversUpToDate(conn)) {
+ pvDrvInstalled = true;
+ }
+ if (isHVM && !pvDrvInstalled) {
+ s_logger.warn(": You attempted an operation on a VM which requires PV drivers to be installed but the drivers were not detected");
+ return new DettachAnswer("You attempted an operation that requires PV drivers to be installed on the VM. Please install them by inserting xen-pv-drv.iso.");
+ }
+
+
+ // Look up all VBDs for this VDI
+ Set<VBD> vbds = vdi.getVBDs(conn);
+
+ // Detach each VBD from its VM, and then destroy it
+ for (VBD vbd : vbds) {
+ VBD.Record vbdr = vbd.getRecord(conn);
+
+ if (vbdr.currentlyAttached) {
+ vbd.unplug(conn);
+ }
+
+ vbd.destroy(conn);
+ }
+
+ // Update the VDI's label to be "detached"
+ vdi.setNameLabel(conn, "detached");
+
+ this.hypervisorResource.umount(conn, vdi);
+
+ return new DettachAnswer(disk);
+ } catch(Exception e) {
+ s_logger.warn("Failed dettach volume: " + data.getPath());
+ return new DettachAnswer("Failed dettach volume: " + data.getPath() + ", due to " + e.toString());
+ }
+ }
+
+
+ protected SR getSRByNameLabel(Connection conn, String nameLabel) throws BadServerResponse, XenAPIException, XmlRpcException {
+ Set<SR> srs = SR.getByNameLabel(conn, nameLabel);
+ if (srs.size() != 1) {
+ throw new CloudRuntimeException("storage uuid: " + nameLabel + " is not unique");
+ }
+ SR poolsr = srs.iterator().next();
+ return poolsr;
+ }
+
+ protected VDI createVdi(Connection conn, String vdiName, SR sr, long size) throws BadServerResponse, XenAPIException, XmlRpcException {
+ VDI.Record vdir = new VDI.Record();
+ vdir.nameLabel = vdiName;
+ vdir.SR = sr;
+ vdir.type = Types.VdiType.USER;
+
+ vdir.virtualSize = size;
+ VDI vdi = VDI.create(conn, vdir);
+ return vdi;
+ }
+
+ protected void deleteVDI(Connection conn, VDI vdi) throws BadServerResponse, XenAPIException, XmlRpcException {
+ vdi.destroy(conn);
+ }
+
+ @Override
+ public Answer createSnapshot(CreateObjectCommand cmd) {
+ Connection conn = hypervisorResource.getConnection();
+ SnapshotObjectTO snapshotTO = (SnapshotObjectTO)cmd.getData();
+ long snapshotId = snapshotTO.getId();
+ String snapshotName = snapshotTO.getName();
+ String details = "create snapshot operation Failed for snapshotId: " + snapshotId;
+ String snapshotUUID = null;
+
+ try {
+ String volumeUUID = snapshotTO.getVolume().getPath();
+ VDI volume = VDI.getByUuid(conn, volumeUUID);
+
+ VDI snapshot = volume.snapshot(conn, new HashMap<String, String>());
+
+ if (snapshotName != null) {
+ snapshot.setNameLabel(conn, snapshotName);
+ }
+
+ snapshotUUID = snapshot.getUuid(conn);
+ String preSnapshotUUID = snapshotTO.getParentSnapshotPath();
+ //check if it is a empty snapshot
+ if( preSnapshotUUID != null) {
+ SR sr = volume.getSR(conn);
+ String srUUID = sr.getUuid(conn);
+ String type = sr.getType(conn);
+ Boolean isISCSI = IsISCSI(type);
+ String snapshotParentUUID = getVhdParent(conn, srUUID, snapshotUUID, isISCSI);
+
+ String preSnapshotParentUUID = getVhdParent(conn, srUUID, preSnapshotUUID, isISCSI);
+ if( snapshotParentUUID != null && snapshotParentUUID.equals(preSnapshotParentUUID)) {
+ // this is empty snapshot, remove it
+ snapshot.destroy(conn);
+ snapshotUUID = preSnapshotUUID;
+ }
+ }
+ SnapshotObjectTO newSnapshot = new SnapshotObjectTO();
+ newSnapshot.setPath(snapshotUUID);
+ return new CreateObjectAnswer(newSnapshot);
+ } catch (XenAPIException e) {
+ details += ", reason: " + e.toString();
+ s_logger.warn(details, e);
+ } catch (Exception e) {
+ details += ", reason: " + e.toString();
+ s_logger.warn(details, e);
+ }
+
+ return new CreateObjectAnswer(details);
+ }
+
+ @Override
+ public Answer deleteVolume(DeleteCommand cmd) {
+ DataTO volume = cmd.getData();
+ Connection conn = hypervisorResource.getConnection();
+ String errorMsg = null;
+ try {
+ VDI vdi = VDI.getByUuid(conn, volume.getPath());
+ deleteVDI(conn, vdi);
+ return new Answer(null);
+ } catch (BadServerResponse e) {
+ s_logger.debug("Failed to delete volume", e);
+ errorMsg = e.toString();
+ } catch (XenAPIException e) {
+ s_logger.debug("Failed to delete volume", e);
+ errorMsg = e.toString();
+ } catch (XmlRpcException e) {
+ s_logger.debug("Failed to delete volume", e);
+ errorMsg = e.toString();
+ }
+ return new Answer(null, false, errorMsg);
+ }
+
+
+ protected SR getNfsSR(Connection conn, StorageFilerTO pool) {
+ Map<String, String> deviceConfig = new HashMap<String, String>();
+ try {
+ String server = pool.getHost();
+ String serverpath = pool.getPath();
+ serverpath = serverpath.replace("//", "/");
+ Set<SR> srs = SR.getAll(conn);
+ for (SR sr : srs) {
+ if (!SRType.NFS.equals(sr.getType(conn))) {
+ continue;
+ }
+
+ Set<PBD> pbds = sr.getPBDs(conn);
+ if (pbds.isEmpty()) {
+ continue;
+ }
+
+ PBD pbd = pbds.iterator().next();
+
+ Map<String, String> dc = pbd.getDeviceConfig(conn);
+
+ if (dc == null) {
+ continue;
+ }
+
+ if (dc.get("server") == null) {
+ continue;
+ }
+
+ if (dc.get("serverpath") == null) {
+ continue;
+ }
+
+ if (server.equals(dc.get("server")) && serverpath.equals(dc.get("serverpath"))) {
+ throw new CloudRuntimeException("There is a SR using the same configuration server:" + dc.get("server") + ", serverpath:"
+ + dc.get("serverpath") + " for pool " + pool.getUuid() + "on host:" + hypervisorResource.getHost().uuid);
+ }
+
+ }
+ deviceConfig.put("server", server);
+ deviceConfig.put("serverpath", serverpath);
+ Host host = Host.getByUuid(conn, hypervisorResource.getHost().uuid);
+ SR sr = SR.create(conn, host, deviceConfig, new Long(0), pool.getUuid(), Long.toString(pool.getId()), SRType.NFS.toString(), "user", true,
+ new HashMap<String, String>());
+ sr.scan(conn);
+ return sr;
+ } catch (XenAPIException e) {
+ throw new CloudRuntimeException("Unable to create NFS SR " + pool.toString(), e);
+ } catch (XmlRpcException e) {
+ throw new CloudRuntimeException("Unable to create NFS SR " + pool.toString(), e);
+ }
+ }
+
+ protected SR getIscsiSR(Connection conn, StorageFilerTO pool) {
+ synchronized (pool.getUuid().intern()) {
+ Map<String, String> deviceConfig = new HashMap<String, String>();
+ try {
+ String target = pool.getHost();
+ String path = pool.getPath();
+ if (path.endsWith("/")) {
+ path = path.substring(0, path.length() - 1);
+ }
+
+ String tmp[] = path.split("/");
+ if (tmp.length != 3) {
+ String msg = "Wrong iscsi path " + pool.getPath() + " it should be /targetIQN/LUN";
+ s_logger.warn(msg);
+ throw new CloudRuntimeException(msg);
+ }
+ String targetiqn = tmp[1].trim();
+ String lunid = tmp[2].trim();
+ String scsiid = "";
+
+ Set<SR> srs = SR.getByNameLabel(conn, pool.getUuid());
+ for (SR sr : srs) {
+ if (!SRType.LVMOISCSI.equals(sr.getType(conn))) {
+ continue;
+ }
+ Set<PBD> pbds = sr.getPBDs(conn);
+ if (pbds.isEmpty()) {
+ continue;
+ }
+ PBD pbd = pbds.iterator().next();
+ Map<String, String> dc = pbd.getDeviceConfig(conn);
+ if (dc == null) {
+ continue;
+ }
+ if (dc.get("target") == null) {
+ continue;
+ }
+ if (dc.get("targetIQN") == null) {
+ continue;
+ }
+ if (dc.get("lunid") == null) {
+ continue;
+ }
+ if (target.equals(dc.get("target")) && targetiqn.equals(dc.get("targetIQN")) && lunid.equals(dc.get("lunid"))) {
+ throw new CloudRuntimeException("There is a SR using the same configuration target:" + dc.get("target") + ", targetIQN:"
+ + dc.get("targetIQN") + ", lunid:" + dc.get("lunid") + " for pool " + pool.getUuid() + "on host:" + this.hypervisorResource.getHost().uuid);
+ }
+ }
+ deviceConfig.put("target", target);
+ deviceConfig.put("targetIQN", targetiqn);
+
+ Host host = Host.getByUuid(conn, this.hypervisorResource.getHost().uuid);
+ Map<String, String> smConfig = new HashMap<String, String>();
+ String type = SRType.LVMOISCSI.toString();
+ String poolId = Long.toString(pool.getId());
+ SR sr = null;
+ try {
+ sr = SR.create(conn, host, deviceConfig, new Long(0), pool.getUuid(), poolId, type, "user", true,
+ smConfig);
+ } catch (XenAPIException e) {
+ String errmsg = e.toString();
+ if (errmsg.contains("SR_BACKEND_FAILURE_107")) {
+ String lun[] = errmsg.split("<LUN>");
+ boolean found = false;
+ for (int i = 1; i < lun.length; i++) {
+ int blunindex = lun[i].indexOf("<LUNid>") + 7;
+ int elunindex = lun[i].indexOf("</LUNid>");
+ String ilun = lun[i].substring(blunindex, elunindex);
+ ilun = ilun.trim();
+ if (ilun.equals(lunid)) {
+ int bscsiindex = lun[i].indexOf("<SCSIid>") + 8;
+ int escsiindex = lun[i].indexOf("</SCSIid>");
+ scsiid = lun[i].substring(bscsiindex, escsiindex);
+ scsiid = scsiid.trim();
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ String msg = "can not find LUN " + lunid + " in " + errmsg;
+ s_logger.warn(msg);
+ throw new CloudRuntimeException(msg);
+ }
+ } else {
+ String msg = "Unable to create Iscsi SR " + deviceConfig + " due to " + e.toString();
+ s_logger.warn(msg, e);
+ throw new CloudRuntimeException(msg, e);
+ }
+ }
+ deviceConfig.put("SCSIid", scsiid);
+
+ String result = SR.probe(conn, host, deviceConfig, type , smConfig);
+ String pooluuid = null;
+ if( result.indexOf("<UUID>") != -1) {
+ pooluuid = result.substring(result.indexOf("<UUID>") + 6, result.indexOf("</UUID>")).trim();
+ }
+ if( pooluuid == null || pooluuid.length() != 36) {
+ sr = SR.create(conn, host, deviceConfig, new Long(0), pool.getUuid(), poolId, type, "user", true,
+ smConfig);
+ } else {
+ sr = SR.introduce(conn, pooluuid, pool.getUuid(), poolId,
+ type, "user", true, smConfig);
+ Pool.Record pRec = XenServerConnectionPool.getPoolRecord(conn);
+ PBD.Record rec = new PBD.Record();
+ rec.deviceConfig = deviceConfig;
+ rec.host = pRec.master;
+ rec.SR = sr;
+ PBD pbd = PBD.create(conn, rec);
+ pbd.plug(conn);
+ }
+ sr.scan(conn);
+ return sr;
+ } catch (XenAPIException e) {
+ String msg = "Unable to create Iscsi SR " + deviceConfig + " due to " + e.toString();
+ s_logger.warn(msg, e);
+ throw new CloudRuntimeException(msg, e);
+ } catch (Exception e) {
+ String msg = "Unable to create Iscsi SR " + deviceConfig + " due to " + e.getMessage();
+ s_logger.warn(msg, e);
+ throw new CloudRuntimeException(msg, e);
+ }
+ }
+ }
+ protected Answer execute(CreateStoragePoolCommand cmd) {
+ Connection conn = this.hypervisorResource.getConnection();
+ StorageFilerTO pool = cmd.getPool();
+ try {
+ if (pool.getType() == StoragePoolType.NetworkFilesystem) {
+ getNfsSR(conn, pool);
+ } else if (pool.getType() == StoragePoolType.IscsiLUN) {
+ getIscsiSR(conn, pool);
+ } else if (pool.getType() == StoragePoolType.PreSetup) {
+ } else {
+ return new Answer(cmd, false, "The pool type: " + pool.getType().name() + " is not supported.");
+ }
+ return new Answer(cmd, true, "success");
+ } catch (Exception e) {
+ String msg = "Catch Exception " + e.getClass().getName() + ", create StoragePool failed due to " + e.toString() + " on host:" + this.hypervisorResource.getHost().uuid + " pool: " + pool.getHost() + pool.getPath();
+ s_logger.warn(msg, e);
+ return new Answer(cmd, false, msg);
+ }
+
+ }
+
+ protected Answer directDownloadHttpTemplate(CopyCommand cmd, DecodedDataObject srcObj, DecodedDataObject destObj) {
+ Connection conn = hypervisorResource.getConnection();
+ SR poolsr = null;
+ VDI vdi = null;
+ boolean result = false;
+ try {
+ if (destObj.getPath() == null) {
+ //need to create volume at first
+
+ }
+ vdi = VDI.getByUuid(conn, destObj.getPath());
+ if (vdi == null) {
+ throw new CloudRuntimeException("can't find volume: " + destObj.getPath());
+ }
+ String destStoreUuid = destObj.getStore().getUuid();
+ Set<SR> srs = SR.getByNameLabel(conn, destStoreUuid);
+ if (srs.size() != 1) {
+ throw new CloudRuntimeException("storage uuid: " + destStoreUuid + " is not unique");
+ }
+ poolsr = srs.iterator().next();
+ VDI.Record vdir = vdi.getRecord(conn);
+ String vdiLocation = vdir.location;
+ String pbdLocation = null;
+ if (destObj.getStore().getScheme().equalsIgnoreCase(DataStoreProtocol.NFS.toString())) {
+ pbdLocation = "/run/sr-mount/" + poolsr.getUuid(conn);
+ } else {
+ Set<PBD> pbds = poolsr.getPBDs(conn);
+ if (pbds.size() != 1) {
+ throw new CloudRuntimeException("Don't how to handle multiple pbds:" + pbds.size() + " for sr: " + poolsr.getUuid(conn));
+ }
+ PBD pbd = pbds.iterator().next();
+ Map<String, String> deviceCfg = pbd.getDeviceConfig(conn);
+ pbdLocation = deviceCfg.get("location");
+ }
+ if (pbdLocation == null) {
+ throw new CloudRuntimeException("Can't get pbd location");
+ }
+
+ String vdiPath = pbdLocation + "/" + vdiLocation + ".vhd";
+ //download a url into vdipath
+ //downloadHttpToLocalFile(vdiPath, template.getPath());
+ hypervisorResource.callHostPlugin(conn, "storagePlugin", "downloadTemplateFromUrl", "destPath", vdiPath, "srcUrl", srcObj.getPath());
+ result = true;
+ //return new CopyCmdAnswer(cmd, vdi.getUuid(conn));
+ } catch (BadServerResponse e) {
+ s_logger.debug("Failed to download template", e);
+ } catch (XenAPIException e) {
+ s_logger.debug("Failed to download template", e);
+ } catch (XmlRpcException e) {
+ s_logger.debug("Failed to download template", e);
+ } catch (Exception e) {
+ s_logger.debug("Failed to download template", e);
+ } finally {
+ if (!result && vdi != null) {
+ try {
+ vdi.destroy(conn);
+ } catch (BadServerResponse e) {
+ s_logger.debug("Failed to cleanup newly created vdi");
+ } catch (XenAPIException e) {
+ s_logger.debug("Failed to cleanup newly created vdi");
+ } catch (XmlRpcException e) {
+ s_logger.debug("Failed to cleanup newly created vdi");
+ }
+ }
+ }
+ return new Answer(cmd, false, "Failed to download template");
+ }
+
+ protected Answer execute(AttachPrimaryDataStoreCmd cmd) {
+ String dataStoreUri = cmd.getDataStore();
+ Connection conn = hypervisorResource.getConnection();
+ try {
+ DecodedDataObject obj = Decoder.decode(dataStoreUri);
+
+ DecodedDataStore store = obj.getStore();
+
+ SR sr = hypervisorResource.getStorageRepository(conn, store.getUuid());
+ hypervisorResource.setupHeartbeatSr(conn, sr, false);
+ long capacity = sr.getPhysicalSize(conn);
+ long available = capacity - sr.getPhysicalUtilisation(conn);
+ if (capacity == -1) {
+ String msg = "Pool capacity is -1! pool: ";
+ s_logger.warn(msg);
+ return new Answer(cmd, false, msg);
+ }
+ AttachPrimaryDataStoreAnswer answer = new AttachPrimaryDataStoreAnswer(cmd);
+ answer.setCapacity(capacity);
+ answer.setUuid(sr.getUuid(conn));
+ answer.setAvailable(available);
+ return answer;
+ } catch (XenAPIException e) {
+ String msg = "AttachPrimaryDataStoreCmd add XenAPIException:" + e.toString();
+ s_logger.warn(msg, e);
+ return new Answer(cmd, false, msg);
+ } catch (Exception e) {
+ String msg = "AttachPrimaryDataStoreCmd failed:" + e.getMessage();
+ s_logger.warn(msg, e);
+ return new Answer(cmd, false, msg);
+ }
+ }
+
+ private boolean IsISCSI(String type) {
+ return SRType.LVMOHBA.equals(type) || SRType.LVMOISCSI.equals(type) || SRType.LVM.equals(type) ;
+ }
+
+ private String copy_vhd_from_secondarystorage(Connection conn, String mountpoint, String sruuid, int wait) {
+ String nameLabel = "cloud-" + UUID.randomUUID().toString();
+ String results = hypervisorResource.callHostPluginAsync(conn, "vmopspremium", "copy_vhd_from_secondarystorage",
+ wait, "mountpoint", mountpoint, "sruuid", sruuid, "namelabel", nameLabel);
+ String errMsg = null;
+ if (results == null || results.isEmpty()) {
+ errMsg = "copy_vhd_from_secondarystorage return null";
+ } else {
+ String[] tmp = results.split("#");
+ String status = tmp[0];
+ if (status.equals("0")) {
+ return tmp[1];
+ } else {
+ errMsg = tmp[1];
+ }
+ }
+ String source = mountpoint.substring(mountpoint.lastIndexOf('/') + 1);
+ if( hypervisorResource.killCopyProcess(conn, source) ) {
+ destroyVDIbyNameLabel(conn, nameLabel);
+ }
+ s_logger.warn(errMsg);
+ throw new CloudRuntimeException(errMsg);
+ }
+
+ private void destroyVDIbyNameLabel(Connection conn, String nameLabel) {
+ try {
+ Set<VDI> vdis = VDI.getByNameLabel(conn, nameLabel);
+ if ( vdis.size() != 1 ) {
+ s_logger.warn("destoryVDIbyNameLabel failed due to there are " + vdis.size() + " VDIs with name " + nameLabel);
+ return;
+ }
+ for (VDI vdi : vdis) {
+ try {
+ vdi.destroy(conn);
+ } catch (Exception e) {
+ }
+ }
+ } catch (Exception e){
+ }
+ }
+
+ protected VDI getVDIbyUuid(Connection conn, String uuid) {
+ try {
+ return VDI.getByUuid(conn, uuid);
+ } catch (Exception e) {
+ String msg = "Catch Exception " + e.getClass().getName() + " :VDI getByUuid for uuid: " + uuid + " failed due to " + e.toString();
+ s_logger.debug(msg);
+ throw new CloudRuntimeException(msg, e);
+ }
+ }
+
+ protected String getVhdParent(Connection conn, String primaryStorageSRUuid, String snapshotUuid, Boolean isISCSI) {
+ String parentUuid = hypervisorResource.callHostPlugin(conn, "vmopsSnapshot", "getVhdParent", "primaryStorageSRUuid", primaryStorageSRUuid,
+ "snapshotUuid", snapshotUuid, "isISCSI", isISCSI.toString());
+
+ if (parentUuid == null || parentUuid.isEmpty() || parentUuid.equalsIgnoreCase("None")) {
+ s_logger.debug("Unable to get parent of VHD " + snapshotUuid + " in SR " + primaryStorageSRUuid);
+ // errString is already logged.
+ return null;
+ }
+ return parentUuid;
+ }
+
+ @Override
+ public Answer copyTemplateToPrimaryStorage(CopyCommand cmd) {
+ DataTO srcData = cmd.getSrcTO();
+ DataTO destData = cmd.getDestTO();
+ int wait = cmd.getWait();
+ DataStoreTO srcStore = srcData.getDataStore();
+ try {
+ if ((srcStore instanceof NfsTO) && (srcData.getObjectType() == DataObjectType.TEMPLATE)) {
+ NfsTO srcImageStore = (NfsTO)srcStore;
+ TemplateObjectTO srcTemplate = (TemplateObjectTO)srcData;
+ String storeUrl = srcImageStore.getUrl();
+
+ URI uri = new URI(storeUrl);
+ String tmplpath = uri.getHost() + ":" + uri.getPath() + "/" + srcData.getPath();
+ PrimaryDataStoreTO destStore = (PrimaryDataStoreTO)destData.getDataStore();
+ String poolName = destStore.getUuid();
+ Connection conn = hypervisorResource.getConnection();
+
+ SR poolsr = null;
+ Set<SR> srs = SR.getByNameLabel(conn, poolName);
+ if (srs.size() != 1) {
+ String msg = "There are " + srs.size() + " SRs with same name: " + poolName;
+ s_logger.warn(msg);
+ return new CopyCmdAnswer(msg);
+ } else {
+ poolsr = srs.iterator().next();
+ }
+ String pUuid = poolsr.getUuid(conn);
+ boolean isISCSI = IsISCSI(poolsr.getType(conn));
+ String uuid = copy_vhd_from_secondarystorage(conn, tmplpath, pUuid, wait);
+ VDI tmpl = getVDIbyUuid(conn, uuid);
+ VDI snapshotvdi = tmpl.snapshot(conn, new HashMap<String, String>());
+ String snapshotUuid = snapshotvdi.getUuid(conn);
+ snapshotvdi.setNameLabel(conn, "Template " + srcTemplate.getName());
+ String parentuuid = getVhdParent(conn, pUuid, snapshotUuid, isISCSI);
+ VDI parent = getVDIbyUuid(conn, parentuuid);
+ Long phySize = parent.getPhysicalUtilisation(conn);
+ tmpl.destroy(conn);
+ poolsr.scan(conn);
+ try{
+ Thread.sleep(5000);
+ } catch (Exception e) {
+ }
+
+ TemplateObjectTO newVol = new TemplateObjectTO();
+ newVol.setUuid(snapshotvdi.getUuid(conn));
+ newVol.setPath(newVol.getUuid());
+ return new CopyCmdAnswer(newVol);
+ }
+ }catch (Exception e) {
+ String msg = "Catch Exception " + e.getClass().getName() + " for template + " + " due to " + e.toString();
+ s_logger.warn(msg, e);
+ return new CopyCmdAnswer(msg);
+ }
+ return new CopyCmdAnswer("not implemented yet");
+ }
+
+ @Override
+ public Answer createVolume(CreateObjectCommand cmd) {
+ DataTO data = cmd.getData();
+ VolumeObjectTO volume = (VolumeObjectTO)data;
+
+ try {
+ Connection conn = hypervisorResource.getConnection();
+ PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)data.getDataStore();
+ SR poolSr = hypervisorResource.getStorageRepository(conn, primaryStore.getUuid());
+ VDI.Record vdir = new VDI.Record();
+ vdir.nameLabel = volume.getName();
+ vdir.SR = poolSr;
+ vdir.type = Types.VdiType.USER;
+
+ vdir.virtualSize = volume.getSize();
+ VDI vdi;
+
+ vdi = VDI.create(conn, vdir);
+ vdir = vdi.getRecord(conn);
+ VolumeObjectTO newVol = new VolumeObjectTO();
+ newVol.setName(vdir.nameLabel);
+ newVol.setSize(vdir.virtualSize);
+ newVol.setPath(vdir.uuid);
+
+ return new CreateObjectAnswer(newVol);
+ } catch (Exception e) {
+ s_logger.debug("create volume failed: " + e.toString());
+ return new CreateObjectAnswer(e.toString());
+ }
+ }
+
+ @Override
+ public Answer cloneVolumeFromBaseTemplate(CopyCommand cmd) {
+ Connection conn = hypervisorResource.getConnection();
+ DataTO srcData = cmd.getSrcTO();
+ DataTO destData = cmd.getDestTO();
+ PrimaryDataStoreTO pool = (PrimaryDataStoreTO)destData.getDataStore();
+ VolumeObjectTO volume = (VolumeObjectTO)destData;
+ VDI vdi = null;
+ try {
+ VDI tmpltvdi = null;
+
+ tmpltvdi = getVDIbyUuid(conn, srcData.getPath());
+ vdi = tmpltvdi.createClone(conn, new HashMap<String, String>());
+ vdi.setNameLabel(conn, volume.getName());
+
+
+ VDI.Record vdir;
+ vdir = vdi.getRecord(conn);
+ s_logger.debug("Succesfully created VDI: Uuid = " + vdir.uuid);
+
+ VolumeObjectTO newVol = new VolumeObjectTO();
+ newVol.setName(vdir.nameLabel);
+ newVol.setSize(vdir.virtualSize);
+ newVol.setPath(vdir.uuid);
+
+ return new CopyCmdAnswer(newVol);
+ } catch (Exception e) {
+ s_logger.warn("Unable to create volume; Pool=" + pool + "; Disk: ", e);
+ return new CopyCmdAnswer(e.toString());
+ }
+ }
+
+ @Override
+ public Answer copyVolumeFromImageCacheToPrimary(CopyCommand cmd) {
+ Connection conn = hypervisorResource.getConnection();
+ DataTO srcData = cmd.getSrcTO();
+ DataTO destData = cmd.getDestTO();
+ int wait = cmd.getWait();
+ VolumeObjectTO srcVolume = (VolumeObjectTO)srcData;
+ VolumeObjectTO destVolume = (VolumeObjectTO)destData;
+ PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)destVolume.getDataStore();
+ DataStoreTO srcStore = srcVolume.getDataStore();
+
+ if (srcStore instanceof NfsTO) {
+ NfsTO nfsStore = (NfsTO)srcStore;
+ try {
+ SR primaryStoragePool = hypervisorResource.getStorageRepository(conn, primaryStore.getUuid());
+ String srUuid = primaryStoragePool.getUuid(conn);
+ String volumePath = nfsStore.getUrl() + ":" + srcVolume.getPath();
+ String uuid = copy_vhd_from_secondarystorage(conn, volumePath, srUuid, wait );
+ VolumeObjectTO newVol = new VolumeObjectTO();
+ newVol.setPath(uuid);
+ newVol.setSize(srcVolume.getSize());
+
+ return new CopyCmdAnswer(newVol);
+ } catch (Exception e) {
+ String msg = "Catch Exception " + e.getClass().getName() + " due to " + e.toString();
+ s_logger.warn(msg, e);
+ return new CopyCmdAnswer(e.toString());
+ }
+ }
+
+ s_logger.debug("unsupported protocol");
+ return new CopyCmdAnswer("unsupported protocol");
+ }
+
+ @Override
+ public Answer copyVolumeFromPrimaryToSecondary(CopyCommand cmd) {
+ Connection conn = hypervisorResource.getConnection();
+ VolumeObjectTO srcVolume = (VolumeObjectTO)cmd.getSrcTO();
+ VolumeObjectTO destVolume = (VolumeObjectTO)cmd.getDestTO();
+ int wait = cmd.getWait();
+ DataStoreTO destStore = destVolume.getDataStore();
+
+ if (destStore instanceof NfsTO) {
+ SR secondaryStorage = null;
+ try {
+ NfsTO nfsStore = (NfsTO)destStore;
+ URI uri = new URI(nfsStore.getUrl());
+ // Create the volume folder
+ if (!hypervisorResource.createSecondaryStorageFolder(conn, uri.getHost() + ":" + uri.getPath(), destVolume.getPath())) {
+ throw new InternalErrorException("Failed to create the volume folder.");
+ }
+
+ // Create a SR for the volume UUID folder
+ secondaryStorage = hypervisorResource.createNfsSRbyURI(conn, new URI(nfsStore.getUrl() + destVolume.getPath()), false);
+ // Look up the volume on the source primary storage pool
+ VDI srcVdi = getVDIbyUuid(conn, srcVolume.getPath());
+ // Copy the volume to secondary storage
+ VDI destVdi = hypervisorResource.cloudVDIcopy(conn, srcVdi, secondaryStorage, wait);
+ String destVolumeUUID = destVdi.getUuid(conn);
+
+ VolumeObjectTO newVol = new VolumeObjectTO();
+ newVol.setPath(destVolumeUUID);
+ newVol.setSize(srcVolume.getSize());
+ return new CopyCmdAnswer(newVol);
+ } catch (Exception e) {
+ s_logger.debug("Failed to copy volume to secondary: " + e.toString());
+ return new CopyCmdAnswer("Failed to copy volume to secondary: " + e.toString());
+ } finally {
+ hypervisorResource.removeSR(conn, secondaryStorage);
+ }
+ }
+ return new CopyCmdAnswer("unsupported protocol");
+ }
+
+ boolean swiftUpload(Connection conn, SwiftTO swift, String container, String ldir, String lfilename, Boolean isISCSI, int wait) {
+ String result = null;
+ try {
+ result = hypervisorResource.callHostPluginAsync(conn, "swiftxen", "swift", wait,
+ "op", "upload", "url", swift.getUrl(), "account", swift.getAccount(),
+ "username", swift.getUserName(), "key", swift.getKey(), "container", container,
+ "ldir", ldir, "lfilename", lfilename, "isISCSI", isISCSI.toString());
+ if( result != null && result.equals("true")) {
+ return true;
+ }
+ } catch (Exception e) {
+ s_logger.warn("swift upload failed due to " + e.toString(), e);
+ }
+ return false;
+ }
+
+ protected String deleteSnapshotBackup(Connection conn, String path, String secondaryStorageMountPath, String backupUUID) {
+
+ // If anybody modifies the formatting below again, I'll skin them
+ String result = hypervisorResource.callHostPlugin(conn, "vmopsSnapshot", "deleteSnapshotBackup", "backupUUID", backupUUID, "path", path, "secondaryStorageMountPath", secondaryStorageMountPath);
+
+ return result;
+ }
+
+ public void swiftBackupSnapshot(Connection conn, SwiftTO swift, String srUuid, String snapshotUuid, String container, Boolean isISCSI, int wait) {
+ String lfilename;
+ String ldir;
+ if ( isISCSI ) {
+ ldir = "/dev/VG_XenStorage-" + srUuid;
+ lfilename = "VHD-" + snapshotUuid;
+ } else {
+ ldir = "/var/run/sr-mount/" + srUuid;
+ lfilename = snapshotUuid + ".vhd";
+ }
+ swiftUpload(conn, swift, container, ldir, lfilename, isISCSI, wait);
+ }
+
+ private static List<String> serializeProperties(final Object object,
+ final Class<?> propertySet) {
+
+ assert object != null;
+ assert propertySet != null;
+ assert propertySet.isAssignableFrom(object.getClass());
+
+ try {
+
+ final BeanInfo beanInfo = Introspector.getBeanInfo(propertySet);
+ final PropertyDescriptor[] descriptors = beanInfo
+ .getPropertyDescriptors();
+
+ final List<String> serializedProperties = new ArrayList<String>();
+ for (final PropertyDescriptor descriptor : descriptors) {
+
+ serializedProperties.add(descriptor.getName());
+ final Object value = descriptor.getReadMethod().invoke(object);
+ serializedProperties.add(value != null ? value.toString()
+ : "null");
+
+ }
+
+ return Collections.unmodifiableList(serializedProperties);
+
+ } catch (IntrospectionException e) {
+ s_logger.warn(
+ "Ignored IntrospectionException when serializing class "
+ + object.getClass().getCanonicalName(), e);
+ } catch (IllegalArgumentException e) {
+ s_logger.warn(
+ "Ignored IllegalArgumentException when serializing class "
+ + object.getClass().getCanonicalName(), e);
+ } catch (IllegalAccessException e) {
+ s_logger.warn(
+ "Ignored IllegalAccessException when serializing class "
+ + object.getClass().getCanonicalName(), e);
+ } catch (InvocationTargetException e) {
+ s_logger.warn(
+ "Ignored InvocationTargetException when serializing class "
+ + object.getClass().getCanonicalName(), e);
+ }
+
+ return Collections.emptyList();
+
+ }
+
+ private boolean backupSnapshotToS3(final Connection connection,
+ final S3TO s3, final String srUuid, final String snapshotUuid,
+ final Boolean iSCSIFlag, final int wait) {
+
+ final String filename = iSCSIFlag ? "VHD-" + snapshotUuid
+ : snapshotUuid + ".vhd";
+ final String dir = (iSCSIFlag ? "/dev/VG_XenStorage-"
+ : "/var/run/sr-mount/") + srUuid;
+ final String key = StringUtils.join("/", "snapshots", snapshotUuid);
+
+ try {
+
+ final List<String> parameters = new ArrayList<String>(
+ serializeProperties(s3, S3Utils.ClientOptions.class));
+ parameters.addAll(Arrays.asList("operation", "put", "directory",
+ dir, "filename", filename, "iSCSIFlag",
+ iSCSIFlag.toString(), "key", key));
+ final String result = hypervisorResource.callHostPluginAsync(connection, "s3xen",
+ "s3", wait,
+ parameters.toArray(new String[parameters.size()]));
+
+ if (result != null && result.equals("true")) {
+ return true;
+ }
+
+ } catch (Exception e) {
+ s_logger.error(String.format(
+ "S3 upload failed of snapshot %1$s due to %2$s.",
+ snapshotUuid, e.toString()), e);
+ }
+
+ return false;
+
+ }
+
+ protected String backupSnapshot(Connection conn, String primaryStorageSRUuid, String path, String secondaryStorageMountPath, String snapshotUuid, String prevBackupUuid, Boolean isISCSI, int wait) {
+ String backupSnapshotUuid = null;
+
+ if (prevBackupUuid == null) {
+ prevBackupUuid = "";
+ }
+
+ // Each argument is put in a separate line for readability.
+ // Using more lines does not harm the environment.
+ String backupUuid = UUID.randomUUID().toString();
+ String results = hypervisorResource.callHostPluginAsync(conn, "vmopsSnapshot", "backupSnapshot", wait,
+ "primaryStorageSRUuid", primaryStorageSRUuid, "path", path, "secondaryStorageMountPath", secondaryStorageMountPath,
+ "snapshotUuid", snapshotUuid, "prevBackupUuid", prevBackupUuid, "backupUuid", backupUuid, "isISCSI", isISCSI.toString());
+ String errMsg = null;
+ if (results == null || results.isEmpty()) {
+ errMsg = "Could not copy backupUuid: " + backupSnapshotUuid
+ + " from primary storage " + primaryStorageSRUuid + " to secondary storage "
+ + secondaryStorageMountPath + " due to null";
+ } else {
+
+ String[] tmp = results.split("#");
+ String status = tmp[0];
+ backupSnapshotUuid = tmp[1];
+ // status == "1" if and only if backupSnapshotUuid != null
+ // So we don't rely on status value but return backupSnapshotUuid as an
+ // indicator of success.
+ if (status != null && status.equalsIgnoreCase("1") && backupSnapshotUuid != null) {
+ s_logger.debug("Successfully copied backupUuid: " + backupSnapshotUuid
+ + " to secondary storage");
+ return backupSnapshotUuid;
+ } else {
+ errMsg = "Could not copy backupUuid: " + backupSnapshotUuid
+ + " from primary storage " + primaryStorageSRUuid + " to secondary storage "
+ + secondaryStorageMountPath + " due to " + tmp[1];
+ }
+ }
+ String source = backupUuid + ".vhd";
+ hypervisorResource.killCopyProcess(conn, source);
+ s_logger.warn(errMsg);
+ return null;
+
+ }
+
+ private boolean destroySnapshotOnPrimaryStorageExceptThis(Connection conn, String volumeUuid, String avoidSnapshotUuid){
+ try {
+ VDI volume = getVDIbyUuid(conn, volumeUuid);
+ if (volume == null) {
+ throw new InternalErrorException("Could not destroy snapshot on volume " + volumeUuid + " due to can not find it");
+ }
+ Set<VDI> snapshots = volume.getSnapshots(conn);
+ for( VDI snapshot : snapshots ) {
+ try {
+ if(! snapshot.getUuid(conn).equals(avoidSnapshotUuid)) {
+ snapshot.destroy(conn);
+ }
+ } catch (Exception e) {
+ String msg = "Destroying snapshot: " + snapshot+ " on primary storage failed due to " + e.toString();
+ s_logger.warn(msg, e);
+ }
+ }
+ s_logger.debug("Successfully destroyed snapshot on volume: " + volumeUuid + " execept this current snapshot "+ avoidSnapshotUuid );
+ return true;
+ } catch (XenAPIException e) {
+ String msg = "Destroying snapshot on volume: " + volumeUuid + " execept this current snapshot "+ avoidSnapshotUuid + " failed due to " + e.toString();
+ s_logger.error(msg, e);
+ } catch (Exception e) {
+ String msg = "Destroying snapshot on volume: " + volumeUuid + " execept this current snapshot "+ avoidSnapshotUuid + " failed due to " + e.toString();
+ s_logger.warn(msg, e);
+ }
+
+ return false;
+ }
+
+ @Override
+ public Answer backupSnasphot(CopyCommand cmd) {
+ Connection conn = hypervisorResource.getConnection();
+ DataTO srcData = cmd.getSrcTO();
+ DataTO cacheData = cmd.getCacheTO();
+ DataTO destData = cmd.getDestTO();
+ int wait = cmd.getWait();
+ PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)srcData.getDataStore();
+ String primaryStorageNameLabel = primaryStore.getUuid();
+ String secondaryStorageUrl = null;
+ NfsTO cacheStore = null;
+ String destPath = null;
+ if (cacheData != null) {
+ cacheStore = (NfsTO)cacheData.getDataStore();
+ secondaryStorageUrl = cacheStore.getUrl();
+ destPath = cacheData.getPath();
+ } else {
+ cacheStore = (NfsTO)destData.getDataStore();
+ secondaryStorageUrl = cacheStore.getUrl();
+ destPath = destData.getPath();
+ }
+
+ SnapshotObjectTO snapshotTO = (SnapshotObjectTO)srcData;
+ SnapshotObjectTO snapshotOnImage = (SnapshotObjectTO)destData;
+ String snapshotUuid = snapshotTO.getPath();
+
+ String prevBackupUuid = snapshotOnImage.getParentSnapshotPath();
+ String prevSnapshotUuid = snapshotTO.getParentSnapshotPath();
+
+ // By default assume failure
+ String details = null;
+ String snapshotBackupUuid = null;
+ boolean fullbackup = true;
+ try {
+ SR primaryStorageSR = hypervisorResource.getSRByNameLabelandHost(conn, primaryStorageNameLabel);
+ if (primaryStorageSR == null) {
+ throw new InternalErrorException("Could not backup snapshot because the primary Storage SR could not be created from the name label: " + primaryStorageNameLabel);
+ }
+ String psUuid = primaryStorageSR.getUuid(conn);
+ Boolean isISCSI = IsISCSI(primaryStorageSR.getType(conn));
+
+ VDI snapshotVdi = getVDIbyUuid(conn, snapshotUuid);
+ String snapshotPaUuid = null;
+ if ( prevBackupUuid != null ) {
+ try {
+ snapshotPaUuid = getVhdParent(conn, psUuid, snapshotUuid, isISCSI);
+ if( snapshotPaUuid != null ) {
+ String snashotPaPaPaUuid = getVhdParent(conn, psUuid, snapshotPaUuid, isISCSI);
+ String prevSnashotPaUuid = getVhdParent(conn, psUuid, prevSnapshotUuid, isISCSI);
+ if (snashotPaPaPaUuid != null && prevSnashotPaUuid!= null && prevSnashotPaUuid.equals(snashotPaPaPaUuid)) {
+ fullbackup = false;
+ }
+ }
+ } catch (Exception e) {
+ }
+ }
+
+ URI uri = new URI(secondaryStorageUrl);
+ String secondaryStorageMountPath = uri.getHost() + ":" + uri.getPath();
+ DataStoreTO destStore = destData.getDataStore();
+ String folder = destPath;
+ if (fullbackup) {
+ // the first snapshot is always a full snapshot
+
+ if( !hypervisorResource.createSecondaryStorageFolder(conn, secondaryStorageMountPath, folder)) {
+ details = " Filed to create folder " + folder + " in secondary storage";
+ s_logger.warn(details);
+ return new CopyCmdAnswer(details);
+ }
+ String snapshotMountpoint = secondaryStorageUrl + "/" + folder;
+ SR snapshotSr = null;
+ try {
+ snapshotSr = hypervisorResource.createNfsSRbyURI(conn, new URI(snapshotMountpoint), false);
+ VDI backedVdi = hypervisorResource.cloudVDIcopy(conn, snapshotVdi, snapshotSr, wait);
+ snapshotBackupUuid = backedVdi.getUuid(conn);
+
+ if( destStore instanceof SwiftTO) {
+ try {
+ hypervisorResource.swiftBackupSnapshot(conn, (SwiftTO)destStore, snapshotSr.getUuid(conn), snapshotBackupUuid, "S-" + snapshotTO.getVolume().getVolumeId().toString(), false, wait);
+ snapshotBackupUuid = snapshotBackupUuid + ".vhd";
+ } finally {
+ deleteSnapshotBackup(conn, folder, secondaryStorageMountPath, snapshotBackupUuid);
+ }
+ } else if (destStore instanceof S3TO) {
+ try {
+ backupSnapshotToS3(conn, (S3TO)destStore, snapshotSr.getUuid(conn), snapshotBackupUuid, isISCSI, wait);
+ snapshotBackupUuid = snapshotBackupUuid + ".vhd";
+ } finally {
+ deleteSnapshotBackup(conn, folder, secondaryStorageMountPath, snapshotBackupUuid);
+ }
+ }
+
+ } finally {
+ if( snapshotSr != null) {
+ hypervisorResource.removeSR(conn, snapshotSr);
+ }
+ }
+ } else {
+ String primaryStorageSRUuid = primaryStorageSR.getUuid(conn);
+ if( destStore instanceof SwiftTO ) {
+ swiftBackupSnapshot(conn, (SwiftTO)destStore, primaryStorageSRUuid, snapshotPaUuid, "S-" + snapshotTO.getVolume().getVolumeId().toString(), isISCSI, wait);
+ if ( isISCSI ) {
+ snapshotBackupUuid = "VHD-" + snapshotPaUuid;
+ } else {
+ snapshotBackupUuid = snapshotPaUuid + ".vhd";
+ }
+
+ } else if (destStore instanceof S3TO ) {
+ backupSnapshotToS3(conn, (S3TO)destStore, primaryStorageSRUuid, snapshotPaUuid, isISCSI, wait);
+ } else {
+ snapshotBackupUuid = backupSnapshot(conn, primaryStorageSRUuid, folder + File.separator + UUID.nameUUIDFromBytes(secondaryStorageMountPath.getBytes())
+ , secondaryStorageMountPath, snapshotUuid, prevBackupUuid, isISCSI, wait);
+
+ }
+ }
+ String volumeUuid = snapshotTO.getVolume().getPath();
+ destroySnapshotOnPrimaryStorageExceptThis(conn, volumeUuid, snapshotUuid);
+
+ SnapshotObjectTO newSnapshot = new SnapshotObjectTO();
+ newSnapshot.setPath(folder + File.separator + snapshotBackupUuid);
+ if (fullbackup) {
+ newSnapshot.setParentSnapshotPath(null);
+ } else {
+ newSnapshot.setParentSnapshotPath(prevBackupUuid);
+ }
+ return new CopyCmdAnswer(newSnapshot);
+ } catch (XenAPIException e) {
+ details = "BackupSnapshot Failed due to " + e.toString();
+ s_logger.warn(details, e);
+ } catch (Exception e) {
+ details = "BackupSnapshot Failed due to " + e.getMessage();
+ s_logger.warn(details, e);
+ }
+
+ return new CopyCmdAnswer(details);
+ }
+
+ @Override
+ public Answer createTemplateFromVolume(CopyCommand cmd) {
+ Connection conn = this.hypervisorResource.getConnection();
+ VolumeObjectTO volume = (VolumeObjectTO)cmd.getSrcTO();
+ TemplateObjectTO template = (TemplateObjectTO)cmd.getDestTO();
+ NfsTO destStore = (NfsTO)cmd.getDestTO().getDataStore();
+ int wait = cmd.getWait();
+
+ String secondaryStoragePoolURL = destStore.getUrl();
+ String volumeUUID = volume.getPath();
+
+ String userSpecifiedName = template.getName();
+
+
+ String details = null;
+ SR tmpltSR = null;
+ boolean result = false;
+ String secondaryStorageMountPath = null;
+ String installPath = null;
+ try {
+ URI uri = new URI(secondaryStoragePoolURL);
+ secondaryStorageMountPath = uri.getHost() + ":" + uri.getPath();
+ installPath = template.getPath();
+ if( !this.hypervisorResource.createSecondaryStorageFolder(conn, secondaryStorageMountPath, installPath)) {
+ details = " Filed to create folder " + installPath + " in secondary storage";
+ s_logger.warn(details);
+ return new CopyCmdAnswer(details);
+ }
+
+ VDI vol = getVDIbyUuid(conn, volumeUUID);
+ // create template SR
+ URI tmpltURI = new URI(secondaryStoragePoolURL + "/" + installPath);
+ tmpltSR = this.hypervisorResource.createNfsSRbyURI(conn, tmpltURI, false);
+
+ // copy volume to template SR
+ VDI tmpltVDI = this.hypervisorResource.cloudVDIcopy(conn, vol, tmpltSR, wait);
+ // scan makes XenServer pick up VDI physicalSize
+ tmpltSR.scan(conn);
+ if (userSpecifiedName != null) {
+ tmpltVDI.setNameLabel(conn, userSpecifiedName);
+ }
+
+ String tmpltUUID = tmpltVDI.getUuid(conn);
+ String tmpltFilename = tmpltUUID + ".vhd";
+ long virtualSize = tmpltVDI.getVirtualSize(conn);
+ long physicalSize = tmpltVDI.getPhysicalUtilisation(conn);
+ // create the template.properties file
+ String templatePath = secondaryStorageMountPath + "/" + installPath;
+ result = this.hypervisorResource.postCreatePrivateTemplate(conn, templatePath, tmpltFilename, tmpltUUID, userSpecifiedName, null, physicalSize, virtualSize, template.getId());
+ if (!result) {
+ throw new CloudRuntimeException("Could not create the template.properties file on secondary storage dir: " + tmpltURI);
+ }
+ installPath = installPath + "/" + tmpltFilename;
+ this.hypervisorResource.removeSR(conn, tmpltSR);
+ tmpltSR = null;
+ TemplateObjectTO newTemplate = new TemplateObjectTO();
+ newTemplate.setPath(installPath);
+ newTemplate.setFormat(ImageFormat.VHD);
+ CopyCmdAnswer answer = new CopyCmdAnswer(newTemplate);
+ return answer;
+ } catch (Exception e) {
+ if (tmpltSR != null) {
+ this.hypervisorResource.removeSR(conn, tmpltSR);
+ }
+ if ( secondaryStorageMountPath != null) {
+ this.hypervisorResource.deleteSecondaryStorageFolder(conn, secondaryStorageMountPath, installPath);
+ }
+ details = "Creating template from volume " + volumeUUID + " failed due to " + e.toString();
+ s_logger.error(details, e);
+ }
+ return new CopyCmdAnswer(details);
+ }
+}
[6/7] git commit: updated refs/heads/object_store to e444867
Posted by ed...@apache.org.
refactor kvm/vmware resource code
Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/42e25a22
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/42e25a22
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/42e25a22
Branch: refs/heads/object_store
Commit: 42e25a22fc7140c68cda589e95d98dda3ba6cdf3
Parents: a83b87b
Author: Edison Su <ed...@citrix.com>
Authored: Thu May 9 23:09:42 2013 -0700
Committer: Edison Su <ed...@citrix.com>
Committed: Thu May 9 23:10:05 2013 -0700
----------------------------------------------------------------------
api/src/com/cloud/agent/api/to/DataObjectType.java | 25 +
api/src/com/cloud/agent/api/to/DataTO.java | 28 +
api/src/com/cloud/agent/api/to/DiskTO.java | 60 +
.../com/cloud/agent/api/to/VirtualMachineTO.java | 6 +-
api/src/com/cloud/vm/VirtualMachineProfile.java | 8 +-
core/src/com/cloud/serializer/GsonHelper.java | 2 +-
.../resource/NfsSecondaryStorageResource.java | 4 +-
.../cloud/storage/resource/StorageProcessor.java | 45 +
.../resource/StorageSubsystemCommandHandler.java | 27 +
.../StorageSubsystemCommandHandlerBase.java | 135 ++
.../engine/subsystem/api/storage/DataObject.java | 2 +
.../subsystem/api/storage/DataObjectType.java | 25 -
.../subsystem/api/storage/DataStoreDriver.java | 1 +
.../engine/subsystem/api/storage/DataTO.java | 30 -
.../cloudstack/storage/command/AttachAnswer.java | 44 +
.../cloudstack/storage/command/AttachCommand.java | 52 +
.../cloudstack/storage/command/CopyCmdAnswer.java | 2 +-
.../cloudstack/storage/command/CopyCommand.java | 2 +-
.../storage/command/CreateObjectAnswer.java | 2 +-
.../storage/command/CreateObjectCommand.java | 2 +-
.../cloudstack/storage/command/DeleteCommand.java | 2 +-
.../cloudstack/storage/command/DettachAnswer.java | 44 +
.../cloudstack/storage/command/DettachCommand.java | 52 +
.../cloudstack/storage/to/PrimaryDataStoreTO.java | 41 +
.../cloudstack/storage/to/SnapshotObjectTO.java | 4 +-
.../cloudstack/storage/to/TemplateObjectTO.java | 11 +-
.../cloudstack/storage/to/VolumeObjectTO.java | 30 +-
.../storage/motion/AncientDataMotionStrategy.java | 4 +-
.../storage/image/TemplateDataFactoryImpl.java | 11 +
.../storage/image/store/TemplateObject.java | 4 +-
.../storage/snapshot/SnapshotObject.java | 4 +-
.../datastore/ObjectInDataStoreManager.java | 2 +-
.../datastore/ObjectInDataStoreManagerImpl.java | 2 +-
.../cloudstack/storage/db/ObjectInDataStoreVO.java | 2 +-
.../storage/datastore/PrimaryDataStoreImpl.java | 2 +-
.../cloudstack/storage/volume/VolumeObject.java | 4 +-
.../kvm/resource/LibvirtComputingResource.java | 190 +--
.../hypervisor/kvm/resource/LibvirtVMDef.java | 6 +-
.../kvm/storage/KVMStorageProcessor.java | 879 +++++++++
.../hypervisor/kvm/storage/KVMStorageResource.java | 87 +
.../hypervisor/vmware/resource/VmwareResource.java | 209 ++-
.../VmwareSecondaryStorageResourceHandler.java | 10 +
.../storage/resource/VmwareStorageProcessor.java | 1144 ++++++++++++
.../xen/resource/CitrixResourceBase.java | 84 +-
.../xen/resource/XenServer56FP1Resource.java | 21 +-
.../xen/resource/XenServerStorageProcessor.java | 1404 +++++++++++++++
.../xen/resource/XenServerStorageResource.java | 1327 --------------
.../driver/CloudStackImageStoreDriverImpl.java | 4 +-
.../datastore/driver/S3ImageStoreDriverImpl.java | 4 +-
.../driver/SampleImageStoreDriverImpl.java | 4 +-
.../driver/SwiftImageStoreDriverImpl.java | 4 +-
.../CloudStackPrimaryDataStoreDriverImpl.java | 4 +-
.../driver/SamplePrimaryDataStoreDriverImpl.java | 2 +-
.../driver/SolidfirePrimaryDataStoreDriver.java | 2 +-
.../com/cloud/hypervisor/HypervisorGuruBase.java | 3 +-
.../src/com/cloud/storage/VolumeManagerImpl.java | 70 +-
.../cloud/storage/download/DownloadListener.java | 2 +-
.../com/cloud/template/TemplateManagerImpl.java | 37 +-
server/src/com/cloud/vm/UserVmManagerImpl.java | 52 +-
.../com/cloud/vm/VirtualMachineProfileImpl.java | 11 +-
60 files changed, 4504 insertions(+), 1777 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/42e25a22/api/src/com/cloud/agent/api/to/DataObjectType.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/agent/api/to/DataObjectType.java b/api/src/com/cloud/agent/api/to/DataObjectType.java
new file mode 100644
index 0000000..6f7a007
--- /dev/null
+++ b/api/src/com/cloud/agent/api/to/DataObjectType.java
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package com.cloud.agent.api.to;
+
+public enum DataObjectType {
+ VOLUME,
+ SNAPSHOT,
+ TEMPLATE
+}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/42e25a22/api/src/com/cloud/agent/api/to/DataTO.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/agent/api/to/DataTO.java b/api/src/com/cloud/agent/api/to/DataTO.java
new file mode 100644
index 0000000..bd9a16b
--- /dev/null
+++ b/api/src/com/cloud/agent/api/to/DataTO.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package com.cloud.agent.api.to;
+
+public interface DataTO {
+ public DataObjectType getObjectType();
+ public DataStoreTO getDataStore();
+ /**
+ * @return
+ */
+ String getPath();
+}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/42e25a22/api/src/com/cloud/agent/api/to/DiskTO.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/agent/api/to/DiskTO.java b/api/src/com/cloud/agent/api/to/DiskTO.java
new file mode 100644
index 0000000..7b32f00
--- /dev/null
+++ b/api/src/com/cloud/agent/api/to/DiskTO.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package com.cloud.agent.api.to;
+
+import com.cloud.storage.Volume;
+
+public class DiskTO {
+ private DataTO data;
+ private Long diskSeq;
+ private Volume.Type type;
+ public DiskTO() {
+
+ }
+
+ public DiskTO(DataTO data, Long diskSeq, Volume.Type type) {
+ this.data = data;
+ this.diskSeq = diskSeq;
+ this.type = type;
+ }
+
+ public DataTO getData() {
+ return data;
+ }
+
+ public void setData(DataTO data) {
+ this.data = data;
+ }
+
+ public Long getDiskSeq() {
+ return diskSeq;
+ }
+
+ public void setDiskSeq(Long diskSeq) {
+ this.diskSeq = diskSeq;
+ }
+
+ public Volume.Type getType() {
+ return type;
+ }
+
+ public void setType(Volume.Type type) {
+ this.type = type;
+ }
+}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/42e25a22/api/src/com/cloud/agent/api/to/VirtualMachineTO.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/agent/api/to/VirtualMachineTO.java b/api/src/com/cloud/agent/api/to/VirtualMachineTO.java
index b84d20a..2644c04 100644
--- a/api/src/com/cloud/agent/api/to/VirtualMachineTO.java
+++ b/api/src/com/cloud/agent/api/to/VirtualMachineTO.java
@@ -57,7 +57,7 @@ public class VirtualMachineTO {
Map<String, String> params;
String uuid;
- VolumeTO[] disks;
+ DiskTO[] disks;
NicTO[] nics;
public VirtualMachineTO(long id, String instanceName, VirtualMachine.Type type, int cpus, Integer speed, long minRam, long maxRam, BootloaderType bootloader, String os, boolean enableHA, boolean limitCpuUse, String vncPassword) {
@@ -206,11 +206,11 @@ public class VirtualMachineTO {
this.bootupScripts = bootupScripts;
}
- public VolumeTO[] getDisks() {
+ public DiskTO[] getDisks() {
return disks;
}
- public void setDisks(VolumeTO[] disks) {
+ public void setDisks(DiskTO[] disks) {
this.disks = disks;
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/42e25a22/api/src/com/cloud/vm/VirtualMachineProfile.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/vm/VirtualMachineProfile.java b/api/src/com/cloud/vm/VirtualMachineProfile.java
index 33a9171..6861372 100644
--- a/api/src/com/cloud/vm/VirtualMachineProfile.java
+++ b/api/src/com/cloud/vm/VirtualMachineProfile.java
@@ -19,6 +19,8 @@ package com.cloud.vm;
import java.util.List;
import java.util.Map;
+import com.cloud.agent.api.to.DataTO;
+import com.cloud.agent.api.to.DiskTO;
import com.cloud.agent.api.to.VolumeTO;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.offering.ServiceOffering;
@@ -111,11 +113,11 @@ public interface VirtualMachineProfile<T extends VirtualMachine> {
List<NicProfile> getNics();
- List<VolumeTO> getDisks();
+ List<DiskTO> getDisks();
void addNic(int index, NicProfile nic);
- void addDisk(int index, VolumeTO disk);
+ void addDisk(int index, DiskTO disk);
StringBuilder getBootArgsBuilder();
@@ -125,7 +127,7 @@ public interface VirtualMachineProfile<T extends VirtualMachine> {
void addNic(NicProfile nic);
- void addDisk(VolumeTO disk);
+ void addDisk(DiskTO disk);
VirtualMachine.Type getType();
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/42e25a22/core/src/com/cloud/serializer/GsonHelper.java
----------------------------------------------------------------------
diff --git a/core/src/com/cloud/serializer/GsonHelper.java b/core/src/com/cloud/serializer/GsonHelper.java
index 5656d91..54b6b17 100644
--- a/core/src/com/cloud/serializer/GsonHelper.java
+++ b/core/src/com/cloud/serializer/GsonHelper.java
@@ -20,13 +20,13 @@ package com.cloud.serializer;
import java.util.List;
-import org.apache.cloudstack.engine.subsystem.api.storage.DataTO;
import org.apache.log4j.Logger;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.Command;
import com.cloud.agent.api.SecStorageFirewallCfgCommand.PortConfig;
import com.cloud.agent.api.to.DataStoreTO;
+import com.cloud.agent.api.to.DataTO;
import com.cloud.agent.transport.ArrayTypeAdaptor;
import com.cloud.agent.transport.InterfaceTypeAdaptor;
import com.cloud.agent.transport.LoggingExclusionStrategy;
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/42e25a22/core/src/com/cloud/storage/resource/NfsSecondaryStorageResource.java
----------------------------------------------------------------------
diff --git a/core/src/com/cloud/storage/resource/NfsSecondaryStorageResource.java b/core/src/com/cloud/storage/resource/NfsSecondaryStorageResource.java
index 03e822e..36b6bbc 100755
--- a/core/src/com/cloud/storage/resource/NfsSecondaryStorageResource.java
+++ b/core/src/com/cloud/storage/resource/NfsSecondaryStorageResource.java
@@ -46,8 +46,6 @@ import java.util.concurrent.Callable;
import javax.naming.ConfigurationException;
-import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType;
-import org.apache.cloudstack.engine.subsystem.api.storage.DataTO;
import org.apache.cloudstack.storage.command.CopyCmdAnswer;
import org.apache.cloudstack.storage.command.CopyCommand;
import org.apache.cloudstack.storage.command.DownloadCommand;
@@ -97,7 +95,9 @@ import com.cloud.agent.api.storage.ListVolumeAnswer;
import com.cloud.agent.api.storage.ListVolumeCommand;
import com.cloud.agent.api.storage.UploadCommand;
import com.cloud.agent.api.storage.ssCommand;
+import com.cloud.agent.api.to.DataObjectType;
import com.cloud.agent.api.to.DataStoreTO;
+import com.cloud.agent.api.to.DataTO;
import com.cloud.agent.api.to.NfsTO;
import com.cloud.agent.api.to.S3TO;
import com.cloud.agent.api.to.SwiftTO;
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/42e25a22/core/src/com/cloud/storage/resource/StorageProcessor.java
----------------------------------------------------------------------
diff --git a/core/src/com/cloud/storage/resource/StorageProcessor.java b/core/src/com/cloud/storage/resource/StorageProcessor.java
new file mode 100644
index 0000000..ec965ed
--- /dev/null
+++ b/core/src/com/cloud/storage/resource/StorageProcessor.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package com.cloud.storage.resource;
+
+import org.apache.cloudstack.storage.command.AttachCommand;
+import org.apache.cloudstack.storage.command.CopyCommand;
+import org.apache.cloudstack.storage.command.CreateObjectCommand;
+import org.apache.cloudstack.storage.command.DeleteCommand;
+import org.apache.cloudstack.storage.command.DettachCommand;
+
+import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.to.DataTO;
+import com.cloud.agent.api.to.DiskTO;
+
+public interface StorageProcessor {
+ public Answer copyTemplateToPrimaryStorage(CopyCommand cmd);
+ public Answer cloneVolumeFromBaseTemplate(CopyCommand cmd);
+ public Answer copyVolumeFromImageCacheToPrimary(CopyCommand cmd);
+ public Answer copyVolumeFromPrimaryToSecondary(CopyCommand cmd);
+ public Answer createTemplateFromVolume(CopyCommand cmd);
+ public Answer backupSnasphot(CopyCommand cmd);
+ public Answer attachIso(AttachCommand cmd);
+ public Answer attachVolume(AttachCommand cmd);
+ public Answer dettachIso(DettachCommand cmd);
+ public Answer dettachVolume(DettachCommand cmd);
+ public Answer createVolume(CreateObjectCommand cmd);
+ public Answer createSnapshot(CreateObjectCommand cmd);
+ public Answer deleteVolume(DeleteCommand cmd);
+}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/42e25a22/core/src/com/cloud/storage/resource/StorageSubsystemCommandHandler.java
----------------------------------------------------------------------
diff --git a/core/src/com/cloud/storage/resource/StorageSubsystemCommandHandler.java b/core/src/com/cloud/storage/resource/StorageSubsystemCommandHandler.java
new file mode 100644
index 0000000..5ac601e
--- /dev/null
+++ b/core/src/com/cloud/storage/resource/StorageSubsystemCommandHandler.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package com.cloud.storage.resource;
+
+import org.apache.cloudstack.storage.command.StorageSubSystemCommand;
+
+import com.cloud.agent.api.Answer;
+
+public interface StorageSubsystemCommandHandler {
+ public Answer handleStorageCommands(StorageSubSystemCommand command);
+}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/42e25a22/core/src/com/cloud/storage/resource/StorageSubsystemCommandHandlerBase.java
----------------------------------------------------------------------
diff --git a/core/src/com/cloud/storage/resource/StorageSubsystemCommandHandlerBase.java b/core/src/com/cloud/storage/resource/StorageSubsystemCommandHandlerBase.java
new file mode 100644
index 0000000..8f76e93
--- /dev/null
+++ b/core/src/com/cloud/storage/resource/StorageSubsystemCommandHandlerBase.java
@@ -0,0 +1,135 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package com.cloud.storage.resource;
+
+import org.apache.cloudstack.storage.command.AttachCommand;
+import org.apache.cloudstack.storage.command.CopyCommand;
+import org.apache.cloudstack.storage.command.CreateObjectAnswer;
+import org.apache.cloudstack.storage.command.CreateObjectCommand;
+import org.apache.cloudstack.storage.command.DeleteCommand;
+import org.apache.cloudstack.storage.command.DettachCommand;
+import org.apache.cloudstack.storage.command.StorageSubSystemCommand;
+import org.apache.log4j.Logger;
+
+import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.Command;
+import com.cloud.agent.api.to.DataObjectType;
+import com.cloud.agent.api.to.DataStoreTO;
+import com.cloud.agent.api.to.DataTO;
+import com.cloud.agent.api.to.DiskTO;
+import com.cloud.agent.api.to.NfsTO;
+import com.cloud.storage.DataStoreRole;
+import com.cloud.storage.Volume;
+
+public class StorageSubsystemCommandHandlerBase implements StorageSubsystemCommandHandler {
+ private static final Logger s_logger = Logger.getLogger(StorageSubsystemCommandHandlerBase.class);
+ private StorageProcessor processor;
+ public StorageSubsystemCommandHandlerBase(StorageProcessor processor) {
+ this.processor = processor;
+ }
+ @Override
+ public Answer handleStorageCommands(StorageSubSystemCommand command) {
+ if (command instanceof CopyCommand) {
+ return this.execute((CopyCommand)command);
+ } else if (command instanceof CreateObjectCommand) {
+ return execute((CreateObjectCommand) command);
+ } else if (command instanceof DeleteCommand) {
+ return execute((DeleteCommand)command);
+ } else if (command instanceof AttachCommand) {
+ return execute((AttachCommand)command);
+ } else if (command instanceof DettachCommand) {
+ return execute((DettachCommand)command);
+ }
+ return new Answer((Command)command, false, "not implemented yet");
+ }
+
+ protected Answer execute(CopyCommand cmd) {
+ DataTO srcData = cmd.getSrcTO();
+ DataTO destData = cmd.getDestTO();
+ DataStoreTO srcDataStore = srcData.getDataStore();
+ DataStoreTO destDataStore = destData.getDataStore();
+
+ if ((srcData.getObjectType() == DataObjectType.TEMPLATE) && (srcDataStore instanceof NfsTO) && (destData.getDataStore().getRole() == DataStoreRole.Primary)) {
+ //copy template to primary storage
+ return processor.copyTemplateToPrimaryStorage(cmd);
+ } else if (srcData.getObjectType() == DataObjectType.TEMPLATE && srcDataStore.getRole() == DataStoreRole.Primary && destDataStore.getRole() == DataStoreRole.Primary) {
+ //clone template to a volume
+ return processor.cloneVolumeFromBaseTemplate(cmd);
+ } else if (srcData.getObjectType() == DataObjectType.VOLUME && (srcData.getDataStore().getRole() == DataStoreRole.ImageCache || srcDataStore.getRole() == DataStoreRole.Image)) {
+ //copy volume from image cache to primary
+ return processor.copyVolumeFromImageCacheToPrimary(cmd);
+ } else if (srcData.getObjectType() == DataObjectType.VOLUME && srcData.getDataStore().getRole() == DataStoreRole.Primary) {
+ if (destData.getObjectType() == DataObjectType.VOLUME) {
+ return processor.copyVolumeFromPrimaryToSecondary(cmd);
+ } else if (destData.getObjectType() == DataObjectType.TEMPLATE) {
+ return processor.createTemplateFromVolume(cmd);
+ }
+ } else if (srcData.getObjectType() == DataObjectType.SNAPSHOT && srcData.getDataStore().getRole() == DataStoreRole.Primary) {
+ return processor.backupSnasphot(cmd);
+ }
+
+ return new Answer(cmd, false, "not implemented yet");
+ }
+
+
+ protected Answer execute(CreateObjectCommand cmd) {
+ DataTO data = cmd.getData();
+ try {
+ if (data.getObjectType() == DataObjectType.VOLUME) {
+ return processor.createVolume(cmd);
+ } else if (data.getObjectType() == DataObjectType.SNAPSHOT) {
+ return processor.createSnapshot(cmd);
+ }
+ return new CreateObjectAnswer("not supported type");
+ } catch (Exception e) {
+ s_logger.debug("Failed to create object: " + data.getObjectType() + ": " + e.toString());
+ return new CreateObjectAnswer(e.toString());
+ }
+ }
+
+ protected Answer execute(DeleteCommand cmd) {
+ DataTO data = cmd.getData();
+ Answer answer = null;
+ if (data.getObjectType() == DataObjectType.VOLUME) {
+ answer = processor.deleteVolume(cmd);
+ } else {
+ answer = new Answer(cmd, false, "unsupported type");
+ }
+
+ return answer;
+ }
+
+ protected Answer execute(AttachCommand cmd) {
+ DiskTO disk = cmd.getDisk();
+ if (disk.getType() == Volume.Type.ISO) {
+ return processor.attachIso(cmd);
+ } else {
+ return processor.attachVolume(cmd);
+ }
+ }
+
+ protected Answer execute(DettachCommand cmd) {
+ DiskTO disk = cmd.getDisk();
+ if (disk.getType() == Volume.Type.ISO) {
+ return processor.dettachIso(cmd);
+ } else {
+ return processor.dettachVolume(cmd);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/42e25a22/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataObject.java
----------------------------------------------------------------------
diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataObject.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataObject.java
index 8ffed6a..7610bca 100644
--- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataObject.java
+++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataObject.java
@@ -19,6 +19,8 @@
package org.apache.cloudstack.engine.subsystem.api.storage;
import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.to.DataObjectType;
+import com.cloud.agent.api.to.DataTO;
public interface DataObject {
public long getId();
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/42e25a22/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataObjectType.java
----------------------------------------------------------------------
diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataObjectType.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataObjectType.java
deleted file mode 100644
index b4d1a57..0000000
--- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataObjectType.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.cloudstack.engine.subsystem.api.storage;
-
-public enum DataObjectType {
- VOLUME,
- SNAPSHOT,
- TEMPLATE
-}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/42e25a22/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreDriver.java
----------------------------------------------------------------------
diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreDriver.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreDriver.java
index cd2dc86..5ed9ab8 100644
--- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreDriver.java
+++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreDriver.java
@@ -24,6 +24,7 @@ import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
import org.apache.cloudstack.storage.command.CommandResult;
import com.cloud.agent.api.to.DataStoreTO;
+import com.cloud.agent.api.to.DataTO;
public interface DataStoreDriver {
public String grantAccess(DataObject data, EndPoint ep);
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/42e25a22/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataTO.java
----------------------------------------------------------------------
diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataTO.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataTO.java
deleted file mode 100644
index 9e26894..0000000
--- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataTO.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.cloudstack.engine.subsystem.api.storage;
-
-import com.cloud.agent.api.to.DataStoreTO;
-
-public interface DataTO {
- public DataObjectType getObjectType();
- public DataStoreTO getDataStore();
- /**
- * @return
- */
- String getPath();
-}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/42e25a22/engine/api/src/org/apache/cloudstack/storage/command/AttachAnswer.java
----------------------------------------------------------------------
diff --git a/engine/api/src/org/apache/cloudstack/storage/command/AttachAnswer.java b/engine/api/src/org/apache/cloudstack/storage/command/AttachAnswer.java
new file mode 100644
index 0000000..1ddcd7d
--- /dev/null
+++ b/engine/api/src/org/apache/cloudstack/storage/command/AttachAnswer.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cloudstack.storage.command;
+
+import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.to.DiskTO;
+
+public class AttachAnswer extends Answer {
+ private DiskTO disk;
+ public AttachAnswer() {
+ super(null);
+ }
+
+ public AttachAnswer(DiskTO disk) {
+ this.setDisk(disk);
+ }
+ public AttachAnswer(String errMsg) {
+ super(null, false, errMsg);
+ }
+
+ public DiskTO getDisk() {
+ return disk;
+ }
+
+ public void setDisk(DiskTO disk) {
+ this.disk = disk;
+ }
+}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/42e25a22/engine/api/src/org/apache/cloudstack/storage/command/AttachCommand.java
----------------------------------------------------------------------
diff --git a/engine/api/src/org/apache/cloudstack/storage/command/AttachCommand.java b/engine/api/src/org/apache/cloudstack/storage/command/AttachCommand.java
new file mode 100644
index 0000000..fa205a5
--- /dev/null
+++ b/engine/api/src/org/apache/cloudstack/storage/command/AttachCommand.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cloudstack.storage.command;
+
+
+import com.cloud.agent.api.Command;
+import com.cloud.agent.api.to.DiskTO;
+
+public class AttachCommand extends Command implements StorageSubSystemCommand {
+ private DiskTO disk;
+ private String vmName;
+
+ public AttachCommand(DiskTO disk, String vmName) {
+ this.disk = disk;
+ this.vmName = vmName;
+ }
+
+ @Override
+ public boolean executeInSequence() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+ public DiskTO getDisk() {
+ return disk;
+ }
+ public void setDisk(DiskTO disk) {
+ this.disk = disk;
+ }
+ public String getVmName() {
+ return vmName;
+ }
+ public void setVmName(String vmName) {
+ this.vmName = vmName;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/42e25a22/engine/api/src/org/apache/cloudstack/storage/command/CopyCmdAnswer.java
----------------------------------------------------------------------
diff --git a/engine/api/src/org/apache/cloudstack/storage/command/CopyCmdAnswer.java b/engine/api/src/org/apache/cloudstack/storage/command/CopyCmdAnswer.java
index 3612cf9..132832a 100644
--- a/engine/api/src/org/apache/cloudstack/storage/command/CopyCmdAnswer.java
+++ b/engine/api/src/org/apache/cloudstack/storage/command/CopyCmdAnswer.java
@@ -17,9 +17,9 @@
package org.apache.cloudstack.storage.command;
-import org.apache.cloudstack.engine.subsystem.api.storage.DataTO;
import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.to.DataTO;
public class CopyCmdAnswer extends Answer {
private DataTO newData;
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/42e25a22/engine/api/src/org/apache/cloudstack/storage/command/CopyCommand.java
----------------------------------------------------------------------
diff --git a/engine/api/src/org/apache/cloudstack/storage/command/CopyCommand.java b/engine/api/src/org/apache/cloudstack/storage/command/CopyCommand.java
index 5bceb03..d512e60 100644
--- a/engine/api/src/org/apache/cloudstack/storage/command/CopyCommand.java
+++ b/engine/api/src/org/apache/cloudstack/storage/command/CopyCommand.java
@@ -16,9 +16,9 @@
// under the License.
package org.apache.cloudstack.storage.command;
-import org.apache.cloudstack.engine.subsystem.api.storage.DataTO;
import com.cloud.agent.api.Command;
+import com.cloud.agent.api.to.DataTO;
public class CopyCommand extends Command implements StorageSubSystemCommand {
private DataTO srcTO;
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/42e25a22/engine/api/src/org/apache/cloudstack/storage/command/CreateObjectAnswer.java
----------------------------------------------------------------------
diff --git a/engine/api/src/org/apache/cloudstack/storage/command/CreateObjectAnswer.java b/engine/api/src/org/apache/cloudstack/storage/command/CreateObjectAnswer.java
index ddd678a..2c174e4 100644
--- a/engine/api/src/org/apache/cloudstack/storage/command/CreateObjectAnswer.java
+++ b/engine/api/src/org/apache/cloudstack/storage/command/CreateObjectAnswer.java
@@ -18,9 +18,9 @@
*/
package org.apache.cloudstack.storage.command;
-import org.apache.cloudstack.engine.subsystem.api.storage.DataTO;
import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.to.DataTO;
public class CreateObjectAnswer extends Answer {
private DataTO data;
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/42e25a22/engine/api/src/org/apache/cloudstack/storage/command/CreateObjectCommand.java
----------------------------------------------------------------------
diff --git a/engine/api/src/org/apache/cloudstack/storage/command/CreateObjectCommand.java b/engine/api/src/org/apache/cloudstack/storage/command/CreateObjectCommand.java
index 6a72277..dfadc2d 100644
--- a/engine/api/src/org/apache/cloudstack/storage/command/CreateObjectCommand.java
+++ b/engine/api/src/org/apache/cloudstack/storage/command/CreateObjectCommand.java
@@ -18,9 +18,9 @@
*/
package org.apache.cloudstack.storage.command;
-import org.apache.cloudstack.engine.subsystem.api.storage.DataTO;
import com.cloud.agent.api.Command;
+import com.cloud.agent.api.to.DataTO;
public class CreateObjectCommand extends Command implements StorageSubSystemCommand {
private DataTO data;
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/42e25a22/engine/api/src/org/apache/cloudstack/storage/command/DeleteCommand.java
----------------------------------------------------------------------
diff --git a/engine/api/src/org/apache/cloudstack/storage/command/DeleteCommand.java b/engine/api/src/org/apache/cloudstack/storage/command/DeleteCommand.java
index 3335848..41af42c 100644
--- a/engine/api/src/org/apache/cloudstack/storage/command/DeleteCommand.java
+++ b/engine/api/src/org/apache/cloudstack/storage/command/DeleteCommand.java
@@ -18,9 +18,9 @@
*/
package org.apache.cloudstack.storage.command;
-import org.apache.cloudstack.engine.subsystem.api.storage.DataTO;
import com.cloud.agent.api.Command;
+import com.cloud.agent.api.to.DataTO;
public class DeleteCommand extends Command implements StorageSubSystemCommand {
private DataTO data;
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/42e25a22/engine/api/src/org/apache/cloudstack/storage/command/DettachAnswer.java
----------------------------------------------------------------------
diff --git a/engine/api/src/org/apache/cloudstack/storage/command/DettachAnswer.java b/engine/api/src/org/apache/cloudstack/storage/command/DettachAnswer.java
new file mode 100644
index 0000000..9019e0c
--- /dev/null
+++ b/engine/api/src/org/apache/cloudstack/storage/command/DettachAnswer.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cloudstack.storage.command;
+
+import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.to.DiskTO;
+
+public class DettachAnswer extends Answer {
+ private DiskTO disk;
+ public DettachAnswer() {
+ super(null);
+ }
+
+ public DettachAnswer(DiskTO disk) {
+ this.setDisk(disk);
+ }
+ public DettachAnswer(String errMsg) {
+ super(null, false, errMsg);
+ }
+
+ public DiskTO getDisk() {
+ return disk;
+ }
+
+ public void setDisk(DiskTO disk) {
+ this.disk = disk;
+ }
+}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/42e25a22/engine/api/src/org/apache/cloudstack/storage/command/DettachCommand.java
----------------------------------------------------------------------
diff --git a/engine/api/src/org/apache/cloudstack/storage/command/DettachCommand.java b/engine/api/src/org/apache/cloudstack/storage/command/DettachCommand.java
new file mode 100644
index 0000000..c435e10
--- /dev/null
+++ b/engine/api/src/org/apache/cloudstack/storage/command/DettachCommand.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cloudstack.storage.command;
+
+import com.cloud.agent.api.Command;
+import com.cloud.agent.api.to.DiskTO;
+
+public class DettachCommand extends Command implements StorageSubSystemCommand {
+ private DiskTO disk;
+ private String vmName;
+
+ public DettachCommand(DiskTO disk, String vmName) {
+ this.disk = disk;
+ this.vmName = vmName;
+ }
+
+ @Override
+ public boolean executeInSequence() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+ public DiskTO getDisk() {
+ return disk;
+ }
+ public void setDisk(DiskTO disk) {
+ this.disk = disk;
+ }
+ public String getVmName() {
+ return vmName;
+ }
+ public void setVmName(String vmName) {
+ this.vmName = vmName;
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/42e25a22/engine/api/src/org/apache/cloudstack/storage/to/PrimaryDataStoreTO.java
----------------------------------------------------------------------
diff --git a/engine/api/src/org/apache/cloudstack/storage/to/PrimaryDataStoreTO.java b/engine/api/src/org/apache/cloudstack/storage/to/PrimaryDataStoreTO.java
index cf9448b..c3ce0e0 100644
--- a/engine/api/src/org/apache/cloudstack/storage/to/PrimaryDataStoreTO.java
+++ b/engine/api/src/org/apache/cloudstack/storage/to/PrimaryDataStoreTO.java
@@ -20,17 +20,26 @@ import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreInfo;
import com.cloud.agent.api.to.DataStoreTO;
import com.cloud.storage.DataStoreRole;
+import com.cloud.storage.Storage.StoragePoolType;
public class PrimaryDataStoreTO implements DataStoreTO {
private final String uuid;
private final String name;
private String type;
private final long id;
+ private StoragePoolType poolType;
+ private String host;
+ private String path;
+ private int port;
public PrimaryDataStoreTO(PrimaryDataStoreInfo dataStore) {
this.uuid = dataStore.getUuid();
this.name = dataStore.getName();
// this.type = dataStore.getType();
this.id = dataStore.getId();
+ this.setPoolType(dataStore.getPoolType());
+ this.setHost(dataStore.getHostAddress());
+ this.setPath(dataStore.getPath());
+ this.setPort(dataStore.getPort());
}
public long getId() {
@@ -53,4 +62,36 @@ public class PrimaryDataStoreTO implements DataStoreTO {
public DataStoreRole getRole() {
return DataStoreRole.Primary;
}
+
+ public StoragePoolType getPoolType() {
+ return poolType;
+ }
+
+ public void setPoolType(StoragePoolType poolType) {
+ this.poolType = poolType;
+ }
+
+ public String getHost() {
+ return host;
+ }
+
+ public void setHost(String host) {
+ this.host = host;
+ }
+
+ public String getPath() {
+ return path;
+ }
+
+ public void setPath(String path) {
+ this.path = path;
+ }
+
+ public int getPort() {
+ return port;
+ }
+
+ public void setPort(int port) {
+ this.port = port;
+ }
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/42e25a22/engine/api/src/org/apache/cloudstack/storage/to/SnapshotObjectTO.java
----------------------------------------------------------------------
diff --git a/engine/api/src/org/apache/cloudstack/storage/to/SnapshotObjectTO.java b/engine/api/src/org/apache/cloudstack/storage/to/SnapshotObjectTO.java
index ed4cbe1..a2e336b 100644
--- a/engine/api/src/org/apache/cloudstack/storage/to/SnapshotObjectTO.java
+++ b/engine/api/src/org/apache/cloudstack/storage/to/SnapshotObjectTO.java
@@ -1,10 +1,10 @@
package org.apache.cloudstack.storage.to;
-import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType;
-import org.apache.cloudstack.engine.subsystem.api.storage.DataTO;
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
+import com.cloud.agent.api.to.DataObjectType;
import com.cloud.agent.api.to.DataStoreTO;
+import com.cloud.agent.api.to.DataTO;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
public class SnapshotObjectTO implements DataTO {
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/42e25a22/engine/api/src/org/apache/cloudstack/storage/to/TemplateObjectTO.java
----------------------------------------------------------------------
diff --git a/engine/api/src/org/apache/cloudstack/storage/to/TemplateObjectTO.java b/engine/api/src/org/apache/cloudstack/storage/to/TemplateObjectTO.java
index aad5d71..14577ef 100644
--- a/engine/api/src/org/apache/cloudstack/storage/to/TemplateObjectTO.java
+++ b/engine/api/src/org/apache/cloudstack/storage/to/TemplateObjectTO.java
@@ -16,13 +16,13 @@
// under the License.
package org.apache.cloudstack.storage.to;
-import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType;
-import org.apache.cloudstack.engine.subsystem.api.storage.DataTO;
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.disktype.DiskFormat;
import org.apache.cloudstack.storage.image.datastore.ImageStoreInfo;
+import com.cloud.agent.api.to.DataObjectType;
import com.cloud.agent.api.to.DataStoreTO;
+import com.cloud.agent.api.to.DataTO;
import com.cloud.storage.Storage.ImageFormat;
import com.cloud.template.VirtualMachineTemplate;
@@ -38,6 +38,7 @@ public class TemplateObjectTO implements DataTO {
private String displayText;
private DataStoreTO imageDataStore;
private String name;
+ private String guestOsType;
public TemplateObjectTO() {
@@ -151,5 +152,11 @@ public class TemplateObjectTO implements DataTO {
this.imageDataStore = imageDataStore;
}
+ public String getGuestOsType() {
+ return guestOsType;
+ }
+ public void setGuestOsType(String guestOsType) {
+ this.guestOsType = guestOsType;
+ }
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/42e25a22/engine/api/src/org/apache/cloudstack/storage/to/VolumeObjectTO.java
----------------------------------------------------------------------
diff --git a/engine/api/src/org/apache/cloudstack/storage/to/VolumeObjectTO.java b/engine/api/src/org/apache/cloudstack/storage/to/VolumeObjectTO.java
index 3f7a8f1..0ae2bc7 100644
--- a/engine/api/src/org/apache/cloudstack/storage/to/VolumeObjectTO.java
+++ b/engine/api/src/org/apache/cloudstack/storage/to/VolumeObjectTO.java
@@ -16,17 +16,18 @@
// under the License.
package org.apache.cloudstack.storage.to;
-import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType;
-import org.apache.cloudstack.engine.subsystem.api.storage.DataTO;
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.disktype.DiskFormat;
import org.apache.cloudstack.engine.subsystem.api.storage.type.VolumeType;
+import com.cloud.agent.api.to.DataObjectType;
import com.cloud.agent.api.to.DataStoreTO;
+import com.cloud.agent.api.to.DataTO;
+import com.cloud.storage.Volume;
public class VolumeObjectTO implements DataTO {
private String uuid;
- private VolumeType volumeType;
+ private Volume.Type volumeType;
private DiskFormat diskType;
private DataStoreTO dataStore;
private String name;
@@ -35,6 +36,8 @@ public class VolumeObjectTO implements DataTO {
private Long volumeId;
private String vmName;
private long accountId;
+ private String chainInfo;
+ private long id;
public VolumeObjectTO() {
@@ -52,6 +55,9 @@ public class VolumeObjectTO implements DataTO {
this.vmName = volume.getAttachedVmName();
this.size = volume.getSize();
this.setVolumeId(volume.getId());
+ this.chainInfo = volume.getChainInfo();
+ this.volumeType = volume.getVolumeType();
+ this.setId(volume.getId());
}
public String getUuid() {
@@ -62,7 +68,7 @@ public class VolumeObjectTO implements DataTO {
return this.path;
}
- public VolumeType getVolumeType() {
+ public Volume.Type getVolumeType() {
return this.volumeType;
}
@@ -130,5 +136,21 @@ public class VolumeObjectTO implements DataTO {
this.vmName = vmName;
}
+ public String getChainInfo() {
+ return chainInfo;
+ }
+
+ public void setChainInfo(String chainInfo) {
+ this.chainInfo = chainInfo;
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(long id) {
+ this.id = id;
+ }
+
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/42e25a22/engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java
----------------------------------------------------------------------
diff --git a/engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java b/engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java
index 560c34f..4e9b02b 100644
--- a/engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java
+++ b/engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java
@@ -26,10 +26,8 @@ import javax.inject.Inject;
import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
import org.apache.cloudstack.engine.subsystem.api.storage.DataMotionStrategy;
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
-import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
-import org.apache.cloudstack.engine.subsystem.api.storage.DataTO;
import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint;
import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector;
@@ -61,7 +59,9 @@ import com.cloud.agent.api.UpgradeSnapshotCommand;
import com.cloud.agent.api.storage.CopyVolumeAnswer;
import com.cloud.agent.api.storage.CopyVolumeCommand;
import com.cloud.agent.api.storage.CreatePrivateTemplateAnswer;
+import com.cloud.agent.api.to.DataObjectType;
import com.cloud.agent.api.to.DataStoreTO;
+import com.cloud.agent.api.to.DataTO;
import com.cloud.agent.api.to.NfsTO;
import com.cloud.agent.api.to.S3TO;
import com.cloud.agent.api.to.SwiftTO;
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/42e25a22/engine/storage/image/src/org/apache/cloudstack/storage/image/TemplateDataFactoryImpl.java
----------------------------------------------------------------------
diff --git a/engine/storage/image/src/org/apache/cloudstack/storage/image/TemplateDataFactoryImpl.java b/engine/storage/image/src/org/apache/cloudstack/storage/image/TemplateDataFactoryImpl.java
index 6f20426..09c79b2 100644
--- a/engine/storage/image/src/org/apache/cloudstack/storage/image/TemplateDataFactoryImpl.java
+++ b/engine/storage/image/src/org/apache/cloudstack/storage/image/TemplateDataFactoryImpl.java
@@ -33,6 +33,7 @@ import org.springframework.stereotype.Component;
import com.cloud.storage.DataStoreRole;
import com.cloud.storage.VMTemplateStoragePoolVO;
+import com.cloud.storage.VMTemplateStorageResourceAssoc;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.storage.dao.VMTemplatePoolDao;
@@ -89,6 +90,16 @@ public class TemplateDataFactoryImpl implements TemplateDataFactory {
}
return this.getTemplate(templateId, store);
}
+
+ @Override
+ public TemplateInfo getTemplate(long templateId, long zoneId) {
+ TemplateDataStoreVO tmplStore = templateStoreDao.findByTemplateZoneDownloadStatus(templateId, zoneId, VMTemplateStorageResourceAssoc.Status.DOWNLOADED);
+ if (tmplStore != null) {
+ DataStore store = this.storeMgr.getDataStore(tmplStore.getDataStoreId(), DataStoreRole.Image);
+ return this.getTemplate(templateId, store);
+ }
+ return null;
+ }
@Override
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/42e25a22/engine/storage/image/src/org/apache/cloudstack/storage/image/store/TemplateObject.java
----------------------------------------------------------------------
diff --git a/engine/storage/image/src/org/apache/cloudstack/storage/image/store/TemplateObject.java b/engine/storage/image/src/org/apache/cloudstack/storage/image/store/TemplateObject.java
index daf8568..12e29e7 100644
--- a/engine/storage/image/src/org/apache/cloudstack/storage/image/store/TemplateObject.java
+++ b/engine/storage/image/src/org/apache/cloudstack/storage/image/store/TemplateObject.java
@@ -24,9 +24,7 @@ import java.util.Map;
import javax.inject.Inject;
import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore;
-import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
-import org.apache.cloudstack.engine.subsystem.api.storage.DataTO;
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event;
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateEvent;
@@ -40,6 +38,8 @@ import org.apache.cloudstack.storage.to.TemplateObjectTO;
import org.apache.log4j.Logger;
import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.to.DataObjectType;
+import com.cloud.agent.api.to.DataTO;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.storage.DataStoreRole;
import com.cloud.storage.Storage.ImageFormat;
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/42e25a22/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotObject.java
----------------------------------------------------------------------
diff --git a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotObject.java b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotObject.java
index f5800c1..423d8c9 100644
--- a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotObject.java
+++ b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotObject.java
@@ -22,9 +22,7 @@ import java.util.Date;
import javax.inject.Inject;
-import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
-import org.apache.cloudstack.engine.subsystem.api.storage.DataTO;
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotDataFactory;
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
@@ -39,6 +37,8 @@ import org.apache.cloudstack.storage.to.SnapshotObjectTO;
import org.apache.log4j.Logger;
import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.to.DataObjectType;
+import com.cloud.agent.api.to.DataTO;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.storage.Snapshot;
import com.cloud.storage.SnapshotVO;
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/42e25a22/engine/storage/src/org/apache/cloudstack/storage/datastore/ObjectInDataStoreManager.java
----------------------------------------------------------------------
diff --git a/engine/storage/src/org/apache/cloudstack/storage/datastore/ObjectInDataStoreManager.java b/engine/storage/src/org/apache/cloudstack/storage/datastore/ObjectInDataStoreManager.java
index ca9f22c..f49929f 100644
--- a/engine/storage/src/org/apache/cloudstack/storage/datastore/ObjectInDataStoreManager.java
+++ b/engine/storage/src/org/apache/cloudstack/storage/datastore/ObjectInDataStoreManager.java
@@ -18,10 +18,10 @@ package org.apache.cloudstack.storage.datastore;
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore;
-import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event;
+import com.cloud.agent.api.to.DataObjectType;
import com.cloud.storage.DataStoreRole;
import com.cloud.utils.fsm.NoTransitionException;
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/42e25a22/engine/storage/src/org/apache/cloudstack/storage/datastore/ObjectInDataStoreManagerImpl.java
----------------------------------------------------------------------
diff --git a/engine/storage/src/org/apache/cloudstack/storage/datastore/ObjectInDataStoreManagerImpl.java b/engine/storage/src/org/apache/cloudstack/storage/datastore/ObjectInDataStoreManagerImpl.java
index f0b54e1..4816e51 100644
--- a/engine/storage/src/org/apache/cloudstack/storage/datastore/ObjectInDataStoreManagerImpl.java
+++ b/engine/storage/src/org/apache/cloudstack/storage/datastore/ObjectInDataStoreManagerImpl.java
@@ -20,7 +20,6 @@ import javax.inject.Inject;
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore;
-import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
@@ -42,6 +41,7 @@ import org.apache.cloudstack.storage.db.ObjectInDataStoreVO;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
+import com.cloud.agent.api.to.DataObjectType;
import com.cloud.storage.DataStoreRole;
import com.cloud.storage.VMTemplateStoragePoolVO;
import com.cloud.storage.dao.SnapshotDao;
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/42e25a22/engine/storage/src/org/apache/cloudstack/storage/db/ObjectInDataStoreVO.java
----------------------------------------------------------------------
diff --git a/engine/storage/src/org/apache/cloudstack/storage/db/ObjectInDataStoreVO.java b/engine/storage/src/org/apache/cloudstack/storage/db/ObjectInDataStoreVO.java
index 5b69251..ecf0391 100644
--- a/engine/storage/src/org/apache/cloudstack/storage/db/ObjectInDataStoreVO.java
+++ b/engine/storage/src/org/apache/cloudstack/storage/db/ObjectInDataStoreVO.java
@@ -30,10 +30,10 @@ import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore;
-import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType;
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.State;
+import com.cloud.agent.api.to.DataObjectType;
import com.cloud.storage.DataStoreRole;
import com.cloud.storage.Storage;
import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/42e25a22/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/PrimaryDataStoreImpl.java
----------------------------------------------------------------------
diff --git a/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/PrimaryDataStoreImpl.java b/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/PrimaryDataStoreImpl.java
index 49bfa65..55c5b91 100644
--- a/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/PrimaryDataStoreImpl.java
+++ b/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/PrimaryDataStoreImpl.java
@@ -25,7 +25,6 @@ import javax.inject.Inject;
import org.apache.cloudstack.engine.subsystem.api.storage.ClusterScope;
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
-import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreDriver;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProvider;
import org.apache.cloudstack.engine.subsystem.api.storage.HostScope;
@@ -46,6 +45,7 @@ import org.apache.cloudstack.storage.to.PrimaryDataStoreTO;
import org.apache.cloudstack.storage.volume.VolumeObject;
import org.apache.log4j.Logger;
+import com.cloud.agent.api.to.DataObjectType;
import com.cloud.agent.api.to.DataStoreTO;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.storage.Storage.StoragePoolType;
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/42e25a22/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeObject.java
----------------------------------------------------------------------
diff --git a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeObject.java b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeObject.java
index be7bd12..6754a1d 100644
--- a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeObject.java
+++ b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeObject.java
@@ -21,9 +21,7 @@ import java.util.Date;
import javax.inject.Inject;
import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore;
-import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
-import org.apache.cloudstack.engine.subsystem.api.storage.DataTO;
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
import org.apache.cloudstack.storage.command.CopyCmdAnswer;
@@ -36,6 +34,8 @@ import org.apache.log4j.Logger;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.storage.DownloadAnswer;
+import com.cloud.agent.api.to.DataObjectType;
+import com.cloud.agent.api.to.DataTO;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.storage.DataStoreRole;
import com.cloud.storage.Volume;
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/42e25a22/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java
index 706c9ef..dd92a31 100755
--- a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java
+++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java
@@ -39,11 +39,11 @@ import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
-import java.util.Set;
-import java.util.HashSet;
import java.util.Properties;
+import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
@@ -56,11 +56,13 @@ import java.util.regex.Pattern;
import javax.ejb.Local;
import javax.naming.ConfigurationException;
-import org.apache.log4j.Logger;
-import org.apache.cloudstack.utils.qemu.QemuImg.PhysicalDiskFormat;
+import org.apache.cloudstack.storage.command.StorageSubSystemCommand;
+import org.apache.cloudstack.storage.to.PrimaryDataStoreTO;
import org.apache.cloudstack.utils.qemu.QemuImg;
-import org.apache.cloudstack.utils.qemu.QemuImgFile;
+import org.apache.cloudstack.utils.qemu.QemuImg.PhysicalDiskFormat;
import org.apache.cloudstack.utils.qemu.QemuImgException;
+import org.apache.cloudstack.utils.qemu.QemuImgFile;
+import org.apache.log4j.Logger;
import org.libvirt.Connect;
import org.libvirt.Domain;
import org.libvirt.DomainInfo;
@@ -166,9 +168,13 @@ import com.cloud.agent.api.storage.CreatePrivateTemplateAnswer;
import com.cloud.agent.api.storage.DestroyCommand;
import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer;
import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand;
-import com.cloud.agent.api.storage.ResizeVolumeCommand;
import com.cloud.agent.api.storage.ResizeVolumeAnswer;
+import com.cloud.agent.api.storage.ResizeVolumeCommand;
+import com.cloud.agent.api.to.DataStoreTO;
+import com.cloud.agent.api.to.DataTO;
+import com.cloud.agent.api.to.DiskTO;
import com.cloud.agent.api.to.IpAddressTO;
+import com.cloud.agent.api.to.NfsTO;
import com.cloud.agent.api.to.NicTO;
import com.cloud.agent.api.to.StorageFilerTO;
import com.cloud.agent.api.to.VirtualMachineTO;
@@ -194,11 +200,12 @@ import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.InputDef;
import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.InterfaceDef;
import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.InterfaceDef.hostNicType;
import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.SerialDef;
-import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.VirtioSerialDef;
import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.TermPolicy;
+import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.VirtioSerialDef;
import com.cloud.hypervisor.kvm.storage.KVMPhysicalDisk;
import com.cloud.hypervisor.kvm.storage.KVMStoragePool;
import com.cloud.hypervisor.kvm.storage.KVMStoragePoolManager;
+import com.cloud.hypervisor.kvm.storage.KVMStorageProcessor;
import com.cloud.network.Networks.BroadcastDomainType;
import com.cloud.network.Networks.IsolationType;
import com.cloud.network.Networks.RouterPrivateIpStrategy;
@@ -212,14 +219,16 @@ import com.cloud.storage.Storage.ImageFormat;
import com.cloud.storage.Storage.StoragePoolType;
import com.cloud.storage.StorageLayer;
import com.cloud.storage.Volume;
+import com.cloud.storage.resource.StorageSubsystemCommandHandler;
+import com.cloud.storage.resource.StorageSubsystemCommandHandlerBase;
import com.cloud.storage.template.Processor;
import com.cloud.storage.template.Processor.FormatInfo;
import com.cloud.storage.template.QCOW2Processor;
-import com.cloud.storage.template.TemplateProp;
import com.cloud.storage.template.TemplateLocation;
+import com.cloud.storage.template.TemplateProp;
+import com.cloud.utils.FileUtil;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.Pair;
-import com.cloud.utils.FileUtil;
import com.cloud.utils.PropertiesUtil;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.net.NetUtils;
@@ -345,7 +354,6 @@ ServerResource {
protected String _localStoragePath;
protected String _localStorageUUID;
private final Map <String, String> _pifs = new HashMap<String, String>();
- private final Map<String, Map<String, String>> hostNetInfo = new HashMap<String, Map<String, String>>();
private final Map<String, vmStats> _vmStats = new ConcurrentHashMap<String, vmStats>();
protected boolean _disconnected = true;
@@ -383,6 +391,8 @@ ServerResource {
}
protected BridgeType _bridgeType;
+
+ protected StorageSubsystemCommandHandler storageHandler;
private String getEndIpFromStartIp(String startIp, int numIps) {
String[] tokens = startIp.split("[.]");
@@ -810,6 +820,10 @@ ServerResource {
params.put("libvirt.computing.resource", this);
configureVifDrivers(params);
+
+ KVMStorageProcessor storageProcessor = new KVMStorageProcessor(this._storagePoolMgr, this);
+ storageProcessor.configure(name, params);
+ storageHandler = new StorageSubsystemCommandHandlerBase(storageProcessor);
return true;
}
@@ -958,11 +972,6 @@ ServerResource {
return pif;
}
-
- private String getOvsPif(String bridge) {
- String pif = Script.runSimpleBashScript("ovs-vsctl list-ports " + bridge);
- return pif;
- }
private String matchPifFileInDirectory(String bridgeName){
File f = new File("/sys/devices/virtual/net/" + bridgeName + "/brif");
@@ -1203,6 +1212,8 @@ ServerResource {
return execute((CheckNetworkCommand) cmd);
} else if (cmd instanceof NetworkRulesVmSecondaryIpCommand) {
return execute((NetworkRulesVmSecondaryIpCommand) cmd);
+ } else if (cmd instanceof StorageSubSystemCommand) {
+ return this.storageHandler.handleStorageCommands((StorageSubSystemCommand)cmd);
} else {
s_logger.warn("Unsupported command ");
return Answer.createUnsupportedCommandAnswer(cmd);
@@ -1496,8 +1507,6 @@ ServerResource {
vol.getPoolType(),
vol.getPoolUuid());
pool.deletePhysicalDisk(vol.getPath());
- String vmName = cmd.getVmName();
- String poolPath = pool.getLocalPath();
return new Answer(cmd, true, "Success");
} catch (CloudRuntimeException e) {
s_logger.debug("Failed to delete volume: " + e.toString());
@@ -1606,7 +1615,6 @@ ServerResource {
try {
conn = LibvirtConnection.getConnectionByVmName(routerName);
- Domain vm = getDomain(conn, routerName);
List<InterfaceDef> pluggedNics = getInterfaces(conn, routerName);
InterfaceDef routerNic = null;
@@ -1621,7 +1629,6 @@ ServerResource {
return new SetupGuestNetworkAnswer(cmd, false, "Can not find nic with mac " + nic.getMac() + " for VM " + routerName);
}
- String args = "vpc_guestnw.sh " + routerIP + " -C";
String dev = "eth" + nic.getDeviceId();
String netmask = NetUtils.getSubNet(routerGIP, nic.getNetmask());
String result = _virtRouterResource.assignGuestNetwork(dev, routerIP,
@@ -1640,14 +1647,10 @@ ServerResource {
private SetNetworkACLAnswer execute(SetNetworkACLCommand cmd) {
String[] results = new String[cmd.getRules().length];
- String callResult;
- Connect conn;
- String routerName = cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME);
+
String routerIp = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP);
try {
- conn = LibvirtConnection.getConnectionByVmName(routerName);
- Domain vm = getDomain(conn, routerName);
String [][] rules = cmd.generateFwRules();
String[] aclRules = rules[0];
NicTO nic = cmd.getNic();
@@ -1671,7 +1674,7 @@ ServerResource {
}
return new SetNetworkACLAnswer(cmd, true, results);
- } catch (LibvirtException e) {
+ } catch (Exception e) {
String msg = "SetNetworkACL failed due to " + e.toString();
s_logger.error(msg, e);
return new SetNetworkACLAnswer(cmd, false, results);
@@ -1686,7 +1689,6 @@ ServerResource {
try {
conn = LibvirtConnection.getConnectionByVmName(routerName);
- Domain vm = getDomain(conn, routerName);
Integer devNum = 0;
String pubVlan = pubIP.getVlanId();
List<InterfaceDef> pluggedNics = getInterfaces(conn, routerName);
@@ -1733,7 +1735,6 @@ ServerResource {
try {
conn = LibvirtConnection.getConnectionByVmName(routerName);
IpAddressTO[] ips = cmd.getIpAddresses();
- Domain vm = getDomain(conn, routerName);
Integer devNum = 0;
Map<String, Integer> vlanToNicNum = new HashMap<String, Integer>();
List<InterfaceDef> pluggedNics = getInterfaces(conn, routerName);
@@ -1919,7 +1920,6 @@ ServerResource {
Long volumeId = cmd.getVolumeId();
String secondaryStoragePoolUrl = cmd.getSecondaryStorageUrl();
String snapshotName = cmd.getSnapshotName();
- String snapshotPath = cmd.getVolumePath();
String snapshotDestPath = null;
String snapshotRelPath = null;
String vmName = cmd.getVmName();
@@ -2194,7 +2194,6 @@ ServerResource {
KVMStoragePool secondaryStorage = null;
KVMStoragePool primary = null;
try {
- Connect conn = LibvirtConnection.getConnectionByVmName(cmd.getVmName());
String templateFolder = cmd.getAccountId() + File.separator
+ cmd.getTemplateId() + File.separator;
String templateInstallFolder = "/template/tmpl/" + templateFolder;
@@ -2290,10 +2289,6 @@ ServerResource {
templateInstallFolder + cmd.getUniqueName() + ".qcow2",
info.virtualSize, info.size, cmd.getUniqueName(),
ImageFormat.QCOW2);
- } catch (LibvirtException e) {
- s_logger.debug("Failed to get secondary storage pool: "
- + e.toString());
- return new CreatePrivateTemplateAnswer(cmd, false, e.toString());
} catch (InternalErrorException e) {
return new CreatePrivateTemplateAnswer(cmd, false, e.toString());
} catch (IOException e) {
@@ -2372,7 +2367,6 @@ ServerResource {
}
protected Answer execute(ModifyStoragePoolCommand cmd) {
- String poolType = cmd.getPool().getType().toString();
KVMStoragePool storagepool = _storagePoolMgr.createStoragePool(cmd
.getPool().getUuid(), cmd.getPool().getHost(),
cmd.getPool().getPort(), cmd.getPool().getPath(),
@@ -2700,8 +2694,8 @@ ServerResource {
}
/* setup disks, e.g for iso */
- VolumeTO[] volumes = vm.getDisks();
- for (VolumeTO volume : volumes) {
+ DiskTO[] volumes = vm.getDisks();
+ for (DiskTO volume : volumes) {
if (volume.getType() == Volume.Type.ISO) {
getVolumePath(conn, volume);
}
@@ -3279,10 +3273,14 @@ ServerResource {
}
}
- private String getVolumePath(Connect conn, VolumeTO volume)
+ private String getVolumePath(Connect conn, DiskTO volume)
throws LibvirtException, URISyntaxException {
- if (volume.getType() == Volume.Type.ISO && volume.getPath() != null) {
- String isoPath = volume.getPath();
+ DataTO data = volume.getData();
+ DataStoreTO store = data.getDataStore();
+
+ if (volume.getType() == Volume.Type.ISO && data.getPath() != null) {
+ NfsTO nfsStore = (NfsTO)store;
+ String isoPath = nfsStore.getUrl() + File.separator + data.getPath();
int index = isoPath.lastIndexOf("/");
String path = isoPath.substring(0, index);
String name = isoPath.substring(index + 1);
@@ -3291,26 +3289,28 @@ ServerResource {
KVMPhysicalDisk isoVol = secondaryPool.getPhysicalDisk(name);
return isoVol.getPath();
} else {
- return volume.getPath();
+ return data.getPath();
}
}
protected void createVbd(Connect conn, VirtualMachineTO vmSpec,
String vmName, LibvirtVMDef vm) throws InternalErrorException,
LibvirtException, URISyntaxException {
- List<VolumeTO> disks = Arrays.asList(vmSpec.getDisks());
- Collections.sort(disks, new Comparator<VolumeTO>() {
+ List<DiskTO> disks = Arrays.asList(vmSpec.getDisks());
+ Collections.sort(disks, new Comparator<DiskTO>() {
@Override
- public int compare(VolumeTO arg0, VolumeTO arg1) {
- return arg0.getDeviceId() > arg1.getDeviceId() ? 1 : -1;
+ public int compare(DiskTO arg0, DiskTO arg1) {
+ return arg0.getDiskSeq() > arg1.getDiskSeq() ? 1 : -1;
}
});
- for (VolumeTO volume : disks) {
+ for (DiskTO volume : disks) {
KVMPhysicalDisk physicalDisk = null;
KVMStoragePool pool = null;
- if (volume.getType() == Volume.Type.ISO && volume.getPath() != null) {
- String volPath = volume.getPath();
+ DataTO data = volume.getData();
+ if (volume.getType() == Volume.Type.ISO && data.getPath() != null) {
+ NfsTO nfsStore = (NfsTO)data.getDataStore();
+ String volPath = nfsStore.getUrl() + File.separator + data.getPath();
int index = volPath.lastIndexOf("/");
String volDir = volPath.substring(0, index);
String volName = volPath.substring(index + 1);
@@ -3318,10 +3318,11 @@ ServerResource {
getStoragePoolByURI(volDir);
physicalDisk = secondaryStorage.getPhysicalDisk(volName);
} else if (volume.getType() != Volume.Type.ISO) {
+ PrimaryDataStoreTO store = (PrimaryDataStoreTO)data.getDataStore();
pool = _storagePoolMgr.getStoragePool(
- volume.getPoolType(),
- volume.getPoolUuid());
- physicalDisk = pool.getPhysicalDisk(volume.getPath());
+ store.getPoolType(),
+ store.getUuid());
+ physicalDisk = pool.getPhysicalDisk(data.getPath());
}
String volPath = null;
@@ -3339,7 +3340,7 @@ ServerResource {
disk.defISODisk(volPath);
}
} else {
- int devId = (int) volume.getDeviceId();
+ int devId = volume.getDiskSeq().intValue();
if (pool.getType() == StoragePoolType.RBD) {
/*
@@ -3379,12 +3380,14 @@ ServerResource {
// For LXC, find and add the root filesystem
if (HypervisorType.LXC.toString().toLowerCase().equals(vm.getHvsType())) {
- for (VolumeTO volume : disks) {
+ for (DiskTO volume : disks) {
if (volume.getType() == Volume.Type.ROOT) {
+ DataTO data = volume.getData();
+ PrimaryDataStoreTO store = (PrimaryDataStoreTO)data.getDataStore();
KVMStoragePool pool = _storagePoolMgr.getStoragePool(
- volume.getPoolType(),
- volume.getPoolUuid());
- KVMPhysicalDisk physicalDisk = pool.getPhysicalDisk(volume.getPath());
+ store.getPoolType(),
+ store.getUuid());
+ KVMPhysicalDisk physicalDisk = pool.getPhysicalDisk(data.getPath());
FilesystemDef rootFs = new FilesystemDef(physicalDisk.getPath(), "/");
vm.getDevices().addDevice(rootFs);
break;
@@ -3394,16 +3397,6 @@ ServerResource {
}
- private VolumeTO getVolume(VirtualMachineTO vmSpec, Volume.Type type) {
- VolumeTO volumes[] = vmSpec.getDisks();
- for (VolumeTO volume : volumes) {
- if (volume.getType() == type) {
- return volume;
- }
- }
- return null;
- }
-
private void createVif(LibvirtVMDef vm, NicTO nic)
throws InternalErrorException, LibvirtException {
vm.getDevices().addDevice(
@@ -3432,7 +3425,7 @@ ServerResource {
return new CheckSshAnswer(cmd);
}
- private boolean cleanupDisk(Connect conn, DiskDef disk) {
+ public boolean cleanupDisk(Connect conn, DiskDef disk) {
// need to umount secondary storage
String path = disk.getDiskPath();
String poolUuid = null;
@@ -4237,28 +4230,6 @@ ServerResource {
return parser.getEmulator();
}
- private String getGuestType(Connect conn, String vmName) {
- LibvirtDomainXMLParser parser = new LibvirtDomainXMLParser();
- Domain dm = null;
- try {
- dm = conn.domainLookupByUUID(UUID.nameUUIDFromBytes(vmName
- .getBytes()));
- String xmlDesc = dm.getXMLDesc(0);
- parser.parseDomainXML(xmlDesc);
- return parser.getDescription();
- } catch (LibvirtException e) {
- s_logger.trace("Ignoring libvirt error.", e);
- return null;
- } finally {
- try {
- if (dm != null) {
- dm.free();
- }
- } catch (LibvirtException l) {
- s_logger.trace("Ignoring libvirt error.", l);
- }
- }
- }
boolean isGuestPVEnabled(String guestOS) {
if (guestOS == null) {
@@ -4296,14 +4267,6 @@ ServerResource {
}
}
- private InterfaceDef.nicModel getGuestNicModel(String guestOSType) {
- if (isGuestPVEnabled(guestOSType)) {
- return InterfaceDef.nicModel.VIRTIO;
- } else {
- return InterfaceDef.nicModel.E1000;
- }
- }
-
private DiskDef.diskBus getGuestDiskModel(String guestOSType) {
if (isGuestPVEnabled(guestOSType)) {
return DiskDef.diskBus.VIRTIO;
@@ -4337,7 +4300,7 @@ ServerResource {
}
}
- private Domain getDomain(Connect conn, String vmName)
+ public Domain getDomain(Connect conn, String vmName)
throws LibvirtException {
return conn
.domainLookupByUUID(UUID.nameUUIDFromBytes(vmName.getBytes()));
@@ -4366,7 +4329,7 @@ ServerResource {
}
}
- protected List<DiskDef> getDisks(Connect conn, String vmName) {
+ public List<DiskDef> getDisks(Connect conn, String vmName) {
LibvirtDomainXMLParser parser = new LibvirtDomainXMLParser();
Domain dm = null;
try {
@@ -4396,38 +4359,7 @@ ServerResource {
return command.execute();
}
- private String executeBashScript(String script, OutputInterpreter parser) {
- Script command = new Script("/bin/bash", _timeout, s_logger);
- command.add("-c");
- command.add(script);
- return command.execute(parser);
- }
- private void deletExitingLinkLocalRoutTable(String linkLocalBr) {
- Script command = new Script("/bin/bash", _timeout);
- command.add("-c");
- command.add("ip route | grep " + NetUtils.getLinkLocalCIDR());
- OutputInterpreter.AllLinesParser parser = new OutputInterpreter.AllLinesParser();
- String result = command.execute(parser);
- boolean foundLinkLocalBr = false;
- if (result == null && parser.getLines() != null) {
- String[] lines = parser.getLines().split("\\n");
- for (String line : lines) {
- String[] tokens = line.split(" ");
- if (!tokens[2].equalsIgnoreCase(linkLocalBr)) {
- Script.runSimpleBashScript("ip route del "
- + NetUtils.getLinkLocalCIDR());
- } else {
- foundLinkLocalBr = true;
- }
- }
- }
- if (!foundLinkLocalBr) {
- Script.runSimpleBashScript("ip route add "
- + NetUtils.getLinkLocalCIDR() + " dev " + linkLocalBr
- + " src " + NetUtils.getLinkLocalGateway());
- }
- }
private class vmStats {
long _usedTime;
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/42e25a22/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java
index 9cddb2e..345b4e8 100644
--- a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java
+++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java
@@ -354,7 +354,7 @@ public class LibvirtVMDef {
}
public static class DiskDef {
- enum deviceType {
+ public enum deviceType {
FLOPPY("floppy"), DISK("disk"), CDROM("cdrom");
String _type;
@@ -396,7 +396,7 @@ public class LibvirtVMDef {
}
}
- enum diskBus {
+ public enum diskBus {
IDE("ide"), SCSI("scsi"), VIRTIO("virtio"), XEN("xen"), USB("usb"), UML(
"uml"), FDC("fdc");
String _bus;
@@ -411,7 +411,7 @@ public class LibvirtVMDef {
}
}
- enum diskFmtType {
+ public enum diskFmtType {
RAW("raw"), QCOW2("qcow2");
String _fmtType;
[5/7] refactor kvm/vmware resource code
Posted by ed...@apache.org.
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/42e25a22/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java
new file mode 100644
index 0000000..c3fc0ec
--- /dev/null
+++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java
@@ -0,0 +1,879 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package com.cloud.hypervisor.kvm.storage;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.text.DateFormat;
+import java.text.MessageFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import javax.naming.ConfigurationException;
+
+import org.apache.cloudstack.storage.command.AttachAnswer;
+import org.apache.cloudstack.storage.command.AttachCommand;
+import org.apache.cloudstack.storage.command.CopyCmdAnswer;
+import org.apache.cloudstack.storage.command.CopyCommand;
+import org.apache.cloudstack.storage.command.CreateObjectAnswer;
+import org.apache.cloudstack.storage.command.CreateObjectCommand;
+import org.apache.cloudstack.storage.command.DeleteCommand;
+import org.apache.cloudstack.storage.command.DettachAnswer;
+import org.apache.cloudstack.storage.command.DettachCommand;
+import org.apache.cloudstack.storage.to.PrimaryDataStoreTO;
+import org.apache.cloudstack.storage.to.SnapshotObjectTO;
+import org.apache.cloudstack.storage.to.TemplateObjectTO;
+import org.apache.cloudstack.storage.to.VolumeObjectTO;
+import org.apache.cloudstack.utils.qemu.QemuImg;
+import org.apache.cloudstack.utils.qemu.QemuImgException;
+import org.apache.cloudstack.utils.qemu.QemuImgFile;
+import org.apache.cloudstack.utils.qemu.QemuImg.PhysicalDiskFormat;
+import org.apache.log4j.Logger;
+import org.libvirt.Connect;
+import org.libvirt.Domain;
+import org.libvirt.DomainInfo;
+import org.libvirt.DomainSnapshot;
+import org.libvirt.LibvirtException;
+
+import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.AttachVolumeAnswer;
+import com.cloud.agent.api.BackupSnapshotAnswer;
+import com.cloud.agent.api.ManageSnapshotAnswer;
+import com.cloud.agent.api.ManageSnapshotCommand;
+import com.cloud.agent.api.storage.CreateAnswer;
+import com.cloud.agent.api.storage.CreatePrivateTemplateAnswer;
+import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer;
+import com.cloud.agent.api.to.DataStoreTO;
+import com.cloud.agent.api.to.DataTO;
+import com.cloud.agent.api.to.DiskTO;
+import com.cloud.agent.api.to.NfsTO;
+import com.cloud.agent.api.to.StorageFilerTO;
+import com.cloud.agent.api.to.VolumeTO;
+import com.cloud.exception.InternalErrorException;
+import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
+import com.cloud.hypervisor.kvm.resource.LibvirtConnection;
+import com.cloud.hypervisor.kvm.resource.LibvirtDomainXMLParser;
+import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.DiskDef;
+import com.cloud.storage.JavaStorageLayer;
+import com.cloud.storage.StorageLayer;
+import com.cloud.storage.Storage.ImageFormat;
+import com.cloud.storage.Storage.StoragePoolType;
+import com.cloud.storage.resource.StorageProcessor;
+import com.cloud.storage.template.Processor;
+import com.cloud.storage.template.QCOW2Processor;
+import com.cloud.storage.template.TemplateLocation;
+import com.cloud.storage.template.Processor.FormatInfo;
+import com.cloud.utils.NumbersUtil;
+import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.utils.script.Script;
+import com.cloud.vm.DiskProfile;
+
+public class KVMStorageProcessor implements StorageProcessor {
+ private static final Logger s_logger = Logger.getLogger(KVMStorageProcessor.class);
+ private KVMStoragePoolManager storagePoolMgr;
+ private LibvirtComputingResource resource;
+ private StorageLayer storageLayer;
+ private String _createTmplPath;
+ private String _manageSnapshotPath;
+ private int _cmdsTimeout;
+ public KVMStorageProcessor(KVMStoragePoolManager storagePoolMgr, LibvirtComputingResource resource) {
+ this.storagePoolMgr = storagePoolMgr;
+ this.resource = resource;
+ }
+
+ protected String getDefaultStorageScriptsDir() {
+ return "scripts/storage/qcow2";
+ }
+
+ public boolean configure(String name, Map<String, Object> params)
+ throws ConfigurationException {
+ storageLayer = new JavaStorageLayer();
+ storageLayer.configure("StorageLayer", params);
+
+ String storageScriptsDir = (String) params.get("storage.scripts.dir");
+ if (storageScriptsDir == null) {
+ storageScriptsDir = getDefaultStorageScriptsDir();
+ }
+
+ _createTmplPath = Script
+ .findScript(storageScriptsDir, "createtmplt.sh");
+ if (_createTmplPath == null) {
+ throw new ConfigurationException(
+ "Unable to find the createtmplt.sh");
+ }
+
+ _manageSnapshotPath = Script.findScript(storageScriptsDir,
+ "managesnapshot.sh");
+ if (_manageSnapshotPath == null) {
+ throw new ConfigurationException(
+ "Unable to find the managesnapshot.sh");
+ }
+
+ String value = (String) params.get("cmds.timeout");
+ _cmdsTimeout = NumbersUtil.parseInt(value, 7200) * 1000;
+ return true;
+ }
+
+ @Override
+ public Answer copyTemplateToPrimaryStorage(CopyCommand cmd) {
+ DataTO srcData = cmd.getSrcTO();
+ DataTO destData = cmd.getDestTO();
+ TemplateObjectTO template = (TemplateObjectTO)srcData;
+ DataStoreTO imageStore = template.getDataStore();
+ VolumeObjectTO volume = (VolumeObjectTO)destData;
+ PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)volume.getDataStore();
+
+ if (!(imageStore instanceof NfsTO)) {
+ return new CopyCmdAnswer("unsupported protocol");
+ }
+
+ NfsTO nfsImageStore = (NfsTO)imageStore;
+ String tmplturl = nfsImageStore.getUrl() + File.separator + template.getPath();
+ int index = tmplturl.lastIndexOf("/");
+ String mountpoint = tmplturl.substring(0, index);
+ String tmpltname = null;
+ if (index < tmplturl.length() - 1) {
+ tmpltname = tmplturl.substring(index + 1);
+ }
+
+ KVMPhysicalDisk tmplVol = null;
+ KVMStoragePool secondaryPool = null;
+ try {
+ secondaryPool = storagePoolMgr.getStoragePoolByURI(mountpoint);
+
+ /* Get template vol */
+ if (tmpltname == null) {
+ secondaryPool.refresh();
+ List<KVMPhysicalDisk> disks = secondaryPool.listPhysicalDisks();
+ if (disks == null || disks.isEmpty()) {
+ return new PrimaryStorageDownloadAnswer(
+ "Failed to get volumes from pool: "
+ + secondaryPool.getUuid());
+ }
+ for (KVMPhysicalDisk disk : disks) {
+ if (disk.getName().endsWith("qcow2")) {
+ tmplVol = disk;
+ break;
+ }
+ }
+ if (tmplVol == null) {
+ return new PrimaryStorageDownloadAnswer(
+ "Failed to get template from pool: "
+ + secondaryPool.getUuid());
+ }
+ } else {
+ tmplVol = secondaryPool.getPhysicalDisk(tmpltname);
+ }
+
+ /* Copy volume to primary storage */
+ KVMStoragePool primaryPool = storagePoolMgr.getStoragePool(
+ primaryStore.getPoolType(),
+ primaryStore.getUuid());
+
+ KVMPhysicalDisk primaryVol = storagePoolMgr.copyPhysicalDisk(
+ tmplVol, UUID.randomUUID().toString(), primaryPool);
+
+ VolumeObjectTO newVol = new VolumeObjectTO();
+ newVol.setPath(primaryVol.getName());
+ newVol.setSize(primaryVol.getSize());
+ return new CopyCmdAnswer(newVol);
+ } catch (CloudRuntimeException e) {
+ return new CopyCmdAnswer(e.toString());
+ } finally {
+ if (secondaryPool != null) {
+ secondaryPool.delete();
+ }
+ }
+ }
+
+ // this is much like PrimaryStorageDownloadCommand, but keeping it separate
+ private KVMPhysicalDisk templateToPrimaryDownload(String templateUrl, KVMStoragePool primaryPool) {
+ int index = templateUrl.lastIndexOf("/");
+ String mountpoint = templateUrl.substring(0, index);
+ String templateName = null;
+ if (index < templateUrl.length() - 1) {
+ templateName = templateUrl.substring(index + 1);
+ }
+
+ KVMPhysicalDisk templateVol = null;
+ KVMStoragePool secondaryPool = null;
+ try {
+ secondaryPool = storagePoolMgr.getStoragePoolByURI(mountpoint);
+ /* Get template vol */
+ if (templateName == null) {
+ secondaryPool.refresh();
+ List<KVMPhysicalDisk> disks = secondaryPool.listPhysicalDisks();
+ if (disks == null || disks.isEmpty()) {
+ s_logger.error("Failed to get volumes from pool: " + secondaryPool.getUuid());
+ return null;
+ }
+ for (KVMPhysicalDisk disk : disks) {
+ if (disk.getName().endsWith("qcow2")) {
+ templateVol = disk;
+ break;
+ }
+ }
+ if (templateVol == null) {
+ s_logger.error("Failed to get template from pool: " + secondaryPool.getUuid());
+ return null;
+ }
+ } else {
+ templateVol = secondaryPool.getPhysicalDisk(templateName);
+ }
+
+ /* Copy volume to primary storage */
+
+ KVMPhysicalDisk primaryVol = storagePoolMgr.copyPhysicalDisk(templateVol, UUID.randomUUID().toString(), primaryPool);
+ return primaryVol;
+ } catch (CloudRuntimeException e) {
+ s_logger.error("Failed to download template to primary storage",e);
+ return null;
+ } finally {
+ if (secondaryPool != null) {
+ secondaryPool.delete();
+ }
+ }
+ }
+
+ @Override
+ public Answer cloneVolumeFromBaseTemplate(CopyCommand cmd) {
+ DataTO srcData = cmd.getSrcTO();
+ DataTO destData = cmd.getDestTO();
+ TemplateObjectTO template = (TemplateObjectTO)srcData;
+ DataStoreTO imageStore = template.getDataStore();
+ VolumeObjectTO volume = (VolumeObjectTO)destData;
+ PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)volume.getDataStore();
+ KVMPhysicalDisk BaseVol = null;
+ KVMStoragePool primaryPool = null;
+ KVMPhysicalDisk vol = null;
+
+ try {
+ primaryPool = storagePoolMgr.getStoragePool(primaryStore.getPoolType(),
+ primaryStore.getUuid());
+
+ String templatePath = null;
+ if (imageStore instanceof NfsTO) {
+ NfsTO nfsImageStore = (NfsTO)imageStore;
+ templatePath = nfsImageStore.getUrl();
+ } else {
+ s_logger.debug("Failed to create volume: ");
+ return new CopyCmdAnswer("Unsupported protocol");
+ }
+
+ if(primaryPool.getType() == StoragePoolType.CLVM) {
+ vol = templateToPrimaryDownload(templatePath, primaryPool);
+ } else {
+ BaseVol = primaryPool.getPhysicalDisk(templatePath);
+ vol = storagePoolMgr.createDiskFromTemplate(BaseVol, UUID
+ .randomUUID().toString(), primaryPool);
+ }
+ if (vol == null) {
+ return new CopyCmdAnswer(
+ " Can't create storage volume on storage pool");
+ }
+
+ VolumeObjectTO newVol = new VolumeObjectTO();
+ newVol.setPath(vol.getName());
+ newVol.setSize(vol.getSize());
+
+ return new CopyCmdAnswer(newVol);
+ } catch (CloudRuntimeException e) {
+ s_logger.debug("Failed to create volume: " + e.toString());
+ return new CopyCmdAnswer(e.toString());
+ }
+ }
+
+ @Override
+ public Answer copyVolumeFromImageCacheToPrimary(CopyCommand cmd) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Answer copyVolumeFromPrimaryToSecondary(CopyCommand cmd) {
+ return null;
+ }
+
+ @Override
+ public Answer createTemplateFromVolume(CopyCommand cmd) {
+ DataTO srcData = cmd.getSrcTO();
+ DataTO destData = cmd.getDestTO();
+ int wait = cmd.getWait();
+ TemplateObjectTO template = (TemplateObjectTO)srcData;
+ DataStoreTO imageStore = template.getDataStore();
+ VolumeObjectTO volume = (VolumeObjectTO)destData;
+ PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)volume.getDataStore();
+
+ if (!(imageStore instanceof NfsTO)) {
+ return new CopyCmdAnswer("unsupported protocol");
+ }
+ NfsTO nfsImageStore = (NfsTO)imageStore;
+
+ KVMStoragePool secondaryStorage = null;
+ KVMStoragePool primary = null;
+ try {
+ String templateFolder = template.getPath();
+
+ secondaryStorage = storagePoolMgr.getStoragePoolByURI(
+ nfsImageStore.getUrl());
+
+ try {
+ primary = storagePoolMgr.getStoragePool(
+ primaryStore.getPoolType(),
+ primaryStore.getUuid());
+ } catch (CloudRuntimeException e) {
+ if (e.getMessage().contains("not found")) {
+ primary = storagePoolMgr.createStoragePool(primaryStore.getUuid(),
+ primaryStore.getHost(), primaryStore.getPort(),
+ primaryStore.getPath(), null,
+ primaryStore.getPoolType());
+ } else {
+ return new CopyCmdAnswer(e.getMessage());
+ }
+ }
+
+ KVMPhysicalDisk disk = primary.getPhysicalDisk(volume.getPath());
+ String tmpltPath = secondaryStorage.getLocalPath() + File.separator
+ + templateFolder;
+ this.storageLayer.mkdirs(tmpltPath);
+ String templateName = UUID.randomUUID().toString();
+
+ if (primary.getType() != StoragePoolType.RBD) {
+ Script command = new Script(_createTmplPath, wait, s_logger);
+ command.add("-f", disk.getPath());
+ command.add("-t", tmpltPath);
+ command.add("-n", templateName + ".qcow2");
+
+ String result = command.execute();
+
+ if (result != null) {
+ s_logger.debug("failed to create template: " + result);
+ return new CopyCmdAnswer(result);
+ }
+ } else {
+ s_logger.debug("Converting RBD disk " + disk.getPath() + " into template " + templateName);
+
+ QemuImgFile srcFile = new QemuImgFile(KVMPhysicalDisk.RBDStringBuilder(primary.getSourceHost(),
+ primary.getSourcePort(),
+ primary.getAuthUserName(),
+ primary.getAuthSecret(),
+ disk.getPath()));
+ srcFile.setFormat(PhysicalDiskFormat.RAW);
+
+ QemuImgFile destFile = new QemuImgFile(tmpltPath + "/" + templateName + ".qcow2");
+ destFile.setFormat(PhysicalDiskFormat.QCOW2);
+
+ QemuImg q = new QemuImg();
+ try {
+ q.convert(srcFile, destFile);
+ } catch (QemuImgException e) {
+ s_logger.error("Failed to create new template while converting "
+ + srcFile.getFileName() + " to " + destFile.getFileName() + " the error was: " + e.getMessage());
+ }
+
+ File templateProp = new File(tmpltPath + "/template.properties");
+ if (!templateProp.exists()) {
+ templateProp.createNewFile();
+ }
+
+ String templateContent = "filename=" + templateName + ".qcow2" + System.getProperty("line.separator");
+
+ DateFormat dateFormat = new SimpleDateFormat("MM_dd_yyyy");
+ Date date = new Date();
+ templateContent += "snapshot.name=" + dateFormat.format(date) + System.getProperty("line.separator");
+
+ FileOutputStream templFo = new FileOutputStream(templateProp);
+ templFo.write(templateContent.getBytes());
+ templFo.flush();
+ templFo.close();
+ }
+
+ Map<String, Object> params = new HashMap<String, Object>();
+ params.put(StorageLayer.InstanceConfigKey, this.storageLayer);
+ Processor qcow2Processor = new QCOW2Processor();
+
+ qcow2Processor.configure("QCOW2 Processor", params);
+
+ FormatInfo info = qcow2Processor.process(tmpltPath, null,
+ templateName);
+
+ TemplateLocation loc = new TemplateLocation(this.storageLayer, tmpltPath);
+ loc.create(1, true, templateName);
+ loc.addFormat(info);
+ loc.save();
+
+ TemplateObjectTO newTemplate = new TemplateObjectTO();
+ newTemplate.setPath(templateFolder + templateName + ".qcow2");
+ return new CopyCmdAnswer(newTemplate);
+ } catch (Exception e) {
+ s_logger.debug("Failed to create template from volume: " + e.toString());
+ return new CopyCmdAnswer(e.toString());
+ } finally {
+ if (secondaryStorage != null) {
+ secondaryStorage.delete();
+ }
+ }
+ }
+
+ @Override
+ public Answer backupSnasphot(CopyCommand cmd) {
+ DataTO srcData = cmd.getSrcTO();
+ DataTO destData = cmd.getDestTO();
+ int wait = cmd.getWait();
+ SnapshotObjectTO snapshot = (SnapshotObjectTO)srcData;
+ PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)snapshot.getDataStore();
+ SnapshotObjectTO destSnapshot = (SnapshotObjectTO)destData;
+ DataStoreTO imageStore = destData.getDataStore();
+
+ if (!(imageStore instanceof NfsTO)) {
+ return new CopyCmdAnswer("unsupported protocol");
+ }
+ NfsTO nfsImageStore = (NfsTO)imageStore;
+
+ String secondaryStoragePoolUrl = nfsImageStore.getUrl();
+ //NOTE: snapshot name is encoded in snapshot path
+ int index = snapshot.getPath().lastIndexOf("/");
+
+ String snapshotName = snapshot.getPath().substring(index + 1);
+ String volumePath = snapshot.getVolume().getPath();
+ String snapshotDestPath = null;
+ String snapshotRelPath = null;
+ String vmName = snapshot.getVmName();
+ KVMStoragePool secondaryStoragePool = null;
+ try {
+ Connect conn = LibvirtConnection.getConnectionByVmName(vmName);
+
+ secondaryStoragePool = storagePoolMgr.getStoragePoolByURI(
+ secondaryStoragePoolUrl);
+
+ String ssPmountPath = secondaryStoragePool.getLocalPath();
+ snapshotRelPath = destSnapshot.getPath();
+
+ snapshotDestPath = ssPmountPath + File.separator + snapshotRelPath;
+ KVMStoragePool primaryPool = storagePoolMgr.getStoragePool(
+ primaryStore.getPoolType(),
+ primaryStore.getUuid());
+ KVMPhysicalDisk snapshotDisk = primaryPool.getPhysicalDisk(volumePath);
+ Script command = new Script(_manageSnapshotPath, _cmdsTimeout,
+ s_logger);
+ command.add("-b", snapshotDisk.getPath());
+ command.add("-n", snapshotName);
+ command.add("-p", snapshotDestPath);
+ command.add("-t", snapshotName);
+ String result = command.execute();
+ if (result != null) {
+ s_logger.debug("Failed to backup snaptshot: " + result);
+ return new CopyCmdAnswer(result);
+ }
+ /* Delete the snapshot on primary */
+
+ DomainInfo.DomainState state = null;
+ Domain vm = null;
+ if (vmName != null) {
+ try {
+ vm = this.resource.getDomain(conn, vmName);
+ state = vm.getInfo().state;
+ } catch (LibvirtException e) {
+ s_logger.trace("Ignoring libvirt error.", e);
+ }
+ }
+
+ KVMStoragePool primaryStorage = storagePoolMgr.getStoragePool(
+ primaryStore.getPoolType(),
+ primaryStore.getUuid());
+ if (state == DomainInfo.DomainState.VIR_DOMAIN_RUNNING
+ && !primaryStorage.isExternalSnapshot()) {
+ DomainSnapshot snap = vm.snapshotLookupByName(snapshotName);
+ snap.delete(0);
+
+ /*
+ * libvirt on RHEL6 doesn't handle resume event emitted from
+ * qemu
+ */
+ vm = this.resource.getDomain(conn, vmName);
+ state = vm.getInfo().state;
+ if (state == DomainInfo.DomainState.VIR_DOMAIN_PAUSED) {
+ vm.resume();
+ }
+ } else {
+ command = new Script(_manageSnapshotPath, _cmdsTimeout,
+ s_logger);
+ command.add("-d", snapshotDisk.getPath());
+ command.add("-n", snapshotName);
+ result = command.execute();
+ if (result != null) {
+ s_logger.debug("Failed to backup snapshot: " + result);
+ return new CopyCmdAnswer(
+ "Failed to backup snapshot: " + result);
+ }
+ }
+
+ SnapshotObjectTO newSnapshot = new SnapshotObjectTO();
+ newSnapshot.setPath(snapshotRelPath
+ + File.separator + snapshotName);
+ return new CopyCmdAnswer(newSnapshot);
+ } catch (LibvirtException e) {
+ s_logger.debug("Failed to backup snapshot: " + e.toString());
+ return new CopyCmdAnswer(e.toString());
+ } catch (CloudRuntimeException e) {
+ s_logger.debug("Failed to backup snapshot: " + e.toString());
+ return new CopyCmdAnswer(e.toString());
+ } finally {
+ if (secondaryStoragePool != null) {
+ secondaryStoragePool.delete();
+ }
+ }
+ }
+
+ protected synchronized String attachOrDetachISO(Connect conn,
+ String vmName, String isoPath, boolean isAttach)
+ throws LibvirtException, URISyntaxException, InternalErrorException {
+ String isoXml = null;
+ if (isoPath != null && isAttach) {
+ int index = isoPath.lastIndexOf("/");
+ String path = isoPath.substring(0, index);
+ String name = isoPath.substring(index + 1);
+ KVMStoragePool secondaryPool = storagePoolMgr.getStoragePoolByURI(
+ path);
+ KVMPhysicalDisk isoVol = secondaryPool.getPhysicalDisk(name);
+ isoPath = isoVol.getPath();
+
+ DiskDef iso = new DiskDef();
+ iso.defISODisk(isoPath);
+ isoXml = iso.toString();
+ } else {
+ DiskDef iso = new DiskDef();
+ iso.defISODisk(null);
+ isoXml = iso.toString();
+ }
+
+ List<DiskDef> disks = this.resource.getDisks(conn, vmName);
+ String result = attachOrDetachDevice(conn, true, vmName, isoXml);
+ if (result == null && !isAttach) {
+ for (DiskDef disk : disks) {
+ if (disk.getDeviceType() == DiskDef.deviceType.CDROM) {
+ this.resource.cleanupDisk(conn, disk);
+ }
+ }
+
+ }
+ return result;
+ }
+ @Override
+ public Answer attachIso(AttachCommand cmd) {
+ DiskTO disk = cmd.getDisk();
+ TemplateObjectTO isoTO = (TemplateObjectTO)disk.getData();
+ DataStoreTO store = isoTO.getDataStore();
+ if (!(store instanceof NfsTO)) {
+ return new AttachAnswer("unsupported protocol");
+ }
+ NfsTO nfsStore = (NfsTO)store;
+ try {
+ Connect conn = LibvirtConnection.getConnectionByVmName(cmd.getVmName());
+ attachOrDetachISO(conn, cmd.getVmName(), nfsStore.getUrl() + File.separator + isoTO.getPath(),
+ true);
+ } catch (LibvirtException e) {
+ return new Answer(cmd, false, e.toString());
+ } catch (URISyntaxException e) {
+ return new Answer(cmd, false, e.toString());
+ } catch (InternalErrorException e) {
+ return new Answer(cmd, false, e.toString());
+ }
+
+ return new Answer(cmd);
+ }
+
+ protected synchronized String attachOrDetachDevice(Connect conn,
+ boolean attach, String vmName, String xml) throws LibvirtException,
+ InternalErrorException {
+ Domain dm = null;
+ try {
+ dm = conn.domainLookupByUUID(UUID.nameUUIDFromBytes((vmName
+ .getBytes())));
+
+ if (attach) {
+ s_logger.debug("Attaching device: " + xml);
+ dm.attachDevice(xml);
+ } else {
+ s_logger.debug("Detaching device: " + xml);
+ dm.detachDevice(xml);
+ }
+ } catch (LibvirtException e) {
+ if (attach) {
+ s_logger.warn("Failed to attach device to " + vmName + ": "
+ + e.getMessage());
+ } else {
+ s_logger.warn("Failed to detach device from " + vmName + ": "
+ + e.getMessage());
+ }
+ throw e;
+ } finally {
+ if (dm != null) {
+ try {
+ dm.free();
+ } catch (LibvirtException l) {
+ s_logger.trace("Ignoring libvirt error.", l);
+ }
+ }
+ }
+
+ return null;
+ }
+
+ protected synchronized String attachOrDetachDisk(Connect conn,
+ boolean attach, String vmName, KVMPhysicalDisk attachingDisk,
+ int devId) throws LibvirtException, InternalErrorException {
+ List<DiskDef> disks = null;
+ Domain dm = null;
+ DiskDef diskdef = null;
+ try {
+ if (!attach) {
+ dm = conn.domainLookupByUUID(UUID.nameUUIDFromBytes(vmName
+ .getBytes()));
+ LibvirtDomainXMLParser parser = new LibvirtDomainXMLParser();
+ String xml = dm.getXMLDesc(0);
+ parser.parseDomainXML(xml);
+ disks = parser.getDisks();
+
+ for (DiskDef disk : disks) {
+ String file = disk.getDiskPath();
+ if (file != null
+ && file.equalsIgnoreCase(attachingDisk.getPath())) {
+ diskdef = disk;
+ break;
+ }
+ }
+ if (diskdef == null) {
+ throw new InternalErrorException("disk: "
+ + attachingDisk.getPath()
+ + " is not attached before");
+ }
+ } else {
+ diskdef = new DiskDef();
+ if (attachingDisk.getFormat() == PhysicalDiskFormat.QCOW2) {
+ diskdef.defFileBasedDisk(attachingDisk.getPath(), devId,
+ DiskDef.diskBus.VIRTIO, DiskDef.diskFmtType.QCOW2);
+ } else if (attachingDisk.getFormat() == PhysicalDiskFormat.RAW) {
+ diskdef.defBlockBasedDisk(attachingDisk.getPath(), devId,
+ DiskDef.diskBus.VIRTIO);
+ }
+ }
+
+ String xml = diskdef.toString();
+ return attachOrDetachDevice(conn, attach, vmName, xml);
+ } finally {
+ if (dm != null) {
+ dm.free();
+ }
+ }
+ }
+
+ @Override
+ public Answer attachVolume(AttachCommand cmd) {
+ DiskTO disk = cmd.getDisk();
+ VolumeObjectTO vol = (VolumeObjectTO)disk.getData();
+ PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)vol.getDataStore();
+ String vmName = vol.getVmName();
+ try {
+ Connect conn = LibvirtConnection.getConnectionByVmName(vmName);
+ KVMStoragePool primary = storagePoolMgr.getStoragePool(
+ primaryStore.getPoolType(),
+ primaryStore.getUuid());
+
+ KVMPhysicalDisk phyDisk = primary.getPhysicalDisk(vol.getPath());
+ attachOrDetachDisk(conn, true, vmName, phyDisk,
+ disk.getDiskSeq().intValue());
+
+ return new AttachAnswer(disk);
+ } catch (LibvirtException e) {
+ s_logger.debug("Failed to attach volume: " + vol.getPath() + ", due to " + e.toString());
+ return new AttachAnswer(e.toString());
+ } catch (InternalErrorException e) {
+ s_logger.debug("Failed to attach volume: " + vol.getPath() + ", due to " + e.toString());
+ return new AttachAnswer(e.toString());
+ }
+
+
+ }
+
+ @Override
+ public Answer dettachIso(DettachCommand cmd) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Answer dettachVolume(DettachCommand cmd) {
+ DiskTO disk = cmd.getDisk();
+ VolumeObjectTO vol = (VolumeObjectTO)disk.getData();
+ PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)vol.getDataStore();
+ String vmName = vol.getVmName();
+ try {
+ Connect conn = LibvirtConnection.getConnectionByVmName(vmName);
+ KVMStoragePool primary = storagePoolMgr.getStoragePool(
+ primaryStore.getPoolType(),
+ primaryStore.getUuid());
+
+ KVMPhysicalDisk phyDisk = primary.getPhysicalDisk(vol.getPath());
+ attachOrDetachDisk(conn, false, vmName, phyDisk,
+ disk.getDiskSeq().intValue());
+
+ return new DettachAnswer(disk);
+ } catch (LibvirtException e) {
+ s_logger.debug("Failed to attach volume: " + vol.getPath() + ", due to " + e.toString());
+ return new DettachAnswer(e.toString());
+ } catch (InternalErrorException e) {
+ s_logger.debug("Failed to attach volume: " + vol.getPath() + ", due to " + e.toString());
+ return new DettachAnswer(e.toString());
+ }
+ }
+
+ @Override
+ public Answer createVolume(CreateObjectCommand cmd) {
+ VolumeObjectTO volume = (VolumeObjectTO)cmd.getData();
+ PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)volume.getDataStore();
+
+ KVMStoragePool primaryPool = null;
+ KVMPhysicalDisk vol = null;
+ long disksize;
+ try {
+ primaryPool = storagePoolMgr.getStoragePool(primaryStore.getPoolType(),
+ primaryStore.getUuid());
+ disksize = volume.getSize();
+
+ vol = primaryPool.createPhysicalDisk(UUID.randomUUID()
+ .toString(), disksize);
+
+ VolumeObjectTO newVol = new VolumeObjectTO();
+ newVol.setPath(vol.getName());
+
+ return new CreateObjectAnswer(newVol);
+ } catch (Exception e) {
+ s_logger.debug("Failed to create volume: " + e.toString());
+ return new CreateObjectAnswer(e.toString());
+ }
+ }
+
+ protected static MessageFormat SnapshotXML = new MessageFormat(
+ " <domainsnapshot>" + " <name>{0}</name>" + " <domain>"
+ + " <uuid>{1}</uuid>" + " </domain>"
+ + " </domainsnapshot>");
+
+ @Override
+ public Answer createSnapshot(CreateObjectCommand cmd) {
+ VolumeObjectTO volume = (VolumeObjectTO)cmd.getData();
+ PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)volume.getDataStore();
+ String snapshotName = UUID.randomUUID().toString();
+ String vmName = volume.getVmName();
+ try {
+ Connect conn = LibvirtConnection.getConnectionByVmName(vmName);
+ DomainInfo.DomainState state = null;
+ Domain vm = null;
+ if (vmName != null) {
+ try {
+ vm = this.resource.getDomain(conn, vmName);
+ state = vm.getInfo().state;
+ } catch (LibvirtException e) {
+ s_logger.trace("Ignoring libvirt error.", e);
+ }
+ }
+
+ KVMStoragePool primaryPool = storagePoolMgr.getStoragePool(
+ primaryStore.getPoolType(),
+ primaryStore.getUuid());
+
+ if (primaryPool.getType() == StoragePoolType.RBD) {
+ s_logger.debug("Snapshots are not supported on RBD volumes");
+ return new CreateObjectAnswer(
+ "Snapshots are not supported on RBD volumes");
+ }
+
+ KVMPhysicalDisk disk = primaryPool.getPhysicalDisk(volume.getPath());
+ if (state == DomainInfo.DomainState.VIR_DOMAIN_RUNNING
+ && !primaryPool.isExternalSnapshot()) {
+ String vmUuid = vm.getUUIDString();
+ Object[] args = new Object[] { snapshotName, vmUuid };
+ String snapshot = SnapshotXML.format(args);
+ s_logger.debug(snapshot);
+
+ vm.snapshotCreateXML(snapshot);
+ /*
+ * libvirt on RHEL6 doesn't handle resume event emitted from
+ * qemu
+ */
+ vm = this.resource.getDomain(conn, vmName);
+ state = vm.getInfo().state;
+ if (state == DomainInfo.DomainState.VIR_DOMAIN_PAUSED) {
+ vm.resume();
+ }
+ } else {
+
+ /* VM is not running, create a snapshot by ourself */
+ final Script command = new Script(_manageSnapshotPath,
+ this._cmdsTimeout, s_logger);
+ command.add("-c", disk.getPath());
+ command.add("-n", snapshotName);
+ String result = command.execute();
+ if (result != null) {
+ s_logger.debug("Failed to manage snapshot: " + result);
+ return new CreateObjectAnswer(
+ "Failed to manage snapshot: " + result);
+ }
+ }
+
+ SnapshotObjectTO newSnapshot = new SnapshotObjectTO();
+ //NOTE: sort of hack, we'd better just put snapshtoName
+ newSnapshot.setPath(disk.getPath() + File.separator + snapshotName);
+ return new CreateObjectAnswer(newSnapshot);
+ } catch (LibvirtException e) {
+ s_logger.debug("Failed to manage snapshot: " + e.toString());
+ return new CreateObjectAnswer(
+ "Failed to manage snapshot: " + e.toString());
+ }
+ }
+
+ @Override
+ public Answer deleteVolume(DeleteCommand cmd) {
+ VolumeObjectTO vol = (VolumeObjectTO)cmd.getData();
+ PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)vol.getDataStore();
+ try {
+ KVMStoragePool pool = storagePoolMgr.getStoragePool(
+ primaryStore.getPoolType(),
+ primaryStore.getUuid());
+ try {
+ pool.getPhysicalDisk(vol.getPath());
+ } catch(Exception e) {
+ s_logger.debug("can't find volume: " + vol.getPath() + ", return true");
+ return new Answer(null);
+ }
+ pool.deletePhysicalDisk(vol.getPath());
+ return new Answer(null);
+ } catch (CloudRuntimeException e) {
+ s_logger.debug("Failed to delete volume: " + e.toString());
+ return new Answer(null, false, e.toString());
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/42e25a22/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/KVMStorageResource.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/KVMStorageResource.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/KVMStorageResource.java
new file mode 100644
index 0000000..52e142e
--- /dev/null
+++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/KVMStorageResource.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package com.cloud.hypervisor.kvm.storage;
+
+import org.apache.cloudstack.storage.command.AttachCommand;
+import org.apache.cloudstack.storage.command.AttachPrimaryDataStoreCmd;
+import org.apache.cloudstack.storage.command.CopyCommand;
+import org.apache.cloudstack.storage.command.CreateObjectCommand;
+import org.apache.cloudstack.storage.command.CreatePrimaryDataStoreCmd;
+import org.apache.cloudstack.storage.command.DeleteCommand;
+import org.apache.cloudstack.storage.command.DettachCommand;
+import org.apache.cloudstack.storage.command.StorageSubSystemCommand;
+
+import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.Command;
+import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource;
+
+public class KVMStorageResource {
+ private LibvirtComputingResource resource;
+ public KVMStorageResource(LibvirtComputingResource resource) {
+ this.resource = resource;
+ }
+
+ public Answer handleStorageCommands(StorageSubSystemCommand command) {
+ if (command instanceof CopyCommand) {
+ return this.execute((CopyCommand)command);
+ } else if (command instanceof AttachPrimaryDataStoreCmd) {
+ return this.execute((AttachPrimaryDataStoreCmd)command);
+ } else if (command instanceof CreatePrimaryDataStoreCmd) {
+ return execute((CreatePrimaryDataStoreCmd) command);
+ } else if (command instanceof CreateObjectCommand) {
+ return execute((CreateObjectCommand) command);
+ } else if (command instanceof DeleteCommand) {
+ return execute((DeleteCommand)command);
+ } else if (command instanceof AttachCommand) {
+ return execute((AttachCommand)command);
+ } else if (command instanceof DettachCommand) {
+ return execute((DettachCommand)command);
+ }
+ return new Answer((Command)command, false, "not implemented yet");
+ }
+
+ protected Answer execute(CopyCommand cmd) {
+ return new Answer((Command)cmd, false, "not implemented yet");
+ }
+
+ protected Answer execute(AttachPrimaryDataStoreCmd cmd) {
+ return new Answer((Command)cmd, false, "not implemented yet");
+ }
+
+ protected Answer execute(CreatePrimaryDataStoreCmd cmd) {
+ return new Answer((Command)cmd, false, "not implemented yet");
+ }
+
+ protected Answer execute(CreateObjectCommand cmd) {
+ return new Answer((Command)cmd, false, "not implemented yet");
+ }
+
+ protected Answer execute(DeleteCommand cmd) {
+ return new Answer((Command)cmd, false, "not implemented yet");
+ }
+
+ protected Answer execute(AttachCommand cmd) {
+ return new Answer((Command)cmd, false, "not implemented yet");
+ }
+
+ protected Answer execute(DettachCommand cmd) {
+ return new Answer((Command)cmd, false, "not implemented yet");
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/42e25a22/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java
index 0f85f4e..f91786f 100755
--- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java
+++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java
@@ -39,6 +39,11 @@ import java.util.UUID;
import javax.naming.ConfigurationException;
+import org.apache.cloudstack.storage.command.DeleteCommand;
+import org.apache.cloudstack.storage.command.StorageSubSystemCommand;
+import org.apache.cloudstack.storage.to.PrimaryDataStoreTO;
+import org.apache.cloudstack.storage.to.TemplateObjectTO;
+import org.apache.cloudstack.storage.to.VolumeObjectTO;
import org.apache.log4j.Logger;
import org.apache.log4j.NDC;
@@ -162,8 +167,11 @@ import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer;
import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand;
import com.cloud.agent.api.storage.ResizeVolumeAnswer;
import com.cloud.agent.api.storage.ResizeVolumeCommand;
+import com.cloud.agent.api.to.DataStoreTO;
+import com.cloud.agent.api.to.DiskTO;
import com.cloud.agent.api.to.FirewallRuleTO;
import com.cloud.agent.api.to.IpAddressTO;
+import com.cloud.agent.api.to.NfsTO;
import com.cloud.agent.api.to.NicTO;
import com.cloud.agent.api.to.PortForwardingRuleTO;
import com.cloud.agent.api.to.StaticNatRuleTO;
@@ -177,6 +185,7 @@ import com.cloud.host.Host.Type;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.hypervisor.vmware.manager.VmwareHostService;
import com.cloud.hypervisor.vmware.manager.VmwareManager;
+import com.cloud.hypervisor.vmware.manager.VmwareStorageMount;
import com.cloud.hypervisor.vmware.mo.ClusterMO;
import com.cloud.hypervisor.vmware.mo.CustomFieldConstants;
import com.cloud.hypervisor.vmware.mo.CustomFieldsManagerMO;
@@ -210,8 +219,12 @@ import com.cloud.storage.Storage;
import com.cloud.storage.Storage.StoragePoolType;
import com.cloud.storage.Volume;
import com.cloud.storage.resource.StoragePoolResource;
+import com.cloud.storage.resource.StorageSubsystemCommandHandler;
+import com.cloud.storage.resource.StorageSubsystemCommandHandlerBase;
+import com.cloud.storage.resource.VmwareStorageProcessor;
import com.cloud.storage.template.TemplateProp;
import com.cloud.utils.DateUtil;
+import com.cloud.utils.NumbersUtil;
import com.cloud.utils.Pair;
import com.cloud.utils.StringUtils;
import com.cloud.utils.db.DB;
@@ -313,6 +326,8 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
protected Gson _gson;
protected volatile long _cmdSequence = 1;
+
+ protected StorageSubsystemCommandHandler storageHandler;
protected static HashMap<VirtualMachinePowerState, State> s_statesTable;
static {
@@ -321,6 +336,10 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
s_statesTable.put(VirtualMachinePowerState.POWERED_OFF, State.Stopped);
s_statesTable.put(VirtualMachinePowerState.SUSPENDED, State.Stopped);
}
+
+ public Gson getGson() {
+ return this._gson;
+ }
public VmwareResource() {
_gson = GsonHelper.getGsonLogger();
@@ -472,6 +491,8 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
answer = execute((CheckS2SVpnConnectionsCommand) cmd);
} else if (clz == ResizeVolumeCommand.class) {
return execute((ResizeVolumeCommand) cmd);
+ } else if (clz == StorageSubSystemCommand.class) {
+ return this.storageHandler.handleStorageCommands((StorageSubSystemCommand)cmd);
} else {
answer = Answer.createUnsupportedCommandAnswer(cmd);
}
@@ -2026,14 +2047,21 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
return new CheckSshAnswer(cmd);
}
- private VolumeTO[] validateDisks(VolumeTO[] disks) {
- List<VolumeTO> validatedDisks = new ArrayList<VolumeTO>();
+ private DiskTO[] validateDisks(DiskTO[] disks) {
+ List<DiskTO> validatedDisks = new ArrayList<DiskTO>();
- for (VolumeTO vol : disks) {
- if (vol.getPoolUuid() != null && !vol.getPoolUuid().isEmpty()) {
- validatedDisks.add(vol);
- } else if (vol.getPoolType() == StoragePoolType.ISO && (vol.getPath() != null && !vol.getPath().isEmpty())) {
- validatedDisks.add(vol);
+ for (DiskTO vol : disks) {
+ if (vol.getType() != Volume.Type.ISO) {
+ VolumeObjectTO volumeTO = (VolumeObjectTO)vol.getData();
+ PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)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));
@@ -2041,7 +2069,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
}
}
- return validatedDisks.toArray(new VolumeTO[0]);
+ return validatedDisks.toArray(new DiskTO[0]);
}
protected StartAnswer execute(StartCommand cmd) {
@@ -2068,7 +2096,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
s_logger.debug("VM " + vmName + " will be started with NIC device type: " + nicDeviceType);
VmwareHypervisorHost hyperHost = getHyperHost(context);
- VolumeTO[] disks = validateDisks(vmSpec.getDisks());
+ DiskTO[] disks = validateDisks(vmSpec.getDisks());
assert (disks.length > 0);
NicTO[] nics = vmSpec.getNics();
@@ -2105,9 +2133,10 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
} else {
int ramMb = (int) (vmSpec.getMinRam() / (1024 * 1024));
Pair<ManagedObjectReference, DatastoreMO> rootDiskDataStoreDetails = null;
- for (VolumeTO vol : disks) {
+ for (DiskTO vol : disks) {
if (vol.getType() == Volume.Type.ROOT) {
- rootDiskDataStoreDetails = dataStoresDetails.get(vol.getPoolUuid());
+ PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)vol.getData().getDataStore();
+ rootDiskDataStoreDetails = dataStoresDetails.get(primaryStore.getUuid());
}
}
@@ -2126,12 +2155,12 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
}
int totalChangeDevices = disks.length + nics.length;
- VolumeTO volIso = null;
+ DiskTO volIso = null;
if (vmSpec.getType() != VirtualMachine.Type.User) {
// system VM needs a patch ISO
totalChangeDevices++;
} else {
- for (VolumeTO vol : disks) {
+ for (DiskTO vol : disks) {
if (vol.getType() == Volume.Type.ISO) {
volIso = vol;
break;
@@ -2188,23 +2217,35 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
i++;
} else {
// we will always plugin a CDROM device
- if (volIso != null && volIso.getPath() != null && !volIso.getPath().isEmpty()) {
- Pair<String, ManagedObjectReference> isoDatastoreInfo = getIsoDatastoreInfo(hyperHost, volIso.getPath());
- assert (isoDatastoreInfo != null);
- assert (isoDatastoreInfo.second() != null);
-
- deviceConfigSpecArray[i] = new VirtualDeviceConfigSpec();
- Pair<VirtualDevice, Boolean> isoInfo = VmwareHelper.prepareIsoDevice(vmMo, isoDatastoreInfo.first(), isoDatastoreInfo.second(), true, true, i, 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);
- }
+
+ 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, i, 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, i, i + 1);
@@ -2224,7 +2265,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
i++;
}
- for (VolumeTO vol : sortVolumesByDeviceId(disks)) {
+ for (DiskTO vol : sortVolumesByDeviceId(disks)) {
deviceConfigSpecArray[i] = new VirtualDeviceConfigSpec();
if (vol.getType() == Volume.Type.ISO) {
@@ -2247,11 +2288,13 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
}
if (vol.getType() != Volume.Type.ISO) {
- Pair<ManagedObjectReference, DatastoreMO> volumeDsDetails = dataStoresDetails.get(vol.getPoolUuid());
+ VolumeObjectTO volumeTO = (VolumeObjectTO)vol.getData();
+ PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)volumeTO.getDataStore();
+ Pair<ManagedObjectReference, DatastoreMO> volumeDsDetails = dataStoresDetails.get(primaryStore.getUuid());
assert (volumeDsDetails != null);
VirtualDevice device;
- datastoreDiskPath = String.format("[%s] %s.vmdk", volumeDsDetails.second().getName(), vol.getPath());
- String chainInfo = vol.getChainInfo();
+ datastoreDiskPath = String.format("[%s] %s.vmdk", volumeDsDetails.second().getName(), volumeTO.getPath());
+ String chainInfo = volumeTO.getChainInfo();
if (chainInfo != null && !chainInfo.isEmpty()) {
String[] diskChain = _gson.fromJson(chainInfo, String[].class);
@@ -2424,19 +2467,19 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
return listForSort.toArray(new NicTO[0]);
}
- private VolumeTO[] sortVolumesByDeviceId(VolumeTO[] volumes) {
+ private DiskTO[] sortVolumesByDeviceId(DiskTO[] volumes) {
- List<VolumeTO> listForSort = new ArrayList<VolumeTO>();
- for (VolumeTO vol : volumes) {
+ List<DiskTO> listForSort = new ArrayList<DiskTO>();
+ for (DiskTO vol : volumes) {
listForSort.add(vol);
}
- Collections.sort(listForSort, new Comparator<VolumeTO>() {
+ Collections.sort(listForSort, new Comparator<DiskTO>() {
@Override
- public int compare(VolumeTO arg0, VolumeTO arg1) {
- if (arg0.getDeviceId() < arg1.getDeviceId()) {
+ public int compare(DiskTO arg0, DiskTO arg1) {
+ if (arg0.getDiskSeq() < arg1.getDiskSeq()) {
return -1;
- } else if (arg0.getDeviceId() == arg1.getDeviceId()) {
+ } else if (arg0.getDiskSeq() == arg1.getDiskSeq()) {
return 0;
}
@@ -2444,16 +2487,18 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
}
});
- return listForSort.toArray(new VolumeTO[0]);
+ return listForSort.toArray(new DiskTO[0]);
}
- private HashMap<String, Pair<ManagedObjectReference, DatastoreMO>> inferDatastoreDetailsFromDiskInfo(VmwareHypervisorHost hyperHost, VmwareContext context, VolumeTO[] disks) throws Exception {
+ private HashMap<String, Pair<ManagedObjectReference, DatastoreMO>> inferDatastoreDetailsFromDiskInfo(VmwareHypervisorHost hyperHost, VmwareContext context, DiskTO[] disks) throws Exception {
HashMap<String ,Pair<ManagedObjectReference, DatastoreMO>> poolMors = new HashMap<String, Pair<ManagedObjectReference, DatastoreMO>>();
assert (hyperHost != null) && (context != null);
- for (VolumeTO vol : disks) {
+ for (DiskTO vol : disks) {
if (vol.getType() != Volume.Type.ISO) {
- String poolUuid = vol.getPoolUuid();
+ VolumeObjectTO volumeTO = (VolumeObjectTO)vol.getData();
+ PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO)volumeTO.getDataStore();
+ String poolUuid = primaryStore.getUuid();
if(poolMors.get(poolUuid) == null) {
ManagedObjectReference morDataStore = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, poolUuid);
if (morDataStore == null) {
@@ -2461,7 +2506,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
s_logger.error(msg);
throw new Exception(msg);
}
- poolMors.put(vol.getPoolUuid(), new Pair<ManagedObjectReference, DatastoreMO> (morDataStore, new DatastoreMO(context, morDataStore)));
+ poolMors.put(poolUuid, new Pair<ManagedObjectReference, DatastoreMO> (morDataStore, new DatastoreMO(context, morDataStore)));
}
}
}
@@ -3306,7 +3351,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
}
}
- private synchronized ManagedObjectReference prepareSecondaryDatastoreOnHost(String storeUrl) throws Exception {
+ public synchronized ManagedObjectReference prepareSecondaryDatastoreOnHost(String storeUrl) throws Exception {
String storeName = getSecondaryDatastoreUUID(storeUrl);
URI uri = new URI(storeUrl);
@@ -3670,8 +3715,8 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
}
}
- @Override
- public Answer execute(DestroyCommand cmd) {
+
+ public Answer execute(DeleteCommand cmd) {
if (s_logger.isInfoEnabled()) {
s_logger.info("Executing resource DestroyCommand: " + _gson.toJson(cmd));
}
@@ -3691,11 +3736,12 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
try {
VmwareContext context = getServiceContext();
VmwareHypervisorHost hyperHost = getHyperHost(context);
- VolumeTO vol = cmd.getVolume();
+ VolumeObjectTO vol = (VolumeObjectTO)cmd.getData();
+ PrimaryDataStoreTO store = (PrimaryDataStoreTO)vol.getDataStore();
- ManagedObjectReference morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, vol.getPoolUuid());
+ ManagedObjectReference morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(hyperHost, store.getUuid());
if (morDs == null) {
- String msg = "Unable to find datastore based on volume mount point " + cmd.getVolume().getMountPoint();
+ String msg = "Unable to find datastore based on volume mount point " + store.getPath();
s_logger.error(msg);
throw new Exception(msg);
}
@@ -3706,8 +3752,8 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
ManagedObjectReference morCluster = hyperHost.getHyperHostCluster();
ClusterMO clusterMo = new ClusterMO(context, morCluster);
- if (cmd.getVolume().getType() == Volume.Type.ROOT) {
- String vmName = cmd.getVmName();
+ if (vol.getVolumeType() == Volume.Type.ROOT) {
+ String vmName = vol.getVmName();
if (vmName != null) {
VirtualMachineMO vmMo = clusterMo.findVmOnHyperHost(vmName);
if (vmMo != null) {
@@ -3734,20 +3780,20 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
}
if (s_logger.isInfoEnabled())
- s_logger.info("Destroy volume by original name: " + cmd.getVolume().getPath() + ".vmdk");
- dsMo.deleteFile(cmd.getVolume().getPath() + ".vmdk", morDc, true);
+ s_logger.info("Destroy volume by original name: " + vol.getPath() + ".vmdk");
+ dsMo.deleteFile(vol.getPath() + ".vmdk", morDc, true);
// root volume may be created via linked-clone, delete the delta disk as well
if (_fullCloneFlag) {
if (s_logger.isInfoEnabled()) {
- s_logger.info("Destroy volume by derived name: " + cmd.getVolume().getPath() + "-flat.vmdk");
+ s_logger.info("Destroy volume by derived name: " + vol.getPath() + "-flat.vmdk");
}
- dsMo.deleteFile(cmd.getVolume().getPath() + "-flat.vmdk", morDc, true);
+ dsMo.deleteFile(vol.getPath() + "-flat.vmdk", morDc, true);
} else {
if (s_logger.isInfoEnabled()) {
- s_logger.info("Destroy volume by derived name: " + cmd.getVolume().getPath() + "-delta.vmdk");
+ s_logger.info("Destroy volume by derived name: " + vol.getPath() + "-delta.vmdk");
}
- dsMo.deleteFile(cmd.getVolume().getPath() + "-delta.vmdk", morDc, true);
+ dsMo.deleteFile(vol.getPath() + "-delta.vmdk", morDc, true);
}
return new Answer(cmd, true, "Success");
}
@@ -3757,17 +3803,17 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
}
} else {
// evitTemplate will be converted into DestroyCommand, test if we are running in this case
- VirtualMachineMO vmMo = clusterMo.findVmOnHyperHost(cmd.getVolume().getPath());
+ VirtualMachineMO vmMo = clusterMo.findVmOnHyperHost(vol.getPath());
if (vmMo != null) {
if (s_logger.isInfoEnabled())
- s_logger.info("Destroy template volume " + cmd.getVolume().getPath());
+ s_logger.info("Destroy template volume " + vol.getPath());
vmMo.destroy();
return new Answer(cmd, true, "Success");
}
}
- String chainInfo = cmd.getVolume().getChainInfo();
+ String chainInfo = vol.getChainInfo();
if (chainInfo != null && !chainInfo.isEmpty()) {
s_logger.info("Destroy volume by chain info: " + chainInfo);
String[] diskChain = _gson.fromJson(chainInfo, String[].class);
@@ -3783,23 +3829,23 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
if (s_logger.isInfoEnabled()) {
s_logger.info("Empty disk chain info, fall back to try to delete by original backing file name");
}
- dsMo.deleteFile(cmd.getVolume().getPath() + ".vmdk", morDc, true);
+ dsMo.deleteFile(vol.getPath() + ".vmdk", morDc, true);
if (s_logger.isInfoEnabled()) {
- s_logger.info("Destroy volume by derived name: " + cmd.getVolume().getPath() + "-flat.vmdk");
+ s_logger.info("Destroy volume by derived name: " + vol.getPath() + "-flat.vmdk");
}
- dsMo.deleteFile(cmd.getVolume().getPath() + "-flat.vmdk", morDc, true);
+ dsMo.deleteFile(vol.getPath() + "-flat.vmdk", morDc, true);
}
} else {
if (s_logger.isInfoEnabled()) {
- s_logger.info("Destroy volume by original name: " + cmd.getVolume().getPath() + ".vmdk");
+ s_logger.info("Destroy volume by original name: " + vol.getPath() + ".vmdk");
}
- dsMo.deleteFile(cmd.getVolume().getPath() + ".vmdk", morDc, true);
+ dsMo.deleteFile(vol.getPath() + ".vmdk", morDc, true);
if (s_logger.isInfoEnabled()) {
- s_logger.info("Destroy volume by derived name: " + cmd.getVolume().getPath() + "-flat.vmdk");
+ s_logger.info("Destroy volume by derived name: " + vol.getPath() + "-flat.vmdk");
}
- dsMo.deleteFile(cmd.getVolume().getPath() + "-flat.vmdk", morDc, true);
+ dsMo.deleteFile(vol.getPath() + "-flat.vmdk", morDc, true);
}
return new Answer(cmd, true, "Success");
@@ -3815,7 +3861,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
}
}
- private void cleanupNetwork(HostMO hostMo, NetworkDetails netDetails) {
+ public void cleanupNetwork(HostMO hostMo, NetworkDetails netDetails) {
// we will no longer cleanup VLAN networks in order to support native VMware HA
/*
* assert(netDetails.getName() != null); try { synchronized(this) { NetworkMO networkMo = new
@@ -4857,7 +4903,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
return s_statesTable.get(powerState);
}
- private static State getVmState(VirtualMachineMO vmMo) throws Exception {
+ public static State getVmState(VirtualMachineMO vmMo) throws Exception {
VirtualMachineRuntimeInfo runtimeInfo = vmMo.getRuntimeInfo();
return convertState(runtimeInfo.getPowerState());
}
@@ -4991,6 +5037,13 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
} else {
_fullCloneFlag = false;
}
+ value = (String)params.get("scripts.timeout");
+ int timeout = NumbersUtil.parseInt(value, 1440) * 1000;
+ VmwareManager mgr = context.getStockObject(VmwareManager.CONTEXT_STOCK_NAME);
+ VmwareStorageProcessor storageProcessor = new VmwareStorageProcessor((VmwareHostService)this, this._fullCloneFlag, (VmwareStorageMount)mgr,
+ timeout, this, this._shutdown_waitMs
+ );
+ storageHandler = new StorageSubsystemCommandHandlerBase(storageProcessor);
return true;
}
@@ -5010,15 +5063,15 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
return true;
}
- private VmwareContext getServiceContext() {
+ public VmwareContext getServiceContext() {
return getServiceContext(null);
}
- private void invalidateServiceContext() {
+ public void invalidateServiceContext() {
invalidateServiceContext(null);
}
- private VmwareHypervisorHost getHyperHost(VmwareContext context) {
+ public VmwareHypervisorHost getHyperHost(VmwareContext context) {
return getHyperHost(context, null);
}
@@ -5115,4 +5168,10 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
// TODO Auto-generated method stub
}
+
+ @Override
+ public Answer execute(DestroyCommand cmd) {
+ // TODO Auto-generated method stub
+ return null;
+ }
}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/42e25a22/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareSecondaryStorageResourceHandler.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareSecondaryStorageResourceHandler.java b/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareSecondaryStorageResourceHandler.java
index 566e750..645b6d3 100644
--- a/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareSecondaryStorageResourceHandler.java
+++ b/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareSecondaryStorageResourceHandler.java
@@ -18,6 +18,7 @@ package com.cloud.storage.resource;
import java.util.List;
+import org.apache.cloudstack.storage.command.StorageSubSystemCommand;
import org.apache.log4j.Logger;
import com.cloud.agent.api.Answer;
@@ -29,6 +30,7 @@ import com.cloud.agent.api.CreateVolumeFromSnapshotCommand;
import com.cloud.agent.api.storage.CopyVolumeCommand;
import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand;
import com.cloud.hypervisor.vmware.manager.VmwareHostService;
+import com.cloud.hypervisor.vmware.manager.VmwareManager;
import com.cloud.hypervisor.vmware.manager.VmwareStorageManager;
import com.cloud.hypervisor.vmware.manager.VmwareStorageManagerImpl;
import com.cloud.hypervisor.vmware.manager.VmwareStorageMount;
@@ -51,6 +53,7 @@ public class VmwareSecondaryStorageResourceHandler implements SecondaryStorageRe
private final VmwareStorageManager _storageMgr;
private final Gson _gson;
+ private StorageSubsystemCommandHandler storageSubsystemHandler;
/*
private Map<String, HostMO> _activeHosts = new HashMap<String, HostMO>();
@@ -60,6 +63,11 @@ public class VmwareSecondaryStorageResourceHandler implements SecondaryStorageRe
_resource = resource;
_storageMgr = new VmwareStorageManagerImpl(this);
_gson = GsonHelper.getGsonLogger();
+
+ VmwareStorageProcessor storageProcessor = new VmwareStorageProcessor((VmwareHostService)this, true, (VmwareStorageMount)this,
+ null, null, null
+ );
+ storageSubsystemHandler = new StorageSubsystemCommandHandlerBase(storageProcessor);
}
@Override
@@ -77,6 +85,8 @@ public class VmwareSecondaryStorageResourceHandler implements SecondaryStorageRe
answer = execute((CopyVolumeCommand)cmd);
} else if(cmd instanceof CreateVolumeFromSnapshotCommand) {
answer = execute((CreateVolumeFromSnapshotCommand)cmd);
+ } else if (cmd instanceof StorageSubSystemCommand) {
+ answer = storageSubsystemHandler.handleStorageCommands((StorageSubSystemCommand)cmd);
} else {
answer = _resource.defaultAction(cmd);
}
[7/7] git commit: updated refs/heads/object_store to e444867
Posted by ed...@apache.org.
fix compile
Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/e444867e
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/e444867e
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/e444867e
Branch: refs/heads/object_store
Commit: e444867e619e88a68af0a06974f63ed892e8d39d
Parents: 42e25a2
Author: Edison Su <ed...@citrix.com>
Authored: Fri May 10 09:47:09 2013 -0700
Committer: Edison Su <ed...@citrix.com>
Committed: Fri May 10 09:47:09 2013 -0700
----------------------------------------------------------------------
.../storage/image/TemplateDataFactoryImpl.java | 11 ------
.../com/cloud/ovm/hypervisor/OvmResourceBase.java | 26 ++++++++++++---
.../com/cloud/hypervisor/HypervisorGuruBase.java | 3 +-
tools/marvin/marvin/deployDataCenter.py | 5 ++-
4 files changed, 26 insertions(+), 19 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e444867e/engine/storage/image/src/org/apache/cloudstack/storage/image/TemplateDataFactoryImpl.java
----------------------------------------------------------------------
diff --git a/engine/storage/image/src/org/apache/cloudstack/storage/image/TemplateDataFactoryImpl.java b/engine/storage/image/src/org/apache/cloudstack/storage/image/TemplateDataFactoryImpl.java
index 09c79b2..52c79e6 100644
--- a/engine/storage/image/src/org/apache/cloudstack/storage/image/TemplateDataFactoryImpl.java
+++ b/engine/storage/image/src/org/apache/cloudstack/storage/image/TemplateDataFactoryImpl.java
@@ -90,17 +90,6 @@ public class TemplateDataFactoryImpl implements TemplateDataFactory {
}
return this.getTemplate(templateId, store);
}
-
- @Override
- public TemplateInfo getTemplate(long templateId, long zoneId) {
- TemplateDataStoreVO tmplStore = templateStoreDao.findByTemplateZoneDownloadStatus(templateId, zoneId, VMTemplateStorageResourceAssoc.Status.DOWNLOADED);
- if (tmplStore != null) {
- DataStore store = this.storeMgr.getDataStore(tmplStore.getDataStoreId(), DataStoreRole.Image);
- return this.getTemplate(templateId, store);
- }
- return null;
- }
-
@Override
public TemplateInfo getTemplate(long templateId, DataStoreRole storeRole, Long zoneId) {
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e444867e/plugins/hypervisors/ovm/src/com/cloud/ovm/hypervisor/OvmResourceBase.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/ovm/src/com/cloud/ovm/hypervisor/OvmResourceBase.java b/plugins/hypervisors/ovm/src/com/cloud/ovm/hypervisor/OvmResourceBase.java
index 7d8d90c..61ac54e 100755
--- a/plugins/hypervisors/ovm/src/com/cloud/ovm/hypervisor/OvmResourceBase.java
+++ b/plugins/hypervisors/ovm/src/com/cloud/ovm/hypervisor/OvmResourceBase.java
@@ -29,6 +29,8 @@ import java.util.concurrent.ConcurrentHashMap;
import javax.naming.ConfigurationException;
+import org.apache.cloudstack.storage.to.TemplateObjectTO;
+import org.apache.cloudstack.storage.to.VolumeObjectTO;
import org.apache.log4j.Logger;
import org.apache.xmlrpc.XmlRpcException;
@@ -90,6 +92,10 @@ import com.cloud.agent.api.storage.CreatePrivateTemplateAnswer;
import com.cloud.agent.api.storage.DestroyCommand;
import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer;
import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand;
+import com.cloud.agent.api.to.DataStoreTO;
+import com.cloud.agent.api.to.DataTO;
+import com.cloud.agent.api.to.DiskTO;
+import com.cloud.agent.api.to.NfsTO;
import com.cloud.agent.api.to.NicTO;
import com.cloud.agent.api.to.StorageFilerTO;
import com.cloud.agent.api.to.VirtualMachineTO;
@@ -527,25 +533,35 @@ public class OvmResourceBase implements ServerResource, HypervisorResource {
}
protected void createVbds(OvmVm.Details vm, VirtualMachineTO spec) throws URISyntaxException {
- for (VolumeTO volume : spec.getDisks()) {
+ for (DiskTO volume : spec.getDisks()) {
if (volume.getType() == Volume.Type.ROOT) {
+ VolumeObjectTO vol = (VolumeObjectTO)volume.getData();
OvmDisk.Details root = new OvmDisk.Details();
- root.path = volume.getPath();
+ root.path = vol.getPath();
root.type = OvmDisk.WRITE;
root.isIso = false;
vm.rootDisk = root;
} else if (volume.getType() == Volume.Type.ISO) {
- if (volume.getPath() != null) {
+ DataTO isoTO = volume.getData();
+ if (isoTO.getPath() != null) {
+ TemplateObjectTO template = (TemplateObjectTO)isoTO;
+ DataStoreTO store = template.getDataStore();
+ if (!(store instanceof NfsTO)) {
+ throw new CloudRuntimeException("unsupported protocol");
+ }
+ NfsTO nfsStore = (NfsTO)store;
+ String isoPath = nfsStore.getUrl() + File.separator + template.getPath();
OvmDisk.Details iso = new OvmDisk.Details();
- URI path = new URI(volume.getPath());
+ URI path = new URI(isoPath);
iso.path = path.getHost() + ":" + path.getPath();
iso.type = OvmDisk.READ;
iso.isIso = true;
vm.disks.add(iso);
}
} else if (volume.getType() == Volume.Type.DATADISK){
+
OvmDisk.Details data = new OvmDisk.Details();
- data.path = volume.getPath();
+ data.path = volume.getData().getPath();
data.type = OvmDisk.SHAREDWRITE;
data.isIso = false;
vm.disks.add(data);
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e444867e/server/src/com/cloud/hypervisor/HypervisorGuruBase.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/hypervisor/HypervisorGuruBase.java b/server/src/com/cloud/hypervisor/HypervisorGuruBase.java
index 2300953..e11aa50 100644
--- a/server/src/com/cloud/hypervisor/HypervisorGuruBase.java
+++ b/server/src/com/cloud/hypervisor/HypervisorGuruBase.java
@@ -23,6 +23,7 @@ import javax.inject.Inject;
import com.cloud.agent.api.Command;
import com.cloud.agent.api.to.DataTO;
+import com.cloud.agent.api.to.DiskTO;
import com.cloud.agent.api.to.NicTO;
import com.cloud.agent.api.to.VirtualMachineTO;
import com.cloud.agent.api.to.VolumeTO;
@@ -102,7 +103,7 @@ public abstract class HypervisorGuruBase extends AdapterBase implements Hypervis
}
to.setNics(nics);
- to.setDisks(vmProfile.getDisks().toArray(new DataTO[vmProfile.getDisks().size()]));
+ to.setDisks(vmProfile.getDisks().toArray(new DiskTO[vmProfile.getDisks().size()]));
if(vmProfile.getTemplate().getBits() == 32) {
to.setArch("i686");
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e444867e/tools/marvin/marvin/deployDataCenter.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/deployDataCenter.py b/tools/marvin/marvin/deployDataCenter.py
index 164af74..956d2bc 100644
--- a/tools/marvin/marvin/deployDataCenter.py
+++ b/tools/marvin/marvin/deployDataCenter.py
@@ -142,8 +142,9 @@ class deployDataCenters():
secondarycmd.url = secondary.url
secondarycmd.provider = secondary.providerName
secondarycmd.details = []
- for item in secondary.details:
- secondarycmd.details.append(item.__dict__)
+ if secondary.providerName != "NFS":
+ for item in secondary.details:
+ secondarycmd.details.append(item.__dict__)
if secondarycmd.provider == "NFS":
secondarycmd.zoneid = zoneId
self.apiClient.addImageStore(secondarycmd)