DataStore Clusters addition as a storage pool

This commit is contained in:
Harikrishna Patnala 2020-07-13 22:14:01 +05:30
parent c45b83a158
commit 48786b2d31
11 changed files with 305 additions and 123 deletions

View File

@ -16,11 +16,11 @@
// under the License.
package com.cloud.storage;
import org.apache.commons.lang.NotImplementedException;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang.NotImplementedException;
public class Storage {
public static enum ImageFormat {
QCOW2(true, true, false, "qcow2"),
@ -135,7 +135,8 @@ public class Storage {
OCFS2(true, false),
SMB(true, false),
Gluster(true, false),
ManagedNFS(true, false);
ManagedNFS(true, false),
DatastoreCluster(true, true); // for VMware, to abstract pool of clusters
private final boolean shared;
private final boolean overprovisioning;

View File

@ -45,6 +45,7 @@ public class StorageTest {
Assert.assertTrue(StoragePoolType.SMB.isShared());
Assert.assertTrue(StoragePoolType.Gluster.isShared());
Assert.assertTrue(StoragePoolType.ManagedNFS.isShared());
Assert.assertTrue(StoragePoolType.DatastoreCluster.isShared());
}
@Test
@ -66,5 +67,6 @@ public class StorageTest {
Assert.assertFalse(StoragePoolType.SMB.supportsOverProvisioning());
Assert.assertFalse(StoragePoolType.Gluster.supportsOverProvisioning());
Assert.assertFalse(StoragePoolType.ManagedNFS.supportsOverProvisioning());
Assert.assertFalse(StoragePoolType.DatastoreCluster.supportsOverProvisioning());
}
}

View File

@ -18,20 +18,6 @@
*/
package org.apache.cloudstack.storage.datastore.provider;
import java.util.List;
import javax.inject.Inject;
import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailVO;
import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailsDao;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
import org.apache.cloudstack.engine.subsystem.api.storage.HypervisorHostListener;
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
import com.cloud.agent.AgentManager;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.ModifyStoragePoolAnswer;
@ -43,6 +29,17 @@ import com.cloud.storage.StoragePool;
import com.cloud.storage.StoragePoolHostVO;
import com.cloud.storage.dao.StoragePoolHostDao;
import com.cloud.utils.exception.CloudRuntimeException;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
import org.apache.cloudstack.engine.subsystem.api.storage.HypervisorHostListener;
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailVO;
import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailsDao;
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import javax.inject.Inject;
import java.util.List;
public class DefaultHostListener implements HypervisorHostListener {
private static final Logger s_logger = Logger.getLogger(DefaultHostListener.class);
@ -108,8 +105,11 @@ public class DefaultHostListener implements HypervisorHostListener {
poolVO.setUsedBytes(mspAnswer.getPoolInfo().getCapacityBytes() - mspAnswer.getPoolInfo().getAvailableBytes());
poolVO.setCapacityBytes(mspAnswer.getPoolInfo().getCapacityBytes());
if(StringUtils.isNotEmpty(mspAnswer.getPoolType())) {
StoragePoolDetailVO storagePoolDetailVO = new StoragePoolDetailVO(poolId, "pool_type", mspAnswer.getPoolType(), false);
storagePoolDetailsDao.persist(storagePoolDetailVO);
StoragePoolDetailVO poolType = storagePoolDetailsDao.findDetail(poolId, "pool_type");
if (poolType == null) {
StoragePoolDetailVO storagePoolDetailVO = new StoragePoolDetailVO(poolId, "pool_type", mspAnswer.getPoolType(), false);
storagePoolDetailsDao.persist(storagePoolDetailVO);
}
}
primaryStoreDao.update(pool.getId(), poolVO);

View File

@ -16,50 +16,9 @@
// under the License.
package com.cloud.hypervisor.vmware.resource;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.ConnectException;
import java.net.InetSocketAddress;
import java.net.URI;
import java.net.URL;
import java.nio.channels.SocketChannel;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.TimeZone;
import java.util.UUID;
import javax.naming.ConfigurationException;
import javax.xml.datatype.XMLGregorianCalendar;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.storage.command.CopyCommand;
import org.apache.cloudstack.storage.command.StorageSubSystemCommand;
import org.apache.cloudstack.storage.configdrive.ConfigDrive;
import org.apache.cloudstack.storage.resource.NfsSecondaryStorageResource;
import org.apache.cloudstack.storage.to.PrimaryDataStoreTO;
import org.apache.cloudstack.storage.to.TemplateObjectTO;
import org.apache.cloudstack.storage.to.VolumeObjectTO;
import org.apache.cloudstack.utils.volume.VirtualMachineDiskInfo;
import org.apache.cloudstack.vm.UnmanagedInstanceTO;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.apache.log4j.Logger;
import org.apache.log4j.NDC;
import org.joda.time.Duration;
import com.cloud.agent.IAgentControl;
import com.cloud.agent.api.Answer;
@ -297,6 +256,7 @@ import com.vmware.vim25.PerfMetricIntSeries;
import com.vmware.vim25.PerfMetricSeries;
import com.vmware.vim25.PerfQuerySpec;
import com.vmware.vim25.RuntimeFaultFaultMsg;
import com.vmware.vim25.StoragePodSummary;
import com.vmware.vim25.ToolsUnavailableFaultMsg;
import com.vmware.vim25.VAppOvfSectionInfo;
import com.vmware.vim25.VAppOvfSectionSpec;
@ -340,6 +300,46 @@ import com.vmware.vim25.VmConfigSpec;
import com.vmware.vim25.VmfsDatastoreInfo;
import com.vmware.vim25.VmwareDistributedVirtualSwitchPvlanSpec;
import com.vmware.vim25.VmwareDistributedVirtualSwitchVlanIdSpec;
import org.apache.cloudstack.storage.command.CopyCommand;
import org.apache.cloudstack.storage.command.StorageSubSystemCommand;
import org.apache.cloudstack.storage.resource.NfsSecondaryStorageResource;
import org.apache.cloudstack.storage.to.PrimaryDataStoreTO;
import org.apache.cloudstack.storage.to.VolumeObjectTO;
import org.apache.cloudstack.utils.volume.VirtualMachineDiskInfo;
import org.apache.cloudstack.vm.UnmanagedInstanceTO;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.apache.log4j.Logger;
import org.apache.log4j.NDC;
import org.joda.time.Duration;
import javax.naming.ConfigurationException;
import javax.xml.datatype.XMLGregorianCalendar;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.ConnectException;
import java.net.InetSocketAddress;
import java.net.URI;
import java.net.URL;
import java.nio.channels.SocketChannel;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.TimeZone;
import java.util.UUID;
import static com.cloud.utils.HumanReadableJson.getHumanReadableBytesJson;
import static com.cloud.utils.NumbersUtil.toHumanReadableSize;
@ -4901,7 +4901,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
VmwareHypervisorHost hyperHost = getHyperHost(getServiceContext());
StorageFilerTO pool = cmd.getPool();
if (pool.getType() != StoragePoolType.NetworkFilesystem && pool.getType() != StoragePoolType.VMFS && pool.getType() != StoragePoolType.PreSetup) {
if (pool.getType() != StoragePoolType.NetworkFilesystem && pool.getType() != StoragePoolType.VMFS && pool.getType() != StoragePoolType.PreSetup && pool.getType() != StoragePoolType.DatastoreCluster) {
throw new Exception("Unsupported storage pool type " + pool.getType());
}
@ -4914,16 +4914,24 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
assert (morDatastore != null);
DatastoreMO dsMo = new DatastoreMO(getServiceContext(), morDatastore);
HypervisorHostHelper.createBaseFolderInDatastore(dsMo, hyperHost);
HypervisorHostHelper.createBaseFolder(dsMo, hyperHost, pool.getType());
DatastoreSummary summary = dsMo.getSummary();
long capacity = summary.getCapacity();
long available = summary.getFreeSpace();
long capacity = 0;
long available = 0;
if (pool.getType() == StoragePoolType.DatastoreCluster) {
StoragePodSummary summary = dsMo.getDatastoreClusterSummary();
capacity = summary.getCapacity();
available = summary.getFreeSpace();
} else {
DatastoreSummary summary = dsMo.getDatastoreSummary();
capacity = summary.getCapacity();
available = summary.getFreeSpace();
}
Map<String, TemplateProp> tInfo = new HashMap<>();
ModifyStoragePoolAnswer answer = new ModifyStoragePoolAnswer(cmd, capacity, available, tInfo);
if (cmd.getAdd() && (pool.getType() == StoragePoolType.VMFS || pool.getType() == StoragePoolType.PreSetup)) {
if (cmd.getAdd() && (pool.getType() == StoragePoolType.VMFS || pool.getType() == StoragePoolType.PreSetup) && pool.getType() != StoragePoolType.DatastoreCluster) {
answer.setPoolType(dsMo.getDatastoreType());
answer.setLocalDatastoreName(morDatastore.getValue());
}
@ -5305,11 +5313,18 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
if (morDs != null) {
DatastoreMO datastoreMo = new DatastoreMO(context, morDs);
DatastoreSummary summary = datastoreMo.getSummary();
assert (summary != null);
long capacity = 0;
long free = 0;
if (cmd.getPooltype() == StoragePoolType.DatastoreCluster) {
StoragePodSummary summary = datastoreMo.getDatastoreClusterSummary();
capacity = summary.getCapacity();
free = summary.getFreeSpace();
} else {
DatastoreSummary summary = datastoreMo.getDatastoreSummary();
capacity = summary.getCapacity();
free = summary.getFreeSpace();
}
long capacity = summary.getCapacity();
long free = summary.getFreeSpace();
long used = capacity - free;
if (s_logger.isDebugEnabled()) {
@ -5317,7 +5332,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
+ ", capacity: " + toHumanReadableSize(capacity) + ", free: " + toHumanReadableSize(free) + ", used: " + toHumanReadableSize(used));
}
if (summary.getCapacity() <= 0) {
if (capacity <= 0) {
s_logger.warn("Something is wrong with vSphere NFS datastore, rebooting ESX(ESXi) host should help");
}
@ -5839,7 +5854,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
dsMo.setCustomFieldValue(CustomFieldConstants.CLOUD_UUID, poolUuid);
}
DatastoreSummary dsSummary = dsMo.getSummary();
DatastoreSummary dsSummary = dsMo.getDatastoreSummary();
String address = hostMo.getHostName();
StoragePoolInfo pInfo = new StoragePoolInfo(poolUuid, address, dsMo.getMor().getValue(), "", StoragePoolType.VMFS, dsSummary.getCapacity(),
dsSummary.getFreeSpace());
@ -6555,6 +6570,8 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
CustomFieldsManagerMO cfmMo = new CustomFieldsManagerMO(context, context.getServiceContent().getCustomFieldsManager());
cfmMo.ensureCustomFieldDef("Datastore", CustomFieldConstants.CLOUD_UUID);
cfmMo.ensureCustomFieldDef("StoragePod", CustomFieldConstants.CLOUD_UUID);
if (_publicTrafficInfo != null && _publicTrafficInfo.getVirtualSwitchType() != VirtualSwitchType.StandardVirtualSwitch
|| _guestTrafficInfo != null && _guestTrafficInfo.getVirtualSwitchType() != VirtualSwitchType.StandardVirtualSwitch) {
cfmMo.ensureCustomFieldDef("DistributedVirtualPortgroup", CustomFieldConstants.CLOUD_GC_DVP);

View File

@ -2962,7 +2962,7 @@ public class VmwareStorageProcessor implements StorageProcessor {
throw new Exception("Unable to create a dummy VM for volume creation");
}
Long volumeSizeToUse = volumeSize < dsMo.getSummary().getFreeSpace() ? volumeSize : dsMo.getSummary().getFreeSpace();
Long volumeSizeToUse = volumeSize < dsMo.getDatastoreSummary().getFreeSpace() ? volumeSize : dsMo.getDatastoreSummary().getFreeSpace();
vmMo.createDisk(vmdkDatastorePath, getMBsFromBytes(volumeSizeToUse), dsMo.getMor(), vmMo.getScsiDeviceControllerKey());
vmMo.detachDisk(vmdkDatastorePath, false);

View File

@ -18,32 +18,6 @@
*/
package org.apache.cloudstack.storage.datastore.lifecycle;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import javax.inject.Inject;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.apache.cloudstack.engine.subsystem.api.storage.ClusterScope;
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.HostScope;
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreLifeCycle;
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreParameters;
import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope;
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
import org.apache.cloudstack.storage.volume.datastore.PrimaryDataStoreHelper;
import com.cloud.agent.AgentManager;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.CreateStoragePoolCommand;
@ -78,6 +52,29 @@ 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 org.apache.cloudstack.engine.subsystem.api.storage.ClusterScope;
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.HostScope;
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreLifeCycle;
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreParameters;
import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope;
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
import org.apache.cloudstack.storage.volume.datastore.PrimaryDataStoreHelper;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import javax.inject.Inject;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
public class CloudStackPrimaryDataStoreLifeCycleImpl implements PrimaryDataStoreLifeCycle {
private static final Logger s_logger = Logger.getLogger(CloudStackPrimaryDataStoreLifeCycleImpl.class);
@ -256,6 +253,11 @@ public class CloudStackPrimaryDataStoreLifeCycleImpl implements PrimaryDataStore
parameters.setHost(storageHost);
parameters.setPort(0);
parameters.setPath(hostPath);
} else if (scheme.equalsIgnoreCase("DatastoreCluster")) {
parameters.setType(StoragePoolType.DatastoreCluster);
parameters.setHost(storageHost);
parameters.setPort(0);
parameters.setPath(hostPath);
} else if (scheme.equalsIgnoreCase("iscsi")) {
String[] tokens = hostPath.split("/");
int lun = NumbersUtil.parseInt(tokens[tokens.length - 1], -1);
@ -360,7 +362,7 @@ public class CloudStackPrimaryDataStoreLifeCycleImpl implements PrimaryDataStore
if (pool.getPoolType() != StoragePoolType.NetworkFilesystem && pool.getPoolType() != StoragePoolType.Filesystem &&
pool.getPoolType() != StoragePoolType.IscsiLUN && pool.getPoolType() != StoragePoolType.Iscsi && pool.getPoolType() != StoragePoolType.VMFS &&
pool.getPoolType() != StoragePoolType.SharedMountPoint && pool.getPoolType() != StoragePoolType.PreSetup && pool.getPoolType() != StoragePoolType.OCFS2 &&
pool.getPoolType() != StoragePoolType.SharedMountPoint && pool.getPoolType() != StoragePoolType.PreSetup && pool.getPoolType() != StoragePoolType.DatastoreCluster && pool.getPoolType() != StoragePoolType.OCFS2 &&
pool.getPoolType() != StoragePoolType.RBD && pool.getPoolType() != StoragePoolType.CLVM && pool.getPoolType() != StoragePoolType.SMB &&
pool.getPoolType() != StoragePoolType.Gluster) {
s_logger.warn(" Doesn't support storage pool type " + pool.getPoolType());

View File

@ -16,12 +16,10 @@
// under the License.
package com.cloud.hypervisor.vmware.mo;
import java.util.ArrayList;
import java.util.List;
import com.cloud.exception.CloudException;
import com.cloud.hypervisor.vmware.util.VmwareContext;
import com.cloud.utils.Pair;
import com.vmware.pbm.PbmProfile;
import org.apache.log4j.Logger;
import com.vmware.vim25.DatastoreHostMount;
import com.vmware.vim25.DatastoreSummary;
import com.vmware.vim25.FileInfo;
@ -35,11 +33,12 @@ import com.vmware.vim25.ObjectSpec;
import com.vmware.vim25.PropertyFilterSpec;
import com.vmware.vim25.PropertySpec;
import com.vmware.vim25.SelectionSpec;
import com.vmware.vim25.StoragePodSummary;
import com.vmware.vim25.TraversalSpec;
import org.apache.log4j.Logger;
import com.cloud.exception.CloudException;
import com.cloud.hypervisor.vmware.util.VmwareContext;
import com.cloud.utils.Pair;
import java.util.ArrayList;
import java.util.List;
import static com.cloud.utils.NumbersUtil.toHumanReadableSize;
@ -65,10 +64,14 @@ public class DatastoreMO extends BaseMO {
return _name;
}
public DatastoreSummary getSummary() throws Exception {
public DatastoreSummary getDatastoreSummary() throws Exception {
return (DatastoreSummary)_context.getVimClient().getDynamicProperty(_mor, "summary");
}
public StoragePodSummary getDatastoreClusterSummary() throws Exception {
return (StoragePodSummary)_context.getVimClient().getDynamicProperty(_mor, "summary");
}
public HostDatastoreBrowserMO getHostDatastoreBrowserMO() throws Exception {
return new HostDatastoreBrowserMO(_context, (ManagedObjectReference)_context.getVimClient().getDynamicProperty(_mor, "browser"));
}

View File

@ -16,11 +16,7 @@
// under the License.
package com.cloud.hypervisor.vmware.mo;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import com.cloud.hypervisor.vmware.util.VmwareContext;
import com.vmware.vim25.CustomFieldStringValue;
import com.vmware.vim25.DatastoreInfo;
import com.vmware.vim25.DynamicProperty;
@ -35,12 +31,18 @@ import com.vmware.vim25.ObjectContent;
import com.vmware.vim25.ObjectSpec;
import com.vmware.vim25.PropertyFilterSpec;
import com.vmware.vim25.PropertySpec;
import com.vmware.vim25.RetrieveOptions;
import com.vmware.vim25.RetrieveResult;
import com.vmware.vim25.SelectionSpec;
import com.vmware.vim25.TraversalSpec;
import com.vmware.vim25.VmfsDatastoreCreateSpec;
import com.vmware.vim25.VmfsDatastoreExpandSpec;
import com.vmware.vim25.VmfsDatastoreOption;
import com.cloud.hypervisor.vmware.util.VmwareContext;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class HostDatastoreSystemMO extends BaseMO {
@ -53,6 +55,14 @@ public class HostDatastoreSystemMO extends BaseMO {
}
public ManagedObjectReference findDatastore(String name) throws Exception {
ManagedObjectReference morDatastore = findSpecificDatastore(name);
if (morDatastore == null) {
morDatastore = findDatastoreCluster(name);
}
return morDatastore;
}
public ManagedObjectReference findSpecificDatastore(String name) throws Exception {
// added Apache CloudStack specific name convention, we will use custom field "cloud.uuid" as datastore name as well
CustomFieldsManagerMO cfmMo = new CustomFieldsManagerMO(_context, _context.getServiceContent().getCustomFieldsManager());
int key = cfmMo.getCustomFieldKey("Datastore", CustomFieldConstants.CLOUD_UUID);
@ -79,6 +89,33 @@ public class HostDatastoreSystemMO extends BaseMO {
return null;
}
public ManagedObjectReference findDatastoreCluster(String name) throws Exception {
// added Apache CloudStack specific name convention, we will use custom field "cloud.uuid" as datastore name as well
CustomFieldsManagerMO cfmMo = new CustomFieldsManagerMO(_context, _context.getServiceContent().getCustomFieldsManager());
int key = cfmMo.getCustomFieldKey("StoragePod", CustomFieldConstants.CLOUD_UUID);
assert (key != 0);
List<ObjectContent> ocs = getDatastoreClusterPropertiesOnHostDatastoreSystem(new String[] {"name", String.format("value[%d]", key)});
if (ocs != null) {
for (ObjectContent oc : ocs) {
if (oc.getPropSet().get(0).getVal().equals(name))
return oc.getObj();
if (oc.getPropSet().size() > 1) {
DynamicProperty prop = oc.getPropSet().get(1);
if (prop != null && prop.getVal() != null) {
if (prop.getVal() instanceof CustomFieldStringValue) {
String val = ((CustomFieldStringValue)prop.getVal()).getValue();
if (val.equalsIgnoreCase(name))
return oc.getObj();
}
}
}
}
}
return null;
}
public List<HostUnresolvedVmfsVolume> queryUnresolvedVmfsVolumes() throws Exception {
return _context.getService().queryUnresolvedVmfsVolumes(_mor);
}
@ -251,4 +288,90 @@ public class HostDatastoreSystemMO extends BaseMO {
return _context.getService().retrieveProperties(_context.getPropertyCollector(), pfSpecArr);
}
public List<ObjectContent> getDatastoreClusterPropertiesOnHostDatastoreSystem(String[] propertyPaths) throws Exception {
ManagedObjectReference retVal = null;
// Create Property Spec
PropertySpec propertySpec = new PropertySpec();
propertySpec.setAll(Boolean.FALSE);
propertySpec.setType("StoragePod");
propertySpec.getPathSet().addAll(Arrays.asList(propertyPaths));
// Now create Object Spec
ObjectSpec objectSpec = new ObjectSpec();
objectSpec.setObj(getContext().getRootFolder());
objectSpec.setSkip(Boolean.TRUE);
objectSpec.getSelectSet().addAll(
Arrays.asList(getStorageTraversalSpec()));
// Create PropertyFilterSpec using the PropertySpec and ObjectPec
// created above.
PropertyFilterSpec propertyFilterSpec = new PropertyFilterSpec();
propertyFilterSpec.getPropSet().add(propertySpec);
propertyFilterSpec.getObjectSet().add(objectSpec);
List<PropertyFilterSpec> listpfs = new ArrayList<PropertyFilterSpec>();
listpfs.add(propertyFilterSpec);
return retrievePropertiesAllObjects(listpfs);
}
private SelectionSpec[] getStorageTraversalSpec() {
// create a traversal spec that start from root folder
SelectionSpec ssFolders = new SelectionSpec();
ssFolders.setName("visitFolders");
TraversalSpec datacenterSpec = new TraversalSpec();
datacenterSpec.setName("dcTodf");
datacenterSpec.setType("Datacenter");
datacenterSpec.setPath("datastoreFolder");
datacenterSpec.setSkip(Boolean.FALSE);
datacenterSpec.getSelectSet().add(ssFolders);
TraversalSpec visitFolder = new TraversalSpec();
visitFolder.setType("Folder");
visitFolder.setName("visitFolders");
visitFolder.setPath("childEntity");
visitFolder.setSkip(Boolean.FALSE);
List<SelectionSpec> ssSpecList = new ArrayList<SelectionSpec>();
ssSpecList.add(datacenterSpec);
ssSpecList.add(ssFolders);
visitFolder.getSelectSet().addAll(ssSpecList);
return (new SelectionSpec[]{visitFolder});
}
private List<ObjectContent> retrievePropertiesAllObjects(
List<PropertyFilterSpec> listpfs) throws Exception {
RetrieveOptions propObjectRetrieveOpts = new RetrieveOptions();
List<ObjectContent> listobjcontent = new ArrayList<ObjectContent>();
RetrieveResult rslts =
getContext().getService().retrievePropertiesEx(getContext().getServiceContent().getPropertyCollector(), listpfs,
propObjectRetrieveOpts);
if (rslts != null && rslts.getObjects() != null
&& !rslts.getObjects().isEmpty()) {
listobjcontent.addAll(rslts.getObjects());
}
String token = null;
if (rslts != null && rslts.getToken() != null) {
token = rslts.getToken();
}
while (token != null && !token.isEmpty()) {
rslts =
getContext().getService().continueRetrievePropertiesEx(getContext().getServiceContent().getPropertyCollector(), token);
token = null;
if (rslts != null) {
token = rslts.getToken();
if (rslts.getObjects() != null && !rslts.getObjects().isEmpty()) {
listobjcontent.addAll(rslts.getObjects());
}
}
}
return listobjcontent;
}
}

View File

@ -28,6 +28,7 @@ import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import com.cloud.storage.Storage;
import com.google.gson.Gson;
import com.vmware.vim25.AboutInfo;
import com.vmware.vim25.AlreadyExistsFaultMsg;
@ -873,12 +874,15 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost {
} else {
morDatastore = _context.getDatastoreMorByPath(poolPath);
if (morDatastore == null) {
String msg = "Unable to create VMFS datastore. host: " + poolHostAddress + ", port: " + poolHostPort + ", path: " + poolPath + ", uuid: " + poolUuid;
s_logger.error(msg);
morDatastore = findDatastore(_context.getDatastoreNameFromPath(poolPath));
if (morDatastore == null) {
String msg = "Unable to create VMFS datastore. host: " + poolHostAddress + ", port: " + poolHostPort + ", path: " + poolPath + ", uuid: " + poolUuid;
s_logger.error(msg);
if (s_logger.isTraceEnabled())
s_logger.trace("vCenter API trace - mountDatastore() done(failed)");
throw new Exception(msg);
if (s_logger.isTraceEnabled())
s_logger.trace("vCenter API trace - mountDatastore() done(failed)");
throw new Exception(msg);
}
}
dsMo = new DatastoreMO(_context, morDatastore);
@ -887,7 +891,7 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost {
}
if (dsMo != null) {
HypervisorHostHelper.createBaseFolderInDatastore(dsMo, this);
HypervisorHostHelper.createBaseFolder(dsMo, this, "StoragePod".equals(morDatastore.getType()) ? Storage.StoragePoolType.DatastoreCluster: null);
}
if (s_logger.isTraceEnabled())

View File

@ -54,6 +54,7 @@ import com.cloud.hypervisor.vmware.util.VmwareContext;
import com.cloud.hypervisor.vmware.util.VmwareHelper;
import com.cloud.network.Networks.BroadcastDomainType;
import com.cloud.offering.NetworkOffering;
import com.cloud.storage.Storage.StoragePoolType;
import com.cloud.utils.ActionDelegate;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.Pair;
@ -172,7 +173,6 @@ public class HypervisorHostHelper {
if (morDs == null)
morDs = hyperHost.findDatastore(uuidName);
DatastoreMO dsMo = new DatastoreMO(hyperHost.getContext(), morDs);
return morDs;
}
@ -2086,7 +2086,19 @@ public class HypervisorHostHelper {
return DiskControllerType.getType(controller) == DiskControllerType.ide;
}
public static void createBaseFolderInDatastore(DatastoreMO dsMo, VmwareHypervisorHost hyperHost) throws Exception {
public static void createBaseFolder(DatastoreMO dsMo, VmwareHypervisorHost hyperHost, StoragePoolType poolType) throws Exception {
if (poolType != null && poolType == StoragePoolType.DatastoreCluster) {
List<ManagedObjectReference> datastoresInCluster = hyperHost.getContext().getVimClient().getDynamicProperty(dsMo.getMor(), "childEntity");
for (ManagedObjectReference datastore : datastoresInCluster) {
DatastoreMO childDsMo = new DatastoreMO(hyperHost.getContext(), datastore);
createBaseFolderInDatastore(childDsMo, hyperHost);
}
} else {
createBaseFolderInDatastore(dsMo, hyperHost);
}
}
private static void createBaseFolderInDatastore(DatastoreMO dsMo, VmwareHypervisorHost hyperHost) throws Exception {
String dsPath = String.format("[%s]", dsMo.getName());
String folderPath = String.format("[%s] %s", dsMo.getName(), VSPHERE_DATASTORE_BASE_FOLDER);

View File

@ -321,6 +321,24 @@ public class VmwareContext {
return dcMo.findDatastore(tokens[1]);
}
// path in format of <datacenter name>/<datastore name>
public String getDatastoreNameFromPath(String inventoryPath) throws Exception {
assert (inventoryPath != null);
String[] tokens;
if (inventoryPath.startsWith("/"))
tokens = inventoryPath.substring(1).split("/");
else
tokens = inventoryPath.split("/");
if (tokens == null || tokens.length != 2) {
s_logger.error("Invalid datastore inventory path. path: " + inventoryPath);
return null;
}
return tokens[1];
}
public void waitForTaskProgressDone(ManagedObjectReference morTask) throws Exception {
while (true) {
TaskInfo tinfo = (TaskInfo)_vimClient.getDynamicProperty(morTask, "info");